chiark / gitweb /
sd-bus: add supplementary groups list to creds object
[elogind.git] / src / libsystemd / sd-bus / bus-kernel.c
index afac3b6bcc3e2895cef6d78fec9f78cb61d11909..e66a263c48d865d76143584ad705efbf44dbfc00 100644 (file)
@@ -513,28 +513,75 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
                         break;
                 }
 
-                case KDBUS_ITEM_CREDS:
-                        /* UID/GID/PID are always valid */
-                        m->creds.uid = (uid_t) d->creds.uid;
-                        m->creds.gid = (gid_t) d->creds.gid;
-                        m->creds.pid = (pid_t) d->creds.pid;
-                        m->creds.mask |= (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID) & bus->creds_mask;
-
-                        /* The PID starttime/TID might be missing
-                         * however, when the data is faked by some
-                         * data bus proxy and it lacks that
-                         * information about the real client since
-                         * SO_PEERCRED is used for that */
-
-                        if (d->creds.starttime > 0) {
-                                m->creds.pid_starttime = d->creds.starttime / NSEC_PER_USEC;
+                case KDBUS_ITEM_PIDS:
+
+                        /* The PID starttime/TID might be missing,
+                         * when the data is faked by some data bus
+                         * proxy and it lacks that information about
+                         * the real client since SO_PEERCRED is used
+                         * for that. */
+
+                        if (d->pids.pid > 0) {
+                                m->creds.pid = (pid_t) d->pids.pid;
+                                m->creds.mask |= SD_BUS_CREDS_PID & bus->creds_mask;
+                        }
+
+                        if (d->pids.starttime > 0) {
+                                m->creds.pid_starttime = d->pids.starttime / NSEC_PER_USEC;
                                 m->creds.mask |= SD_BUS_CREDS_PID_STARTTIME & bus->creds_mask;
                         }
 
-                        if (d->creds.tid > 0) {
-                                m->creds.tid = (pid_t) d->creds.tid;
+                        if (d->pids.tid > 0) {
+                                m->creds.tid = (pid_t) d->pids.tid;
                                 m->creds.mask |= SD_BUS_CREDS_TID & bus->creds_mask;
                         }
+
+                        break;
+
+                case KDBUS_ITEM_CREDS:
+
+                        /* EUID/SUID/FSUID/EGID/SGID/FSGID might be missing too (see above). */
+
+                        if ((uid_t) d->creds.uid != (uid_t) -1) {
+                                m->creds.uid = (uid_t) d->creds.uid;
+                                m->creds.mask |= SD_BUS_CREDS_UID & bus->creds_mask;
+                        }
+
+                        if ((uid_t) d->creds.euid != (uid_t) -1) {
+                                m->creds.euid = (uid_t) d->creds.euid;
+                                m->creds.mask |= SD_BUS_CREDS_EUID & bus->creds_mask;
+                        }
+
+                        if ((uid_t) d->creds.suid != (uid_t) -1) {
+                                m->creds.suid = (uid_t) d->creds.suid;
+                                m->creds.mask |= SD_BUS_CREDS_SUID & bus->creds_mask;
+                        }
+
+                        if ((uid_t) d->creds.fsuid != (uid_t) -1) {
+                                m->creds.fsuid = (uid_t) d->creds.fsuid;
+                                m->creds.mask |= SD_BUS_CREDS_FSUID & bus->creds_mask;
+                        }
+
+                        if ((gid_t) d->creds.gid != (gid_t) -1) {
+                                m->creds.gid = (gid_t) d->creds.gid;
+                                m->creds.mask |= SD_BUS_CREDS_GID & bus->creds_mask;
+                        }
+
+                        if ((gid_t) d->creds.egid != (gid_t) -1) {
+                                m->creds.egid = (gid_t) d->creds.egid;
+                                m->creds.mask |= SD_BUS_CREDS_EGID & bus->creds_mask;
+                        }
+
+                        if ((gid_t) d->creds.sgid != (gid_t) -1) {
+                                m->creds.sgid = (gid_t) d->creds.sgid;
+                                m->creds.mask |= SD_BUS_CREDS_SGID & bus->creds_mask;
+                        }
+
+                        if ((gid_t) d->creds.fsgid != (gid_t) -1) {
+                                m->creds.fsgid = (gid_t) d->creds.fsgid;
+                                m->creds.mask |= SD_BUS_CREDS_FSGID & bus->creds_mask;
+                        }
+
                         break;
 
                 case KDBUS_ITEM_TIMESTAMP:
@@ -613,6 +660,29 @@ static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
                         m->creds.mask |= SD_BUS_CREDS_DESCRIPTION & bus->creds_mask;
                         break;
 
+                case KDBUS_ITEM_AUXGROUPS:
+
+                        if (bus->creds_mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
+                                size_t i, n;
+                                uid_t *u;
+                                n = (d->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t);
+                                u = new(uid_t, n);
+                                if (!u) {
+                                        r = -ENOMEM;
+                                        goto fail;
+                                }
+
+                                for (i = 0; i < n; i++)
+                                        u[i] = (uid_t) d->data64[i];
+
+                                m->creds.supplementary_gids = u;
+                                m->creds.n_supplementary_gids = n;
+
+                                m->creds.mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
+                        }
+
+                        break;
+
                 case KDBUS_ITEM_FDS:
                 case KDBUS_ITEM_SECLABEL:
                         break;
@@ -724,6 +794,9 @@ int bus_kernel_take_fd(sd_bus *b) {
         if (b->fake_creds_valid)
                 sz += ALIGN8(offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds));
 
+        if (b->fake_pids_valid)
+                sz += ALIGN8(offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids));
+
         if (b->fake_label) {
                 l = strlen(b->fake_label);
                 sz += ALIGN8(offsetof(struct kdbus_item, str) + l + 1);
@@ -751,6 +824,14 @@ int bus_kernel_take_fd(sd_bus *b) {
                 item = KDBUS_ITEM_NEXT(item);
         }
 
+        if (b->fake_pids_valid) {
+                item->size = offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids);
+                item->type = KDBUS_ITEM_PIDS;
+                item->pids = b->fake_pids;
+
+                item = KDBUS_ITEM_NEXT(item);
+        }
+
         if (b->fake_label) {
                 item->size = offsetof(struct kdbus_item, str) + l + 1;
                 item->type = KDBUS_ITEM_SECLABEL;
@@ -1237,9 +1318,13 @@ int kdbus_translate_attach_flags(uint64_t mask, uint64_t *kdbus_mask) {
 
         assert(kdbus_mask);
 
-        if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID))
+        if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
+                    SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID))
                 m |= KDBUS_ATTACH_CREDS;
 
+        if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_PID_STARTTIME|SD_BUS_CREDS_TID))
+                m |= KDBUS_ATTACH_PIDS;
+
         if (mask & SD_BUS_CREDS_COMM)
                 m |= KDBUS_ATTACH_PID_COMM;
 
@@ -1270,6 +1355,9 @@ int kdbus_translate_attach_flags(uint64_t mask, uint64_t *kdbus_mask) {
         if (mask & SD_BUS_CREDS_DESCRIPTION)
                 m |= KDBUS_ATTACH_CONN_DESCRIPTION;
 
+        if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS)
+                m |= KDBUS_ATTACH_AUXGROUPS;
+
         *kdbus_mask = m;
         return 0;
 }