svn commit: r350957 - in head: include/rpcsvc lib/libc/net lib/libc/rpc usr.sbin/rpc.yppasswdd usr.sbin/rpc.ypupdated usr.sbin/ypldap usr.sbin/yppush usr.sbin/ypserv
Konstantin Belousov
kib at FreeBSD.org
Mon Aug 12 20:27:36 UTC 2019
Author: kib
Date: Mon Aug 12 20:27:33 2019
New Revision: 350957
URL: https://svnweb.freebsd.org/changeset/base/350957
Log:
Increase YPMAXRECORD to 16M to be compatible with Linux.
Since YP protocol definition uses the constant to declare
variable-size opaque byte strings, the change should be binary
compatible with existing installations which do not expose keys or
values larger than 1024 bytes.
All uses of local variables with YPMAXRECORD sizes were removed to
avoid insane stack use. On the other hand, variables with static
lifetime should be fine and only result in increased VA use.
Glibc made same change, increasing the allowed length for keys and
values in YP to 16M, in 2013.
Reviewed by: markj
Discussed with: ian
Sponsored by: Mellanox Technologies
MFC after: 3 weeks
Differential revision: https://reviews.freebsd.org/D20900
Modified:
head/include/rpcsvc/yp.x
head/include/rpcsvc/yp_prot.h
head/include/rpcsvc/ypxfrd.x
head/lib/libc/net/gethostbynis.c
head/lib/libc/net/getnetbynis.c
head/lib/libc/net/getservent.c
head/lib/libc/rpc/getrpcent.c
head/usr.sbin/rpc.yppasswdd/yppasswdd_server.c
head/usr.sbin/rpc.ypupdated/yp_dbupdate.c
head/usr.sbin/ypldap/yp.c
head/usr.sbin/yppush/yppush_main.c
head/usr.sbin/ypserv/yp_server.c
Modified: head/include/rpcsvc/yp.x
==============================================================================
--- head/include/rpcsvc/yp.x Mon Aug 12 20:21:36 2019 (r350956)
+++ head/include/rpcsvc/yp.x Mon Aug 12 20:27:33 2019 (r350957)
@@ -40,7 +40,7 @@
%__FBSDID("$FreeBSD$");
#endif
-const YPMAXRECORD = 1024;
+const YPMAXRECORD = 16777216;
const YPMAXDOMAIN = 64;
const YPMAXMAP = 64;
const YPMAXPEER = 64;
Modified: head/include/rpcsvc/yp_prot.h
==============================================================================
--- head/include/rpcsvc/yp_prot.h Mon Aug 12 20:21:36 2019 (r350956)
+++ head/include/rpcsvc/yp_prot.h Mon Aug 12 20:27:33 2019 (r350957)
@@ -79,7 +79,7 @@ typedef u_int bool;
#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)
Modified: head/include/rpcsvc/ypxfrd.x
==============================================================================
--- head/include/rpcsvc/ypxfrd.x Mon Aug 12 20:21:36 2019 (r350956)
+++ head/include/rpcsvc/ypxfrd.x Mon Aug 12 20:27:33 2019 (r350957)
@@ -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;
Modified: head/lib/libc/net/gethostbynis.c
==============================================================================
--- head/lib/libc/net/gethostbynis.c Mon Aug 12 20:21:36 2019 (r350956)
+++ head/lib/libc/net/gethostbynis.c Mon Aug 12 20:27:33 2019 (r350957)
@@ -58,7 +58,7 @@ _gethostbynis(const char *name, char *map, int af, str
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 @@ _gethostbynis(const char *name, char *map, int af, str
}
/* 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';
Modified: head/lib/libc/net/getnetbynis.c
==============================================================================
--- head/lib/libc/net/getnetbynis.c Mon Aug 12 20:21:36 2019 (r350956)
+++ head/lib/libc/net/getnetbynis.c Mon Aug 12 20:27:33 2019 (r350957)
@@ -58,7 +58,7 @@ _getnetbynis(const char *name, char *map, int af, stru
char *cp, **q;
char *result;
int resultlen, len;
- char ypbuf[YPMAXRECORD + 2];
+ char *ypbuf;
switch(af) {
case AF_INET:
@@ -77,10 +77,11 @@ _getnetbynis(const char *name, char *map, int af, stru
&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';
Modified: head/lib/libc/net/getservent.c
==============================================================================
--- head/lib/libc/net/getservent.c Mon Aug 12 20:21:36 2019 (r350956)
+++ head/lib/libc/net/getservent.c Mon Aug 12 20:27:33 2019 (r350957)
@@ -664,7 +664,7 @@ nis_servent(void *retval, void *mdata, va_list ap)
{
char *resultbuf, *lastkey;
int resultbuflen;
- char buf[YPMAXRECORD + 2];
+ char *buf;
struct nis_state *st;
int rv;
@@ -681,6 +681,7 @@ nis_servent(void *retval, void *mdata, va_list ap)
name = NULL;
proto = NULL;
+ buf = NULL;
how = (enum nss_lookup_type)mdata;
switch (how) {
case nss_lt_name:
@@ -716,7 +717,10 @@ nis_servent(void *retval, void *mdata, va_list ap)
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 @@ nis_servent(void *retval, void *mdata, va_list ap)
}
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 @@ nis_servent(void *retval, void *mdata, va_list ap)
} while (!(rv & NS_TERMINATE) && how == nss_lt_all);
fin:
+ free(buf);
if (rv == NS_SUCCESS && retval != NULL)
*(struct servent **)retval = serv;
Modified: head/lib/libc/rpc/getrpcent.c
==============================================================================
--- head/lib/libc/rpc/getrpcent.c Mon Aug 12 20:21:36 2019 (r350956)
+++ head/lib/libc/rpc/getrpcent.c Mon Aug 12 20:27:33 2019 (r350957)
@@ -400,7 +400,7 @@ nis_rpcent(void *retval, void *mdata, va_list ap)
char *lastkey;
char *resultbuf;
int resultbuflen;
- char buf[YPMAXRECORD + 2];
+ char *buf;
struct nis_state *st;
int rv;
@@ -422,6 +422,7 @@ nis_rpcent(void *retval, void *mdata, va_list ap)
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 @@ nis_rpcent(void *retval, void *mdata, va_list ap)
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 @@ nis_rpcent(void *retval, void *mdata, va_list ap)
}
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 @@ done:
} while (!(rv & NS_TERMINATE) && (how == nss_lt_all));
fin:
+ free(buf);
if ((rv == NS_SUCCESS) && (retval != NULL))
*((struct rpcent **)retval) = rpc;
Modified: head/usr.sbin/rpc.yppasswdd/yppasswdd_server.c
==============================================================================
--- head/usr.sbin/rpc.yppasswdd/yppasswdd_server.c Mon Aug 12 20:21:36 2019 (r350956)
+++ head/usr.sbin/rpc.yppasswdd/yppasswdd_server.c Mon Aug 12 20:27:33 2019 (r350957)
@@ -323,15 +323,16 @@ update_inplace(struct passwd *pw, char *domain)
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 @@ update_inplace(struct passwd *pw, char *domain)
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 @@ with the same UID - continuing");
* 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 @@ with the same name - continuing");
}
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 @@ with the same name - continuing");
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 @@ with the same name - continuing");
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 *
Modified: head/usr.sbin/rpc.ypupdated/yp_dbupdate.c
==============================================================================
--- head/usr.sbin/rpc.ypupdated/yp_dbupdate.c Mon Aug 12 20:21:36 2019 (r350956)
+++ head/usr.sbin/rpc.ypupdated/yp_dbupdate.c Mon Aug 12 20:27:33 2019 (r350957)
@@ -81,7 +81,7 @@ ypmap_update(char *netname, char *map, unsigned int op
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;
Modified: head/usr.sbin/ypldap/yp.c
==============================================================================
--- head/usr.sbin/ypldap/yp.c Mon Aug 12 20:21:36 2019 (r350956)
+++ head/usr.sbin/ypldap/yp.c Mon Aug 12 20:27:33 2019 (r350957)
@@ -323,7 +323,7 @@ ypproc_match_2_svc(ypreq_key *arg, struct svc_req *req
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 @@ ypproc_match_2_svc(ypreq_key *arg, struct svc_req *req
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 @@ ypproc_match_2_svc(ypreq_key *arg, struct svc_req *req
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 @@ ypproc_match_2_svc(ypreq_key *arg, struct svc_req *req
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 @@ ypproc_match_2_svc(ypreq_key *arg, struct svc_req *req
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 @@ ypproc_match_2_svc(ypreq_key *arg, struct svc_req *req
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 @@ ypproc_next_2_svc(ypreq_key *arg, struct svc_req *req)
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 @@ ypproc_next_2_svc(ypreq_key *arg, struct svc_req *req)
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 @@ ypproc_next_2_svc(ypreq_key *arg, struct svc_req *req)
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 @@ ypproc_next_2_svc(ypreq_key *arg, struct svc_req *req)
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 @@ ypproc_next_2_svc(ypreq_key *arg, struct svc_req *req)
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);
Modified: head/usr.sbin/yppush/yppush_main.c
==============================================================================
--- head/usr.sbin/yppush/yppush_main.c Mon Aug 12 20:21:36 2019 (r350956)
+++ head/usr.sbin/yppush/yppush_main.c Mon Aug 12 20:27:33 2019 (r350957)
@@ -438,15 +438,26 @@ static int
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 @@ yppush_foreach(int status, char *key, int keylen, char
;
/* 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);
}
Modified: head/usr.sbin/ypserv/yp_server.c
==============================================================================
--- head/usr.sbin/ypserv/yp_server.c Mon Aug 12 20:21:36 2019 (r350956)
+++ head/usr.sbin/ypserv/yp_server.c Mon Aug 12 20:27:33 2019 (r350957)
@@ -173,8 +173,9 @@ ypproc_match_2_svc(ypreq_key *argp, struct svc_req *rq
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';
More information about the svn-src-all
mailing list