diff options
author | michen <none@none> | 2007-04-30 17:48:25 -0700 |
---|---|---|
committer | michen <none@none> | 2007-04-30 17:48:25 -0700 |
commit | 606f6aa3d37f0f8e8282e483c1400bae5275aeeb (patch) | |
tree | fc38185db3e98a44b67a3c8753ee0064ed7e5398 | |
parent | 59f2ff5c96304fcfa3d97e66fbe1c521f42ac103 (diff) | |
download | illumos-gate-onnv_64.tar.gz |
6548196 Multiple memory corruption vulnerabilities in nscd(1M)onnv_64
-rw-r--r-- | usr/src/cmd/nscd/cache.c | 8 | ||||
-rw-r--r-- | usr/src/cmd/nscd/nscd_common.h | 3 | ||||
-rw-r--r-- | usr/src/cmd/nscd/nscd_door.c | 19 | ||||
-rw-r--r-- | usr/src/cmd/nscd/nscd_door.h | 8 | ||||
-rw-r--r-- | usr/src/cmd/nscd/nscd_frontend.c | 305 | ||||
-rw-r--r-- | usr/src/cmd/nscd/nscd_frontend.h | 8 | ||||
-rw-r--r-- | usr/src/lib/libc/port/gen/getxby_door.c | 36 | ||||
-rw-r--r-- | usr/src/lib/libc/port/gen/nss_dbdefs.c | 21 |
8 files changed, 377 insertions, 31 deletions
diff --git a/usr/src/cmd/nscd/cache.c b/usr/src/cmd/nscd/cache.c index 65bdd85db3..f7abb08d58 100644 --- a/usr/src/cmd/nscd/cache.c +++ b/usr/src/cmd/nscd/cache.c @@ -1748,7 +1748,13 @@ nsc_lookup(nsc_lookup_args_t *largs, int flag) { break; case SERVERERROR: - /* status and errno already set in the phdr */ + /* + * status and errno should have been set in the phdr, + * if not, set status to NSS_ERROR + */ + if (NSCD_STATUS_IS_OK(phdr)) { + NSCD_SET_STATUS(phdr, NSS_ERROR, 0); + } break; case NOSERVER: diff --git a/usr/src/cmd/nscd/nscd_common.h b/usr/src/cmd/nscd/nscd_common.h index 8d7de7478c..f45ce07f07 100644 --- a/usr/src/cmd/nscd/nscd_common.h +++ b/usr/src/cmd/nscd/nscd_common.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -69,6 +69,7 @@ typedef enum { NSCD_CREATE_GETENT_CTX_FAILED, NSCD_NSS_BACKEND_NOT_FOUND, NSCD_DOOR_UCRED_ERROR, + NSCD_DOOR_BUFFER_CHECK_FAILED, NSCD_SELF_CRED_NOT_CONFIGURED, NSCD_SELF_CRED_NO_FORKER, NSCD_SELF_CRED_WRONG_NSCD, diff --git a/usr/src/cmd/nscd/nscd_door.c b/usr/src/cmd/nscd/nscd_door.c index 87640baf02..dc43c9c92f 100644 --- a/usr/src/cmd/nscd/nscd_door.c +++ b/usr/src/cmd/nscd/nscd_door.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -105,11 +105,11 @@ copy_output(void *outdata, int outdlen, return (ret); } - nss_status_t _nscd_doorcall(int callnum) { - nss_pheader_t phdr; + size_t buflen; + nss_pheader_t *phdr; void *dptr; size_t ndata; size_t adata; @@ -119,21 +119,24 @@ _nscd_doorcall(int callnum) _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) (me, "processing door call %d ...\n", callnum); - phdr.nsc_callnumber = callnum; - ndata = sizeof (phdr); - adata = sizeof (phdr); - dptr = (void *)&phdr; + /* allocate door buffer from the stack */ + NSCD_ALLOC_DOORBUF(callnum, 0, dptr, buflen); + ndata = buflen; + adata = buflen; + ret = _nsc_trydoorcall(&dptr, &ndata, &adata); if (ret != NSS_SUCCESS) { + phdr = (nss_pheader_t *)dptr; _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_DEBUG) (me, "door call (%d) failed (status = %d, error = %s)\n", - callnum, ret, strerror(NSCD_GET_ERRNO(&phdr))); + callnum, ret, strerror(NSCD_GET_ERRNO(phdr))); } return (ret); } + nss_status_t _nscd_doorcall_data(int callnum, void *indata, int indlen, void *outdata, int outdlen, nss_pheader_t *phdr) diff --git a/usr/src/cmd/nscd/nscd_door.h b/usr/src/cmd/nscd/nscd_door.h index 382968f5e1..102cc65f26 100644 --- a/usr/src/cmd/nscd/nscd_door.h +++ b/usr/src/cmd/nscd/nscd_door.h @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -70,8 +70,12 @@ extern "C" { uptr = alloca(usz); \ (void) memset(uptr, 0, usz); \ ((nss_pheader_t *)uptr)->nsc_callnumber = (cn); \ + ((nss_pheader_t *)uptr)->p_version = NSCD_HEADER_REV; \ ((nss_pheader_t *)uptr)->pbufsiz = usz; \ - ((nss_pheader_t *)uptr)->data_off = sizeof (nss_pheader_t); + ((nss_pheader_t *)uptr)->data_off = sizeof (nss_pheader_t); \ + ((nss_pheader_t *)uptr)->key_off = sizeof (nss_pheader_t); \ + ((nss_pheader_t *)uptr)->dbd_off = sizeof (nss_pheader_t); \ + ((nss_pheader_t *)uptr)->data_len = dsz; #define NSCD_N2N_DOOR_DATA(type, buf) \ (type *)((void *)(((char *)(buf)) + sizeof (nss_pheader_t))) diff --git a/usr/src/cmd/nscd/nscd_frontend.c b/usr/src/cmd/nscd/nscd_frontend.c index fe42fecb90..02b081db58 100644 --- a/usr/src/cmd/nscd/nscd_frontend.c +++ b/usr/src/cmd/nscd/nscd_frontend.c @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -377,6 +377,261 @@ _nscd_APP_check_cred( } } +/* log error and return -1 when an invalid packed buffer header is found */ +static int +pheader_error(nss_pheader_t *phdr, uint32_t call_number) +{ + char *call_num_str; + + switch (call_number) { + case NSCD_SEARCH: + call_num_str = "NSCD_SEARCH"; + break; + case NSCD_SETENT: + call_num_str = "NSCD_SETENT"; + break; + case NSCD_GETENT: + call_num_str = "NSCD_GETENT"; + break; + case NSCD_ENDENT: + call_num_str = "NSCD_ENDENT"; + break; + case NSCD_PUT: + call_num_str = "NSCD_PUT"; + break; + case NSCD_GETHINTS: + call_num_str = "NSCD_GETHINTS"; + break; + default: + call_num_str = "UNKNOWN"; + break; + } + + _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ALERT) + ("pheader_error", "call number %s: invalid packed buffer header\n", + call_num_str); + + NSCD_SET_STATUS(phdr, NSS_ERROR, EINVAL); + return (-1); +} + +/* + * Validate the header of a getXbyY or setent/getent/endent request. + * Return 0 if good, -1 otherwise. + * + * A valid header looks like the following (size is arg_size, does + * not include the output area): + * +----------------------------------+ -- + * | nss_pheader_t (header fixed part)| ^ + * | | | + * | pbufsiz, dbd,off, key_off, | len = sizeof(nss_pheader_t) + * | data_off .... | | + * | | v + * +----------------------------------+ <----- dbd_off + * | dbd (database description) | ^ + * | nss_dbd_t + up to 3 strings | | + * | length = sizeof(nss_dbd_t) + | len = key_off - dbd_off + * | length of 3 strings + | | + * | length of padding | | + * | (total length in multiple of 4) | v + * +----------------------------------+ <----- key_off + * | lookup key | ^ + * | nss_XbyY_key_t, content varies, | | + * | based on database and lookup op | len = data_off - key_off + * | length = data_off - key_off | | + * | including padding, multiple of 4 | v + * +----------------------------------+ <----- data_off (= arg_size) + * | | ^ + * | area to hold results | | + * | | len = data_len (= pbufsiz - + * | | | data_off) + * | | v + * +----------------------------------+ <----- pbufsiz + */ +static int +validate_pheader( + void *argp, + size_t arg_size, + uint32_t call_number) +{ + nss_pheader_t *phdr = (nss_pheader_t *)(void *)argp; + nssuint_t l1, l2; + + /* + * current version is NSCD_HEADER_REV, length of the fixed part + * of the header must match the size of nss_pheader_t + */ + if (phdr->p_version != NSCD_HEADER_REV || + phdr->dbd_off != sizeof (nss_pheader_t)) + return (pheader_error(phdr, call_number)); + + /* + * buffer size and offsets must be in multiple of 4 + */ + if ((arg_size & 3) || (phdr->dbd_off & 3) || (phdr->key_off & 3) || + (phdr->data_off & 3)) + return (pheader_error(phdr, call_number)); + + /* + * the input arg_size is the length of the request header + * and should be less than NSCD_PHDR_MAXLEN + */ + if (phdr->data_off != arg_size || arg_size > NSCD_PHDR_MAXLEN) + return (pheader_error(phdr, call_number)); + + /* get length of the dbd area */ + l1 = phdr->key_off - phdr-> dbd_off; + + /* + * dbd area may contain padding, so length of dbd should + * not be less than the length of the actual data + */ + if (l1 < phdr->dbd_len) + return (pheader_error(phdr, call_number)); + + /* get length of the key area */ + l2 = phdr->data_off - phdr->key_off; + + /* + * key area may contain padding, so length of key area should + * not be less than the length of the actual data + */ + if (l2 < phdr->key_len) + return (pheader_error(phdr, call_number)); + + /* + * length of fixed part + lengths of dbd and key area = length of + * the request header + */ + if (sizeof (nss_pheader_t) + l1 + l2 != phdr->data_off) + return (pheader_error(phdr, call_number)); + + /* header length + data length = buffer length */ + if (phdr->data_off + phdr->data_len != phdr->pbufsiz) + return (pheader_error(phdr, call_number)); + + return (0); +} + +/* log error and return -1 when an invalid nscd to nscd buffer is found */ +static int +N2Nbuf_error(nss_pheader_t *phdr, uint32_t call_number) +{ + char *call_num_str; + + switch (call_number) { + case NSCD_PING: + call_num_str = "NSCD_PING"; + break; + + case NSCD_IMHERE: + call_num_str = "NSCD_IMHERE"; + break; + + case NSCD_PULSE: + call_num_str = "NSCD_PULSE"; + break; + + case NSCD_FORK: + call_num_str = "NSCD_FORK"; + break; + + case NSCD_KILL: + call_num_str = "NSCD_KILL"; + break; + + case NSCD_REFRESH: + call_num_str = "NSCD_REFRESH"; + break; + + case NSCD_GETPUADMIN: + call_num_str = "NSCD_GETPUADMIN"; + break; + + case NSCD_GETADMIN: + call_num_str = "NSCD_GETADMIN"; + break; + + case NSCD_SETADMIN: + call_num_str = "NSCD_SETADMIN"; + break; + + case NSCD_KILLSERVER: + call_num_str = "NSCD_KILLSERVER"; + break; + default: + call_num_str = "UNKNOWN"; + break; + } + + _NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ALERT) + ("N2Nbuf_error", "call number %s: invalid N2N buffer\n", + call_num_str); + + NSCD_SET_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0, + NSCD_DOOR_BUFFER_CHECK_FAILED); + + return (-1); +} + +/* + * Validate the buffer of an nscd to nscd request. + * Return 0 if good, -1 otherwise. + * + * A valid buffer looks like the following (size is arg_size): + * +----------------------------------+ -- + * | nss_pheader_t (header fixed part)| ^ + * | | | + * | pbufsiz, dbd,off, key_off, | len = sizeof(nss_pheader_t) + * | data_off .... | | + * | | v + * +----------------------------------+ <---dbd_off = key_off = data_off + * | | ^ + * | input data/output data | | + * | OR no data | len = data_len (= pbufsiz - + * | | | data_off) + * | | | len could be zero + * | | v + * +----------------------------------+ <--- pbufsiz + */ +static int +validate_N2Nbuf( + void *argp, + size_t arg_size, + uint32_t call_number) +{ + nss_pheader_t *phdr = (nss_pheader_t *)(void *)argp; + + /* + * current version is NSCD_HEADER_REV, length of the fixed part + * of the header must match the size of nss_pheader_t + */ + if (phdr->p_version != NSCD_HEADER_REV || + phdr->dbd_off != sizeof (nss_pheader_t)) + return (N2Nbuf_error(phdr, call_number)); + + /* + * There are no dbd and key data, so the dbd, key, data + * offsets should be equal + */ + if (phdr->dbd_off != phdr->key_off || + phdr->dbd_off != phdr->data_off) + return (N2Nbuf_error(phdr, call_number)); + + /* + * the input arg_size is the buffer length and should + * be less or equal than NSCD_N2NBUF_MAXLEN + */ + if (phdr->pbufsiz != arg_size || arg_size > NSCD_N2NBUF_MAXLEN) + return (N2Nbuf_error(phdr, call_number)); + + /* header length + data length = buffer length */ + if (phdr->data_off + phdr->data_len != phdr->pbufsiz) + return (N2Nbuf_error(phdr, call_number)); + + return (0); +} + static void lookup(char *argp, size_t arg_size) { @@ -387,6 +642,12 @@ lookup(char *argp, size_t arg_size) NSCD_ALLOC_LOOKUP_BUFFER(argp, arg_size, phdr, space, sizeof (space)); + /* + * make sure the first couple bytes of the data area is null, + * so that bad strings in the packed header stop here + */ + (void) memset((char *)phdr + phdr->data_off, 0, 16); + (void) memset(&largs, 0, sizeof (largs)); largs.buffer = argp; largs.bufsize = arg_size; @@ -506,7 +767,8 @@ if_selfcred_return_per_user_door(char *argp, size_t arg_size, int door = -1; int rc = 0; door_desc_t desc; - char space[1024*4]; + char *space; + int len; /* * check to see if self-cred is configured and @@ -540,17 +802,16 @@ if_selfcred_return_per_user_door(char *argp, size_t arg_size, } /* return the alternate door descriptor */ - (void) memcpy(space, phdr, NSCD_PHDR_LEN(phdr)); - argp = space; - phdr = (nss_pheader_t *)(void *)space; + len = strlen(dblist) + 1; + space = alloca(arg_size + len); + phdr->data_len = len; + (void) memcpy(space, phdr, arg_size); + (void) strncpy((char *)space + arg_size, dblist, len); dp = &desc; dp->d_attributes = DOOR_DESCRIPTOR; dp->d_data.d_desc.d_descriptor = door; - phdr->data_len = strlen(dblist) + 1; - (void) strcpy(((char *)phdr) + NSCD_PHDR_LEN(phdr), dblist); - - arg_size = NSCD_PHDR_LEN(phdr) + NSCD_DATA_LEN(phdr); - (void) door_return(argp, arg_size, dp, 1); + arg_size += len; + (void) door_return(space, arg_size, dp, 1); } /*ARGSUSED*/ @@ -562,7 +823,8 @@ switcher(void *cookie, char *argp, size_t arg_size, pid_t ent_pid = -1; nss_pheader_t *phdr = (nss_pheader_t *)((void *)argp); void *uptr; - int buflen, len; + int len; + size_t buflen; int callnum; char *me = "switcher"; @@ -585,7 +847,14 @@ switcher(void *cookie, char *argp, size_t arg_size, restart_if_cfgfile_changed(); if ((phdr->nsc_callnumber & NSCDV2CATMASK) == NSCD_CALLCAT_APP) { + + /* make sure the packed buffer header is good */ + if (validate_pheader(argp, arg_size, + phdr->nsc_callnumber) == -1) + (void) door_return(argp, arg_size, NULL, 0); + switch (phdr->nsc_callnumber) { + case NSCD_SEARCH: /* if a fallback to main nscd, skip per-user setup */ @@ -655,6 +924,11 @@ switcher(void *cookie, char *argp, size_t arg_size, callnum = phdr->nsc_callnumber; /* nscd -> nscd v2 calls */ + + /* make sure the buffer is good */ + if (validate_N2Nbuf(argp, arg_size, callnum) == -1) + (void) door_return(argp, arg_size, NULL, 0); + switch (callnum) { case NSCD_PING: @@ -684,9 +958,12 @@ switcher(void *cookie, char *argp, size_t arg_size, break; case NSCD_REFRESH: - if (_nscd_refresh() != NSCD_SUCCESS) - exit(1); - NSCD_SET_STATUS_SUCCESS(phdr); + N2N_check_priv(argp, "NSCD_REFRESH"); + if (NSCD_STATUS_IS_OK(phdr)) { + if (_nscd_refresh() != NSCD_SUCCESS) + exit(1); + NSCD_SET_STATUS_SUCCESS(phdr); + } break; case NSCD_GETPUADMIN: diff --git a/usr/src/cmd/nscd/nscd_frontend.h b/usr/src/cmd/nscd/nscd_frontend.h index e917db99bd..48da7c37e3 100644 --- a/usr/src/cmd/nscd/nscd_frontend.h +++ b/usr/src/cmd/nscd/nscd_frontend.h @@ -19,7 +19,7 @@ * CDDL HEADER END */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -34,6 +34,8 @@ extern "C" { #include "cache.h" +#define NSCD_N2NBUF_MAXLEN 1024 * 8 +#define NSCD_PHDR_MAXLEN 1024 * 8 #define NSCD_LOOKUP_BUFSIZE 1024 * 16 #define NSCD_DOORBUF_MAXLEN 1024 * 512 #define NSCD_PHDR_LEN(hdrp) ((hdrp)->data_off) @@ -45,6 +47,8 @@ extern "C" { bufp = space; \ bufsiz = spsiz; \ hdrp = (nss_pheader_t *)(void *)space; \ + (hdrp)->pbufsiz = bufsiz; \ + (hdrp)->data_len = bufsiz - (hdrp)->data_off; \ } else { \ (bufp) = NULL; \ bufsiz = (hdrp)->pbufsiz; \ @@ -54,6 +58,8 @@ extern "C" { if ((bufp) != NULL) { \ (void) memcpy((bufp), (hdrp), NSCD_PHDR_LEN(hdrp)); \ (hdrp) = (nss_pheader_t *)(void *)(bufp); \ + (hdrp)->pbufsiz = bufsiz; \ + (hdrp)->data_len = bufsiz - (hdrp)->data_off; \ } else { \ NSCD_SET_STATUS((hdrp), NSS_ERROR, ENOMEM); \ (void) door_return((char *)(hdrp), \ diff --git a/usr/src/lib/libc/port/gen/getxby_door.c b/usr/src/lib/libc/port/gen/getxby_door.c index e659ed9dcb..3d1768baca 100644 --- a/usr/src/lib/libc/port/gen/getxby_door.c +++ b/usr/src/lib/libc/port/gen/getxby_door.c @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -43,6 +43,7 @@ #include <sys/door.h> #include <procfs.h> #include <door.h> +#include <sys/mman.h> #include "libc.h" #include "tsd.h" #include "base_conversion.h" @@ -418,11 +419,20 @@ _nsc_trydoorcall_ext(void **dptr, size_t *ndata, size_t *adata) nss_dbd_t *dbd; int fb2frontd = 0; int reset_frontd = 0; + size_t ndata_save = *ndata, adata_save = *adata; + void *dptr_save = *dptr; ph = (nss_pheader_t *)*dptr; dbd = (nss_dbd_t *)((void *)((char *)ph + ph->dbd_off)); if (dbd->o_name != 0) db = (char *)dbd + dbd->o_name; + + /* + * save away a copy of the header, in case the request needs + * to be sent to nscd more than once. In that case, this + * original header can be copied back to the door buffer + * to replace the possibly changed header + */ ph_save = *ph; while (ret == NSS_ALTRETRY || ret == NSS_ALTRESET) { @@ -449,6 +459,18 @@ _nsc_trydoorcall_ext(void **dptr, size_t *ndata, size_t *adata) * fall back and retry on front door */ fb2frontd = 1; + if (*dptr != dptr_save) + (void) munmap((void *)*dptr, *ndata); + + /* + * restore the buffer size and header + * data so that the front door will + * see the original request + */ + *ndata = ndata_save; + *adata = adata_save; + *dptr = dptr_save; + ph = (nss_pheader_t *)*dptr; *ph = ph_save; /* * tell the front door server, this is @@ -538,6 +560,18 @@ _nsc_trydoorcall_ext(void **dptr, size_t *ndata, size_t *adata) (void) fcntl(backd->doorfd, F_SETFD, FD_CLOEXEC); lmutex_unlock(&backd->door_lock); /* NSS_ALTRETRY new back door */ + if (*dptr != dptr_save) + (void) munmap((void *)*dptr, *ndata); + + /* + * restore the buffer size and header + * data so that the back door will + * see the original request + */ + *ndata = ndata_save; + *adata = adata_save; + *dptr = dptr_save; + ph = (nss_pheader_t *)*dptr; *ph = ph_save; } return (ret); diff --git a/usr/src/lib/libc/port/gen/nss_dbdefs.c b/usr/src/lib/libc/port/gen/nss_dbdefs.c index 22f8d1bc98..f8ef2e93d1 100644 --- a/usr/src/lib/libc/port/gen/nss_dbdefs.c +++ b/usr/src/lib/libc/port/gen/nss_dbdefs.c @@ -864,7 +864,7 @@ nss_upack_key2arg(void *buffer, size_t length, char **dbname, { nss_pheader_t *pbuf = (nss_pheader_t *)buffer; const char *strtype = NULL; - nssuint_t off, *uptr; + nssuint_t off, *uptr, keysize; size_t len, slop; int i, j; char **cv, *bptr; @@ -874,6 +874,9 @@ nss_upack_key2arg(void *buffer, size_t length, char **dbname, nss_pnetgr_t *pptr; _priv_execattr *pe; + /* keysize is length of the key area */ + keysize = pbuf->data_off - pbuf->key_off; + off = pbuf->key_off; bptr = (char *)buffer + off; uptr = (nssuint_t *)((void *)bptr); @@ -1014,11 +1017,15 @@ nss_upack_key2arg(void *buffer, size_t length, char **dbname, for (j = 0; j < NSS_NETGR_N; j++) { ing->arg[j].argv = cv; for (i = 0; i < ing->arg[j].argc; i++) { + if (*uptr >= keysize) + return (NSS_ERROR); *cv++ = (bptr + *uptr++); } } ing->groups.argv = cv; for (i = 0; i < ing->groups.argc; i++) { + if (*uptr >= keysize) + return (NSS_ERROR); *cv++ = (bptr + *uptr++); } break; @@ -1110,7 +1117,7 @@ nss_packed_getkey(void *buffer, size_t length, char **dbname, { nss_pheader_t *pbuf = (nss_pheader_t *)buffer; nss_dbd_t *pdbd; - nssuint_t off; + nssuint_t off, dbdsize; int index; if (buffer == NULL || length == 0 || dbop == NULL || @@ -1120,6 +1127,10 @@ nss_packed_getkey(void *buffer, size_t length, char **dbname, *dbop = pbuf->nss_dbop; off = pbuf->dbd_off; pdbd = (nss_dbd_t *)((void *)((char *)buffer + off)); + dbdsize = pbuf->key_off - pbuf->dbd_off; + if (pdbd->o_name >= dbdsize || pdbd->o_config_name >= dbdsize || + pdbd->o_default_config >= dbdsize) + return (NSS_ERROR); *dbname = (char *)buffer + off + pdbd->o_name; if ((index = nss_dbop_search(*dbname, (uint32_t)*dbop)) < 0) return (NSS_ERROR); @@ -1169,7 +1180,7 @@ nss_packed_arg_init(void *buffer, size_t length, nss_db_root_t *db_root, nss_str2ent_t s2e = str2packent; nss_str2ent_t real_s2e = NULL; nss_dbd_t *pdbd; - nssuint_t off; + nssuint_t off, dbdsize; char *dbname, *bptr; size_t len; int index; @@ -1182,6 +1193,10 @@ nss_packed_arg_init(void *buffer, size_t length, nss_db_root_t *db_root, *dbop = pbuf->nss_dbop; off = pbuf->dbd_off; pdbd = (nss_dbd_t *)((void *)((char *)buffer + off)); + dbdsize = pbuf->key_off - pbuf->dbd_off; + if (pdbd->o_name >= dbdsize || pdbd->o_config_name >= dbdsize || + pdbd->o_default_config >= dbdsize) + return (NSS_ERROR); dbname = (char *)buffer + off + pdbd->o_name; if ((index = nss_dbop_search(dbname, (uint32_t)*dbop)) < 0) return (NSS_ERROR); |