From 239903d44c12f10b5fe7c1f8457ae5203e47d8cc Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Sat, 27 Dec 2025 15:24:45 +0100 Subject: [PATCH] nss-systemd: set sg_adm/sg_mem in intrinsic groups The sg_adm and sg_mem fields are supposed to point to a NULL terminated string array. If these are NULL, some foreign tools like shadow's sg trigger NULL pointer dereferences (or fortunately their asset() calls). --- src/nss-systemd/nss-systemd.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/nss-systemd/nss-systemd.c b/src/nss-systemd/nss-systemd.c index ae0b5c803d..11384dbad8 100644 --- a/src/nss-systemd/nss-systemd.c +++ b/src/nss-systemd/nss-systemd.c @@ -75,6 +75,8 @@ static const struct group root_group = { static const struct sgrp root_sgrp = { .sg_namp = (char*) "root", .sg_passwd = (char*) PASSWORD_LOCKED_AND_INVALID, + .sg_adm = (char*[]) { NULL }, + .sg_mem = (char*[]) { NULL }, }; static const struct group nobody_group = { @@ -87,6 +89,8 @@ static const struct group nobody_group = { static const struct sgrp nobody_sgrp = { .sg_namp = (char*) NOBODY_GROUP_NAME, .sg_passwd = (char*) PASSWORD_LOCKED_AND_INVALID, + .sg_adm = (char*[]) { NULL }, + .sg_mem = (char*[]) { NULL }, }; typedef struct GetentData { @@ -257,12 +261,18 @@ static enum nss_status copy_synthesized_sgrp( assert(src); assert(src->sg_namp); assert(src->sg_passwd); + assert(src->sg_adm); + assert(!*src->sg_adm); /* Our synthesized records' sg_adm is always just NULL... */ + assert(src->sg_mem); + assert(!*src->sg_mem); /* Our synthesized records' sg_mem is always just NULL... */ size_t required = strlen(src->sg_namp) + 1 + - strlen(src->sg_passwd) + 1; + strlen(src->sg_passwd) + 1 + + sizeof(char*) + /* NULL terminator storage for src->sg_adm */ + sizeof(char*); /* NULL terminator storage for src->sg_mem */ - if (buflen < required) { + if (buflen < ALIGN(required)) { *errnop = ERANGE; return NSS_STATUS_TRYAGAIN; } @@ -274,7 +284,10 @@ static enum nss_status copy_synthesized_sgrp( /* String fields point into the user-provided buffer */ dest->sg_namp = buffer; dest->sg_passwd = stpcpy(dest->sg_namp, src->sg_namp) + 1; - strcpy(dest->sg_passwd, src->sg_passwd); + dest->sg_adm = ALIGN_PTR(stpcpy(dest->sg_passwd, src->sg_passwd) + 1); + *dest->sg_adm = NULL; + dest->sg_mem = dest->sg_adm + 1; + *dest->sg_mem = NULL; return NSS_STATUS_SUCCESS; }