--- a/support/nfsidmap/libnfsidmap.c +++ b/support/nfsidmap/libnfsidmap.c @@ -430,11 +430,17 @@ nobody_user = conf_get_str("Mapping", "Nobody-User"); if (nobody_user) { - size_t buflen = sysconf(_SC_GETPW_R_SIZE_MAX); + long scbuflen = sysconf(_SC_GETPW_R_SIZE_MAX); + size_t buflen = 1024; /*value on my gentoo glibc system that has _SC_GETPW_R_SIZE_MAX*/ struct passwd *buf; struct passwd *pw = NULL; int err; + /*sysconf can return -1 when _SC_GETPW_R_SIZE_MAX is not defined, like on musl systems, if cast to size_t this will lead + to an integer overflow, which leads to a buffer overflow and crashes svcgssd */ + if (scbuflen > 0) + buflen = (size_t)scbuflen; + buf = malloc(sizeof(*buf) + buflen); if (buf) { err = getpwnam_r(nobody_user, buf, ((char *)buf) + sizeof(*buf), buflen, &pw); @@ -451,10 +457,16 @@ nobody_group = conf_get_str("Mapping", "Nobody-Group"); if (nobody_group) { - size_t buflen = sysconf(_SC_GETGR_R_SIZE_MAX); + long scbuflen = sysconf(_SC_GETGR_R_SIZE_MAX); + size_t buflen = 1024; /*value on my gentoo glibc system that has _SC_GETGR_R_SIZE_MAX*/ struct group *buf; struct group *gr = NULL; int err; + + /*sysconf can return -1 when _SC_GETGR_R_SIZE_MAX is not defined, like on musl systems, if cast to size_t this will lead + to an integer overflow, which leads to a buffer overflow and crashes svcgssd */ + if (scbuflen > 0) + buflen = (size_t)scbuflen; buf = malloc(sizeof(*buf) + buflen); if (buf) { --- a/support/nfsidmap/static.c +++ b/support/nfsidmap/static.c @@ -98,10 +98,14 @@ { struct passwd *pw; struct pwbuf *buf; - size_t buflen = sysconf(_SC_GETPW_R_SIZE_MAX); + long scbuflen = sysconf(_SC_GETPW_R_SIZE_MAX); + size_t buflen = 1024; char *localname; int err; + if (scbuflen > 0) + buflen = (size_t)scbuflen; + buf = malloc(sizeof(*buf) + buflen); if (!buf) { err = ENOMEM; @@ -149,9 +153,13 @@ { struct group *gr; struct grbuf *buf; - size_t buflen = sysconf(_SC_GETGR_R_SIZE_MAX); + long scbuflen = sysconf(_SC_GETGR_R_SIZE_MAX); + size_t buflen = 1024; char *localgroup; int err; + + if (scbuflen > 0) + buflen = (size_t)scbuflen; buf = malloc(sizeof(*buf) + buflen); if (!buf) { --- a/support/nfsidmap/nss.c +++ b/support/nfsidmap/nss.c @@ -91,9 +91,13 @@ struct passwd *pw = NULL; struct passwd pwbuf; char *buf; - size_t buflen = sysconf(_SC_GETPW_R_SIZE_MAX); + long scbuflen = sysconf(_SC_GETPW_R_SIZE_MAX); + size_t buflen = 1024; int err = -ENOMEM; + if (scbuflen > 0) + buflen = (size_t)scbuflen; + buf = malloc(buflen); if (!buf) goto out; @@ -119,8 +123,12 @@ struct group *gr = NULL; struct group grbuf; char *buf; - size_t buflen = sysconf(_SC_GETGR_R_SIZE_MAX); + long scbuflen = sysconf(_SC_GETGR_R_SIZE_MAX); + size_t buflen = 1024; int err; + + if (scbuflen > 0) + buflen = (size_t)scbuflen; if (domain == NULL) domain = get_default_domain();