Index: head/include/rpcsvc/yp.x =================================================================== --- head/include/rpcsvc/yp.x +++ head/include/rpcsvc/yp.x @@ -40,7 +40,7 @@ %__FBSDID("$FreeBSD$"); #endif -const YPMAXRECORD = 1024; +const YPMAXRECORD = 16777216; const YPMAXDOMAIN = 64; const YPMAXMAP = 64; const YPMAXPEER = 64; Index: head/include/rpcsvc/yp_prot.h =================================================================== --- head/include/rpcsvc/yp_prot.h +++ head/include/rpcsvc/yp_prot.h @@ -79,7 +79,7 @@ #define YPPROG ((u_long)100004) #define YPVERS ((u_long)2) #define YPVERS_ORIG ((u_long)1) -#define YPMAXRECORD ((u_long)1024) +#define YPMAXRECORD ((u_long)16 * 1024 * 1024) #define YPMAXDOMAIN ((u_long)64) #define YPMAXMAP ((u_long)64) #define YPMAXPEER ((u_long)256) Index: head/include/rpcsvc/ypxfrd.x =================================================================== --- head/include/rpcsvc/ypxfrd.x +++ head/include/rpcsvc/ypxfrd.x @@ -70,7 +70,7 @@ #endif /* XXX cribbed from yp.x */ -const _YPMAXRECORD = 1024; +const _YPMAXRECORD = 16777216; const _YPMAXDOMAIN = 64; const _YPMAXMAP = 64; const _YPMAXPEER = 64; Index: head/lib/libc/net/gethostbynis.c =================================================================== --- head/lib/libc/net/gethostbynis.c +++ head/lib/libc/net/gethostbynis.c @@ -58,7 +58,7 @@ char *cp, **q; char *result; int resultlen, size, addrok = 0; - char ypbuf[YPMAXRECORD + 2]; + char *ypbuf; res_state statp; statp = __res_state(); @@ -88,10 +88,11 @@ } /* avoid potential memory leak */ - bcopy((char *)result, (char *)&ypbuf, resultlen); + ypbuf = alloca(resultlen + 2); + bcopy(result, ypbuf, resultlen); ypbuf[resultlen] = '\0'; free(result); - result = (char *)&ypbuf; + result = ypbuf; if ((cp = strchr(result, '\n'))) *cp = '\0'; Index: head/lib/libc/net/getnetbynis.c =================================================================== --- head/lib/libc/net/getnetbynis.c +++ head/lib/libc/net/getnetbynis.c @@ -58,7 +58,7 @@ char *cp, **q; char *result; int resultlen, len; - char ypbuf[YPMAXRECORD + 2]; + char *ypbuf; switch(af) { case AF_INET: @@ -77,10 +77,11 @@ &resultlen)) return (-1); - bcopy((char *)result, (char *)&ypbuf, resultlen); + ypbuf = alloca(resultlen + 2); + bcopy(result, ypbuf, resultlen); ypbuf[resultlen] = '\0'; free(result); - result = (char *)&ypbuf; + result = ypbuf; if ((cp = strchr(result, '\n'))) *cp = '\0'; Index: head/lib/libc/net/getservent.c =================================================================== --- head/lib/libc/net/getservent.c +++ head/lib/libc/net/getservent.c @@ -664,7 +664,7 @@ { char *resultbuf, *lastkey; int resultbuflen; - char buf[YPMAXRECORD + 2]; + char *buf; struct nis_state *st; int rv; @@ -681,6 +681,7 @@ name = NULL; proto = NULL; + buf = NULL; how = (enum nss_lookup_type)mdata; switch (how) { case nss_lt_name: @@ -716,7 +717,10 @@ do { switch (how) { case nss_lt_name: - snprintf(buf, sizeof(buf), "%s/%s", name, proto); + free(buf); + asprintf(&buf, "%s/%s", name, proto); + if (buf == NULL) + return (NS_TRYAGAIN); if (yp_match(st->yp_domain, "services.byname", buf, strlen(buf), &resultbuf, &resultbuflen)) { rv = NS_NOTFOUND; @@ -724,8 +728,10 @@ } break; case nss_lt_id: - snprintf(buf, sizeof(buf), "%d/%s", ntohs(port), - proto); + free(buf); + asprintf(&buf, "%d/%s", ntohs(port), proto); + if (buf == NULL) + return (NS_TRYAGAIN); /* * We have to be a little flexible @@ -791,6 +797,7 @@ } while (!(rv & NS_TERMINATE) && how == nss_lt_all); fin: + free(buf); if (rv == NS_SUCCESS && retval != NULL) *(struct servent **)retval = serv; Index: head/lib/libc/rpc/getrpcent.c =================================================================== --- head/lib/libc/rpc/getrpcent.c +++ head/lib/libc/rpc/getrpcent.c @@ -400,7 +400,7 @@ char *lastkey; char *resultbuf; int resultbuflen; - char buf[YPMAXRECORD + 2]; + char *buf; struct nis_state *st; int rv; @@ -422,6 +422,7 @@ return (NS_NOTFOUND); } + buf = NULL; rpc = va_arg(ap, struct rpcent *); buffer = va_arg(ap, char *); bufsize = va_arg(ap, size_t); @@ -445,7 +446,10 @@ case nss_lt_name: if (!st->no_name_map) { - snprintf(buf, sizeof buf, "%s", name); + free(buf); + asprintf(&buf, "%s", name); + if (buf == NULL) + return (NS_TRYAGAIN); rv = yp_match(st->domain, "rpc.byname", buf, strlen(buf), &resultbuf, &resultbuflen); @@ -473,7 +477,10 @@ } break; case nss_lt_id: - snprintf(buf, sizeof buf, "%d", number); + free(buf); + asprintf(&buf, "%d", number); + if (buf == NULL) + return (NS_TRYAGAIN); if (yp_match(st->domain, "rpc.bynumber", buf, strlen(buf), &resultbuf, &resultbuflen)) { rv = NS_NOTFOUND; @@ -560,6 +567,7 @@ } while (!(rv & NS_TERMINATE) && (how == nss_lt_all)); fin: + free(buf); if ((rv == NS_SUCCESS) && (retval != NULL)) *((struct rpcent **)retval) = rpc; Index: head/usr.sbin/rpc.yppasswdd/yppasswdd_server.c =================================================================== --- head/usr.sbin/rpc.yppasswdd/yppasswdd_server.c +++ head/usr.sbin/rpc.yppasswdd/yppasswdd_server.c @@ -323,15 +323,16 @@ DB *dbp = NULL; DBT key = { NULL, 0 }; DBT data = { NULL, 0 }; - char pwbuf[YPMAXRECORD]; + char *pwbuf; char keybuf[20]; int i; char *ptr = NULL; static char yp_last[] = "YP_LAST_MODIFIED"; - char yplastbuf[YPMAXRECORD]; + char yplastbuf[64]; snprintf(yplastbuf, sizeof yplastbuf, "%llu", (unsigned long long)time(NULL)); + pwbuf = NULL; for (i = 0; i < 4; i++) { @@ -364,12 +365,12 @@ if (yp_get_record(domain,maps[i],&key,&data,1) != YP_TRUE) { yp_error("couldn't read %s/%s: %s", domain, maps[i], strerror(errno)); - return(1); + goto ret1; } if ((ptr = strchr(data.data, ':')) == NULL) { yp_error("no colon in passwd record?!"); - return(1); + goto ret1; } /* @@ -393,8 +394,12 @@ * We're really being ultra-paranoid here. * This is generally a 'can't happen' condition. */ - snprintf(pwbuf, sizeof pwbuf, ":%d:%d:", pw->pw_uid, - pw->pw_gid); + free(pwbuf); + asprintf(&pwbuf, ":%d:%d:", pw->pw_uid, pw->pw_gid); + if (pwbuf == NULL) { + yp_error("no memory"); + goto ret1; + } if (!strstr(data.data, pwbuf)) { yp_error("warning: found entry for user %s \ in map %s@%s with wrong UID", pw->pw_name, maps[i], domain); @@ -405,24 +410,30 @@ } if (i < 2) { - snprintf(pwbuf, sizeof pwbuf, formats[i], + free(pwbuf); + asprintf(&pwbuf, formats[i], pw->pw_name, pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_class, pw->pw_change, pw->pw_expire, pw->pw_gecos, pw->pw_dir, pw->pw_shell); } else { - snprintf(pwbuf, sizeof pwbuf, formats[i], + free(pwbuf); + asprintf(&pwbuf, formats[i], pw->pw_name, *(ptr+1) == '*' ? "*" : pw->pw_passwd, pw->pw_uid, pw->pw_gid, pw->pw_gecos, pw->pw_dir, pw->pw_shell); } + if (pwbuf == NULL) { + yp_error("no memory"); + goto ret1; + } #define FLAGS O_RDWR|O_CREAT if ((dbp = yp_open_db_rw(domain, maps[i], FLAGS)) == NULL) { yp_error("couldn't open %s/%s r/w: %s",domain, maps[i],strerror(errno)); - return(1); + goto ret1; } data.data = pwbuf; @@ -432,7 +443,7 @@ yp_error("failed to update record in %s/%s", domain, maps[i]); (void)(dbp->close)(dbp); - return(1); + goto ret1; } key.data = yp_last; @@ -444,13 +455,17 @@ yp_error("failed to update timestamp in %s/%s", domain, maps[i]); (void)(dbp->close)(dbp); - return(1); + goto ret1; } (void)(dbp->close)(dbp); } - return(0); + free(pwbuf); + return (0); +ret1: + free(pwbuf); + return (1); } int * Index: head/usr.sbin/rpc.ypupdated/yp_dbupdate.c =================================================================== --- head/usr.sbin/rpc.ypupdated/yp_dbupdate.c +++ head/usr.sbin/rpc.ypupdated/yp_dbupdate.c @@ -81,7 +81,7 @@ DB *dbp; DBT key = { NULL, 0 }, data = { NULL, 0 }; char *yp_last = "YP_LAST_MODIFIED"; - char yplastbuf[YPMAXRECORD]; + char yplastbuf[32]; char *domptr; int rval = 0; Index: head/usr.sbin/ypldap/yp.c =================================================================== --- head/usr.sbin/ypldap/yp.c +++ head/usr.sbin/ypldap/yp.c @@ -323,7 +323,7 @@ static struct ypresp_val res; const char *estr; char *bp, *cp; - char key[YPMAXRECORD+1]; + char *key; log_debug("matching '%.*s' in map %s", arg->key.keydat_len, arg->key.keydat_val, arg->map); @@ -342,7 +342,9 @@ log_debug("argument too long"); return (NULL); } - memset(key, 0, sizeof(key)); + key = calloc(arg->key.keydat_len + 1, 1); + if (key == NULL) + return (NULL); (void)strncpy(key, arg->key.keydat_val, arg->key.keydat_len); if (strcmp(arg->map, "passwd.byname") == 0 || @@ -351,23 +353,23 @@ if ((ue = RB_FIND(user_name_tree, env->sc_user_names, &ukey)) == NULL) { res.stat = YP_NOKEY; - return (&res); + goto out; } yp_make_val(&res, ue->ue_line, 1); - return (&res); + goto out; } else if (strcmp(arg->map, "passwd.byuid") == 0 || strcmp(arg->map, "master.passwd.byuid") == 0) { ukey.ue_uid = strtonum(key, 0, UID_MAX, &estr); if (estr) { res.stat = YP_BADARGS; - return (&res); + goto out; } if ((ue = RB_FIND(user_uid_tree, &env->sc_user_uids, &ukey)) == NULL) { res.stat = YP_NOKEY; - return (&res); + goto out; } yp_make_val(&res, ue->ue_line, 1); @@ -376,12 +378,12 @@ gkey.ge_gid = strtonum(key, 0, GID_MAX, &estr); if (estr) { res.stat = YP_BADARGS; - return (&res); + goto out; } if ((ge = RB_FIND(group_gid_tree, &env->sc_group_gids, &gkey)) == NULL) { res.stat = YP_NOKEY; - return (&res); + goto out; } yp_make_val(&res, ge->ge_line, 1); @@ -391,7 +393,7 @@ if ((ge = RB_FIND(group_name_tree, env->sc_group_names, &gkey)) == NULL) { res.stat = YP_NOKEY; - return (&res); + goto out; } yp_make_val(&res, ge->ge_line, 1); @@ -401,46 +403,49 @@ if (strncmp(bp, "unix.", strlen("unix.")) != 0) { res.stat = YP_BADARGS; - return (&res); + goto out; } bp += strlen("unix."); if (*bp == '\0') { res.stat = YP_BADARGS; - return (&res); + goto out; } if (!(cp = strsep(&bp, "@"))) { res.stat = YP_BADARGS; - return (&res); + goto out; } if (strcmp(bp, arg->domain) != 0) { res.stat = YP_BADARGS; - return (&res); + goto out; } ukey.ue_uid = strtonum(cp, 0, UID_MAX, &estr); if (estr) { res.stat = YP_BADARGS; - return (&res); + goto out; } if ((ue = RB_FIND(user_uid_tree, &env->sc_user_uids, &ukey)) == NULL) { res.stat = YP_NOKEY; - return (&res); + goto out; } yp_make_val(&res, ue->ue_netid_line, 0); - return (&res); + goto out; } else { log_debug("unknown map %s", arg->map); res.stat = YP_NOMAP; - return (&res); + goto out; } +out: + free(key); + return (&res); } ypresp_key_val * @@ -479,14 +484,19 @@ struct groupent *ge; char *line; static struct ypresp_key_val res; - char key[YPMAXRECORD+1]; + char *key; if (yp_valid_domain(arg->domain, (struct ypresp_val *)&res) == -1) return (&res); + key = NULL; if (strcmp(arg->map, "passwd.byname") == 0 || strcmp(arg->map, "master.passwd.byname") == 0) { - memset(key, 0, sizeof(key)); + key = calloc(arg->key.keydat_len + 1, 1); + if (key == NULL) { + res.stat = YP_YPERR; + return (&res); + } (void)strncpy(key, arg->key.keydat_val, arg->key.keydat_len); ukey.ue_line = key; @@ -506,6 +516,7 @@ RB_REMOVE(user_name_tree, env->sc_user_names, &ukey); res.stat = YP_NOKEY; + free(key); return (&res); } RB_REMOVE(user_name_tree, env->sc_user_names, &ukey); @@ -513,11 +524,16 @@ line = ue->ue_line + (strlen(ue->ue_line) + 1); line = line + (strlen(line) + 1); yp_make_keyval(&res, line, line); + free(key); return (&res); } else if (strcmp(arg->map, "group.byname") == 0) { - memset(key, 0, sizeof(key)); + key = calloc(arg->key.keydat_len + 1, 1); + if (key == NULL) { + res.stat = YP_YPERR; + return (&res); + } (void)strncpy(key, arg->key.keydat_val, arg->key.keydat_len); @@ -533,6 +549,7 @@ RB_REMOVE(group_name_tree, env->sc_group_names, &gkey); res.stat = YP_NOKEY; + free(key); return (&res); } RB_REMOVE(group_name_tree, env->sc_group_names, &gkey); @@ -541,6 +558,7 @@ line = ge->ge_line + (strlen(ge->ge_line) + 1); line = line + (strlen(line) + 1); yp_make_keyval(&res, line, line); + free(key); return (&res); } else { log_debug("unknown map %s", arg->map); Index: head/usr.sbin/yppush/yppush_main.c =================================================================== --- head/usr.sbin/yppush/yppush_main.c +++ head/usr.sbin/yppush/yppush_main.c @@ -438,15 +438,26 @@ yppush_foreach(int status, char *key, int keylen, char *val, int vallen, char *data) { - char server[YPMAXRECORD + 2]; + char *server; if (status != YP_TRUE) return (status); - snprintf(server, sizeof(server), "%.*s", vallen, val); - if (skip_master && strcasecmp(server, yppush_master) == 0) + asprintf(&server, "%.*s", vallen, val); + + /* + * Do not stop the iteration on the allocation failure. We + * cannot usefully react on low memory condition anyway, and + * the failure is more likely due to insane val. + */ + if (server == NULL) return (0); + if (skip_master && strcasecmp(server, yppush_master) == 0) { + free(server); + return (0); + } + /* * Restrict the number of concurrent jobs: if yppush_jobs number * of jobs have already been dispatched and are still pending, @@ -456,12 +467,15 @@ ; /* Cleared for takeoff: set everything in motion. */ - if (yp_push(server, yppush_mapname, yppush_transid)) + if (yp_push(server, yppush_mapname, yppush_transid)) { + free(server); return(yp_errno); + } /* Bump the job counter and transaction ID. */ yppush_running_jobs++; yppush_transid++; + free(server); return (0); } Index: head/usr.sbin/ypserv/yp_server.c =================================================================== --- head/usr.sbin/ypserv/yp_server.c +++ head/usr.sbin/ypserv/yp_server.c @@ -173,8 +173,9 @@ if (do_dns && result.stat != YP_TRUE && (strstr(argp->map, "hosts") || strstr(argp->map, "ipnodes"))) { #endif - char nbuf[YPMAXRECORD]; + char *nbuf; + nbuf = alloca(argp->key.keydat_len + 1); /* NUL terminate! NUL terminate!! NUL TERMINATE!!! */ bcopy(argp->key.keydat_val, nbuf, argp->key.keydat_len); nbuf[argp->key.keydat_len] = '\0';