diff options
author | djl <none@none> | 2008-03-25 10:48:32 -0700 |
---|---|---|
committer | djl <none@none> | 2008-03-25 10:48:32 -0700 |
commit | 6dd841390b98241b22857b3e09e7720492884621 (patch) | |
tree | be6f8ab1236c4a9768790c5c1a319b60bdbb9bda /usr/src | |
parent | 80252d54f78e0c9d6807f9faa20fb7bd5cdc6956 (diff) | |
download | illumos-joyent-6dd841390b98241b22857b3e09e7720492884621.tar.gz |
6564720 Large groups bug still in this release
6662929 getusernam(3secdb) and friends return null when the selected /etc/user_attr line is > 1024
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/lib/libc/port/gen/getgrnam.c | 59 | ||||
-rw-r--r-- | usr/src/lib/libc/port/gen/nss_common.c | 137 | ||||
-rw-r--r-- | usr/src/lib/libc/port/gen/sysconf.c | 7 | ||||
-rw-r--r-- | usr/src/lib/nsswitch/files/common/files_common.c | 30 |
4 files changed, 154 insertions, 79 deletions
diff --git a/usr/src/lib/libc/port/gen/getgrnam.c b/usr/src/lib/libc/port/gen/getgrnam.c index e2fa0c0ed3..5080bd2ac0 100644 --- a/usr/src/lib/libc/port/gen/getgrnam.c +++ b/usr/src/lib/libc/port/gen/getgrnam.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -46,6 +45,8 @@ #ifdef NSS_INCLUDE_UNSAFE +extern size_t _nss_get_bufsizes(int arg); + /* * Ye olde non-reentrant interface (MT-unsafe, caveat utor) */ @@ -59,40 +60,70 @@ free_grbuf(void *arg) } static nss_XbyY_buf_t * -get_grbuf() +get_grbuf(int max_buf) { nss_XbyY_buf_t **buffer = tsdalloc(_T_GRBUF, sizeof (nss_XbyY_buf_t *), free_grbuf); nss_XbyY_buf_t *b; + size_t blen; if (buffer == NULL) return (NULL); - b = NSS_XbyY_ALLOC(buffer, sizeof (struct group), NSS_BUFLEN_GROUP); + if (max_buf == 0) + blen = _nss_get_bufsizes(0); /* default size */ + else + blen = sysconf(_SC_GETGR_R_SIZE_MAX); /* max size */ + if (*buffer) { + if ((*buffer)->buflen >= blen) /* existing size fits */ + return (*buffer); + NSS_XbyY_FREE(buffer); /* existing is too small */ + } + b = NSS_XbyY_ALLOC(buffer, sizeof (struct group), blen); return (b); } struct group * getgrgid(gid_t gid) { - nss_XbyY_buf_t *b = get_grbuf(); + nss_XbyY_buf_t *b = get_grbuf(0); + struct group *ret; - return (b == NULL ? NULL : - getgrgid_r(gid, b->result, b->buffer, b->buflen)); + if (b == NULL) + return (NULL); + + ret = getgrgid_r(gid, b->result, b->buffer, b->buflen); + if (ret == NULL && errno == ERANGE) { + b = get_grbuf(1); + if (b == NULL) + return (NULL); + ret = getgrgid_r(gid, b->result, b->buffer, b->buflen); + } + return (ret); } struct group * getgrnam(const char *nam) { - nss_XbyY_buf_t *b = get_grbuf(); + nss_XbyY_buf_t *b = get_grbuf(0); + struct group *ret; - return (b == NULL ? NULL : - getgrnam_r(nam, b->result, b->buffer, b->buflen)); + if (b == NULL) + return (NULL); + + ret = getgrnam_r(nam, b->result, b->buffer, b->buflen); + if (ret == NULL && errno == ERANGE && nam != NULL) { + b = get_grbuf(1); + if (b == NULL) + return (NULL); + ret = getgrnam_r(nam, b->result, b->buffer, b->buflen); + } + return (ret); } struct group * getgrent(void) { - nss_XbyY_buf_t *b = get_grbuf(); + nss_XbyY_buf_t *b = get_grbuf(1); return (b == NULL ? NULL : getgrent_r(b->result, b->buffer, b->buflen)); @@ -101,7 +132,7 @@ getgrent(void) struct group * fgetgrent(FILE *f) { - nss_XbyY_buf_t *b = get_grbuf(); + nss_XbyY_buf_t *b = get_grbuf(1); return (b == NULL ? NULL : fgetgrent_r(f, b->result, b->buffer, b->buflen)); diff --git a/usr/src/lib/libc/port/gen/nss_common.c b/usr/src/lib/libc/port/gen/nss_common.c index f7a77e278b..056752743c 100644 --- a/usr/src/lib/libc/port/gen/nss_common.c +++ b/usr/src/lib/libc/port/gen/nss_common.c @@ -63,6 +63,22 @@ #include <getxby_door.h> /* + * configurable values for default buffer sizes + */ + +/* + * PSARC/2005/133 updated the buffering mechanisms to handle + * up to 2^64 buffering. But sets a practical limit of 512*1024. + * the expectation is the practical limit will be dynamic from + * nscd. For now, set the group limit to this value. + */ + +#define NSS_BUFLEN_PRACTICAL (512*1024) + +static size_t __nss_buflen_group = NSS_BUFLEN_PRACTICAL; +static size_t __nss_buflen_default = NSS_BUFLEN_DOOR; + +/* * policy component function interposing definitions: * nscd if so desired can interpose it's own switch functions over * the internal unlocked counterparts. This will allow nscd to replace @@ -396,7 +412,7 @@ nss_cfgcomp_get(char *name, int add) return ((nss_cfglist_t *)NULL); } (void) memset((void *)(next + nss_cfgcount), '\0', - NSS_CFG_INCR * sizeof (nss_cfglist_t)); + NSS_CFG_INCR * sizeof (nss_cfglist_t)); nss_cfgmax += NSS_CFG_INCR; nss_cfg = next; } @@ -641,12 +657,12 @@ set_option(struct option *opt, char *name, char *val) for (; opt->name; opt++) { if (strcmp(name, opt->name) == 0) { switch (opt->type) { - case OPT_STRING: + case OPT_STRING: p = libc_strdup(val); *((char **)opt->address) = p; break; - case OPT_INT: + case OPT_INT: if (strcmp(val, "") == 0) n = 1; else @@ -654,7 +670,7 @@ set_option(struct option *opt, char *name, char *val) *((int *)opt->address) = n; break; #ifdef DEBUG - case OPT_FILE: + case OPT_FILE: fp = fopen(val, "wF"); *((FILE **)opt->address) = fp; break; @@ -774,11 +790,8 @@ nss_get_backend_u(nss_db_root_t **rootpp, struct nss_db_state *s, int n_src) for (bf = s->p.finders; bf != 0; bf = bf->next) { nss_backend_constr_t c; - c = (*bf->lookup) - (bf->lookup_priv, - s->p.name, - src->lkp->service_name, - &src->finder_priv); + c = (*bf->lookup) (bf->lookup_priv, s->p.name, + src->lkp->service_name, &src->finder_priv); if (c != 0) { src->be_constr = c; src->finder = bf; @@ -794,8 +807,7 @@ nss_get_backend_u(nss_db_root_t **rootpp, struct nss_db_state *s, int n_src) if (src->n_active < s->p.max_active_per_src) { be = (*src->be_constr)(s->p.name, - src->lkp->service_name, - 0 /* === unimplemented */); + src->lkp->service_name, 0 /* === unimplemented */); if (be != 0) { src->n_active++; break; @@ -847,9 +859,9 @@ nss_put_backend_u(struct nss_db_state *s, int n_src, nss_backend_t *be) src->dormant.single = be; src->n_dormant++; } else if (src->dormant.multi != 0 || - (src->dormant.multi = - libc_malloc(s->p.max_dormant_per_src * - sizeof (nss_backend_t *))) != NULL) { + (src->dormant.multi = + libc_malloc(s->p.max_dormant_per_src * + sizeof (nss_backend_t *))) != NULL) { src->dormant.multi[src->n_dormant] = be; src->n_dormant++; } else { @@ -935,14 +947,14 @@ _nss_src_state_destr(struct nss_src_state *src, int max_dormant) if (max_dormant == 1) { if (src->n_dormant != 0) { (void) NSS_INVOKE_DBOP(src->dormant.single, - NSS_DBOP_DESTRUCTOR, 0); + NSS_DBOP_DESTRUCTOR, 0); }; } else if (src->dormant.multi != 0) { int n; for (n = 0; n < src->n_dormant; n++) { (void) NSS_INVOKE_DBOP(src->dormant.multi[n], - NSS_DBOP_DESTRUCTOR, 0); + NSS_DBOP_DESTRUCTOR, 0); } libc_free(src->dormant.multi); } @@ -985,7 +997,7 @@ _nss_db_state_destr(struct nss_db_state *s) for (n_src = 0; n_src < s->max_src; n_src++) { _nss_src_state_destr(&s->src[n_src], - s->p.max_dormant_per_src); + s->p.max_dormant_per_src); } libc_free(s->src); } @@ -1089,7 +1101,7 @@ retry_test(nss_status_t res, int n, struct __nsw_lookup_v1 *lkp) if (res == NSS_SUCCESS) { __NSW_UNPAUSE_ACTION(lkp->actions[__NSW_TRYAGAIN]); __NSW_UNPAUSE_ACTION( - lkp->actions[__NSW_NISSERVDNS_TRYAGAIN]); + lkp->actions[__NSW_NISSERVDNS_TRYAGAIN]); } return (0); } @@ -1196,20 +1208,23 @@ nss_search(nss_db_root_t *rootp, nss_db_initf_t initf, int search_fnum, /* After several tries, backoff... */ if (n_loop > no_backoff) { - if (__nss_debug_eng_loop > 1) - (void) fprintf(__nss_debug_file, - "NSS: loop: sleeping %d ...\n", - NSS_BACKOFF(n_loop, - no_backoff, max_backoff)); - - (void) sleep(NSS_BACKOFF(n_loop, + if (__nss_debug_eng_loop > 1) + (void) fprintf( + __nss_debug_file, + "NSS: loop: " + "sleeping %d ...\n", + NSS_BACKOFF(n_loop, + no_backoff, + max_backoff)); + + (void) sleep(NSS_BACKOFF(n_loop, no_backoff, max_backoff)); } if (__nss_debug_eng_loop) output_loop_diag_a(n_loop, - s->config->dbase, - s->src[n_src].lkp); + s->config->dbase, + s->src[n_src].lkp); res = (*funcp)(be, search_args); @@ -1217,9 +1232,9 @@ nss_search(nss_db_root_t *rootp, nss_db_initf_t initf, int search_fnum, n_loop++; if (__nss_debug_eng_loop) output_loop_diag_b(res, - s->src[n_src].lkp); + s->src[n_src].lkp); } while (retry_test(res, n_loop, - s->src[n_src].lkp)); + s->src[n_src].lkp)); } nss_put_backend_u(s, n_src, be); } @@ -1227,14 +1242,14 @@ nss_search(nss_db_root_t *rootp, nss_db_initf_t initf, int search_fnum, if (__NSW_ACTION_V1(s->src[n_src].lkp, res) == __NSW_RETURN) { if (__nss_debug_eng_loop) (void) fprintf(__nss_debug_file, - "NSS: '%s': return.\n", - s->config->dbase); + "NSS: '%s': return.\n", + s->config->dbase); break; } else if (__nss_debug_eng_loop) (void) fprintf(__nss_debug_file, - "NSS: '%s': continue ...\n", - s->config->dbase); + "NSS: '%s': continue ...\n", + s->config->dbase); } NSS_UNREF_UNLOCK(rootp, s); return (res); @@ -1424,7 +1439,7 @@ nss_setent_u(nss_db_root_t *rootp, nss_db_initf_t initf, } } for (n_src = 0, be = 0; n_src < s->max_src && - (be = nss_get_backend_u(&rootp, s, n_src)) == 0; n_src++) { + (be = nss_get_backend_u(&rootp, s, n_src)) == 0; n_src++) { ; } NSS_UNLOCK(rootp); @@ -1498,7 +1513,7 @@ nss_getent_u(nss_db_root_t *rootp, nss_db_initf_t initf, do { n_src++; } while (n_src < s->max_src && - (be = nss_get_backend_u(&rootp, s, n_src)) == 0); + (be = nss_get_backend_u(&rootp, s, n_src)) == 0); if (be == 0) { /* * This is the case where we failed to get the backend @@ -1706,13 +1721,13 @@ nss_pack(void *buffer, size_t bufsize, nss_db_root_t *rootp, } /* use default packer for known getXbyY ops */ ret = nss_default_key2str(bptr, blen, in, dbn, - search_fnum, &len); + search_fnum, &len); } else if (in->key2str == NULL || - (search_fnum == NSS_DBOP_GROUP_BYMEMBER && - strcmp(dbn, NSS_DBNAM_GROUP) == 0)) { + (search_fnum == NSS_DBOP_GROUP_BYMEMBER && + strcmp(dbn, NSS_DBNAM_GROUP) == 0)) { /* use default packer for known getXbyY ops */ ret = nss_default_key2str(bptr, blen, in, dbn, - search_fnum, &len); + search_fnum, &len); } else { ret = (*in->key2str)(bptr, blen, &in->key, &len); } @@ -1851,10 +1866,10 @@ nss_unpack(void *buffer, size_t bufsize, nss_db_root_t *rootp, dbn = (char *)pdbd + pdbd->o_name; fmt_type = 0; /* nss_XbyY_args_t */ if (search_fnum == NSS_DBOP_GROUP_BYMEMBER && - strcmp(dbn, NSS_DBNAM_GROUP) == 0) + strcmp(dbn, NSS_DBNAM_GROUP) == 0) fmt_type = 1; /* struct nss_groupsbymem */ else if (search_fnum == NSS_DBOP_NETGROUP_IN && - strcmp(dbn, NSS_DBNAM_NETGROUP) == 0) + strcmp(dbn, NSS_DBNAM_NETGROUP) == 0) fmt_type = 2; /* struct nss_innetgr_args */ /* if error - door's switch error */ @@ -1904,7 +1919,7 @@ nss_unpack(void *buffer, size_t bufsize, nss_db_root_t *rootp, /* process the normal cases */ /* marshall data directly into users buffer */ ret = (*in->str2ent)(buf, len, in->buf.result, in->buf.buffer, - in->buf.buflen); + in->buf.buflen); if (ret == NSS_STR_PARSE_ERANGE) { in->returnval = 0; in->returnlen = 0; @@ -1955,7 +1970,7 @@ nss_unpack_ent(void *buffer, size_t bufsize, nss_db_root_t *rootp, nptr = (nssuint_t *)((void *)((char *)buffer + pbuf->key_off)); cookie = contextp->cookie; if (cookie != NSCD_NEW_COOKIE && cookie != contextp->cookie_setent && - cookie != *nptr) { + cookie != *nptr) { /* * Should either be new, or the cookie returned by the last * setent (i.e., this is the first getent after the setent) @@ -1980,7 +1995,7 @@ nss_unpack_ent(void *buffer, size_t bufsize, nss_db_root_t *rootp, /* marshall data directly into users buffer */ ret = (*in->str2ent)(buf, len, in->buf.result, in->buf.buffer, - in->buf.buflen); + in->buf.buflen); if (ret == NSS_STR_PARSE_ERANGE) { in->returnval = 0; in->returnlen = 0; @@ -2028,7 +2043,7 @@ _nsc_search(nss_db_root_t *rootp, nss_db_initf_t initf, int search_fnum, pbuf->nsc_callnumber = NSCD_SEARCH; /* copy relevant door request info into door buffer */ status = nss_pack((void *)pbuf, bufsize, rootp, - initf, search_fnum, search_args); + initf, search_fnum, search_args); /* Packing error return error results */ if (status != NSS_SUCCESS) @@ -2055,7 +2070,7 @@ _nsc_search(nss_db_root_t *rootp, nss_db_initf_t initf, int search_fnum, /* unpack and marshall data/errors to user structure */ /* set any error conditions */ status = nss_unpack((void *)doorptr, bufsize, rootp, initf, - search_fnum, search_args); + search_fnum, search_args); /* * check if doors reallocated the memory underneath us * if they did munmap it or suffer a memory leak @@ -2116,8 +2131,7 @@ _nsc_setent_u(nss_db_root_t *rootp, nss_db_initf_t initf, } /* pack relevant setent request info into door buffer */ - status = nss_pack_ent((void *)pbuf, bufsize, rootp, - initf, contextpp); + status = nss_pack_ent((void *)pbuf, bufsize, rootp, initf, contextpp); if (status != NSS_SUCCESS) return (status); @@ -2136,7 +2150,7 @@ _nsc_setent_u(nss_db_root_t *rootp, nss_db_initf_t initf, } /* unpack returned cookie stash it away */ status = nss_unpack_ent((void *)doorptr, bufsize, rootp, - initf, contextpp, NULL); + initf, contextpp, NULL); /* save the setent cookie for later use */ contextp->cookie_setent = contextp->cookie; /* @@ -2180,8 +2194,7 @@ _nsc_getent_u(nss_db_root_t *rootp, nss_db_initf_t initf, pbuf->nsc_callnumber = NSCD_GETENT; /* pack relevant setent request info into door buffer */ - status = nss_pack_ent((void *)pbuf, bufsize, rootp, - initf, contextpp); + status = nss_pack_ent((void *)pbuf, bufsize, rootp, initf, contextpp); if (status != NSS_SUCCESS) return (status); @@ -2193,7 +2206,7 @@ _nsc_getent_u(nss_db_root_t *rootp, nss_db_initf_t initf, /* If fallback to standard nss logic (door failure) if possible */ if (status != NSS_SUCCESS) { if (status == NSS_TRYLOCAL || - contextp->cookie == NSCD_NEW_COOKIE) { + contextp->cookie == NSCD_NEW_COOKIE) { contextp->cookie = NSCD_LOCAL_COOKIE; /* init the local cookie */ @@ -2206,7 +2219,7 @@ _nsc_getent_u(nss_db_root_t *rootp, nss_db_initf_t initf, } /* check error, unpack and process results */ status = nss_unpack_ent((void *)doorptr, bufsize, rootp, - initf, contextpp, args); + initf, contextpp, args); /* * check if doors reallocated the memory underneath us * if they did munmap it or suffer a memory leak @@ -2246,8 +2259,7 @@ _nsc_endent_u(nss_db_root_t *rootp, nss_db_initf_t initf, pbuf->nsc_callnumber = NSCD_ENDENT; /* pack relevant setent request info into door buffer */ - status = nss_pack_ent((void *)pbuf, bufsize, rootp, - initf, contextpp); + status = nss_pack_ent((void *)pbuf, bufsize, rootp, initf, contextpp); if (status != NSS_SUCCESS) return (status); @@ -2276,3 +2288,18 @@ _nsc_endent_u(nss_db_root_t *rootp, nss_db_initf_t initf, contextp->cookie = NSCD_NEW_COOKIE; return (NSS_SUCCESS); } + +/* + * Internal private API to return default suggested buffer sizes + * for nsswitch API requests + */ + +size_t +_nss_get_bufsizes(int arg) +{ + switch (arg) { + case _SC_GETGR_R_SIZE_MAX: + return (__nss_buflen_group); + } + return (__nss_buflen_default); +} diff --git a/usr/src/lib/libc/port/gen/sysconf.c b/usr/src/lib/libc/port/gen/sysconf.c index f9503ce1ce..4b06010170 100644 --- a/usr/src/lib/libc/port/gen/sysconf.c +++ b/usr/src/lib/libc/port/gen/sysconf.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -48,6 +48,9 @@ #include "libc.h" #include "xpg6.h" +/* from nss_common.c */ +extern size_t _nss_get_bufsizes(int); + long sysconf(int name) { @@ -363,7 +366,7 @@ sysconf(int name) return (-1L); case _SC_GETGR_R_SIZE_MAX: - return ((long)NSS_BUFLEN_GROUP); + return ((long)_nss_get_bufsizes(_SC_GETGR_R_SIZE_MAX)); case _SC_GETPW_R_SIZE_MAX: return ((long)NSS_BUFLEN_PASSWD); diff --git a/usr/src/lib/nsswitch/files/common/files_common.c b/usr/src/lib/nsswitch/files/common/files_common.c index 0f89f25d0b..74d47f7c8c 100644 --- a/usr/src/lib/nsswitch/files/common/files_common.c +++ b/usr/src/lib/nsswitch/files/common/files_common.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Common code and structures used by name-service-switch "files" backends. @@ -150,13 +150,16 @@ _nss_files_do_all(be, args, filter, func) const char *filter; files_do_all_func_t func; { + long grlen; char *buffer; int buflen; nss_status_t res; - if (be->buf == 0 && - (be->buf = malloc(be->minbuf)) == 0) { - return (NSS_UNAVAIL); + if (be->buf == 0) { + if ((grlen = sysconf(_SC_GETGR_R_SIZE_MAX)) > 0) + be->minbuf = grlen; + if ((be->buf = malloc(be->minbuf)) == 0) + return (NSS_UNAVAIL); } buffer = be->buf; buflen = be->minbuf; @@ -205,15 +208,26 @@ _nss_files_XY_all(be, args, netdb, filter, check) /* string search */ files_XY_check_func check; /* NULL means one-shot, for getXXent */ { + char *r; nss_status_t res; int parsestat; int (*func)(); if (filter != NULL && *filter == '\0') return (NSS_NOTFOUND); - if (be->buf == 0 && - (be->buf = malloc(be->minbuf)) == 0) { - return (NSS_UNAVAIL); /* really panic, malloc failed */ + if (be->buf == 0 || (be->minbuf < args->buf.buflen)) { + if (be->minbuf < args->buf.buflen) { + if (be->buf == 0) { + be->minbuf = args->buf.buflen; + } else if ( + (r = realloc(be->buf, args->buf.buflen)) != NULL) { + be->buf = r; + be->minbuf = args->buf.buflen; + } + } + if (be->buf == 0 && + (be->buf = malloc(be->minbuf)) == 0) + return (NSS_UNAVAIL); } if (check != 0 || be->f == 0) { @@ -670,7 +684,7 @@ _nss_files_check_name_aliases(nss_XbyY_args_t *argp, const char *line, /* compare with the alias name */ keyp = argp->key.name; while (*keyp && linep < limit && !isspace(*linep) && - *keyp == *linep) { + *keyp == *linep) { keyp++; linep++; } |