]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
nss-systemd: set sg_adm/sg_mem in intrinsic groups
authorTobias Stoeckmann <tobias@stoeckmann.org>
Sat, 27 Dec 2025 14:24:45 +0000 (15:24 +0100)
committerTobias Stoeckmann <tobias@stoeckmann.org>
Sun, 4 Jan 2026 17:01:13 +0000 (18:01 +0100)
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

index ae0b5c803df0e008cd9403c2cddcec6a96bb3ee0..11384dbad8446dc548693a3e06907d64851c379c 100644 (file)
@@ -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;
 }