Quellcode durchsuchen

[LibOS] Add supplementary groups support: set{get}groups()

This commit adds emulation of setgroups() and getgroups() syscalls.
These syscalls are dummies, they do not consult host OS. Instead, they
initialize a per-process array of suppl group IDs to a single entry of
getgid() and allow to set any group IDs.
Zhang Chen vor 5 Jahren
Ursprung
Commit
18eb57832e

+ 2 - 0
LibOS/shim/include/shim_table.h

@@ -434,6 +434,8 @@ uid_t shim_do_getuid (void);
 gid_t shim_do_getgid (void);
 int shim_do_setuid (uid_t uid);
 int shim_do_setgid (gid_t gid);
+int shim_do_setgroups (int gidsetsize, gid_t * grouplist);
+int shim_do_getgroups (int gidsetsize, gid_t * grouplist);
 uid_t shim_do_geteuid (void);
 gid_t shim_do_getegid (void);
 pid_t shim_do_getppid (void);

+ 0 - 0
LibOS/shim/src/bookkeep/shim_thread.c


+ 8 - 6
LibOS/shim/src/shim_syscalls.c

@@ -506,6 +506,14 @@ DEFINE_SHIM_SYSCALL (setuid, 1, shim_do_setuid, int, uid_t, uid)
 /* setgid: sys/shim_getpid.c */
 DEFINE_SHIM_SYSCALL (setgid, 1, shim_do_setgid, int, gid_t, gid)
 
+/* setgroups: sys/shim_getpid.c */
+DEFINE_SHIM_SYSCALL (setgroups, 2, shim_do_setgroups, int, int,
+                     gidsetsize, gid_t *, grouplist)
+
+/* getgroups: sys/shim_getpid.c */
+DEFINE_SHIM_SYSCALL (getgroups, 2, shim_do_getgroups, int, int,
+                     gidsetsize, gid_t *, grouplist)
+
 /* geteuid: sys/shim_getpid.c */
 DEFINE_SHIM_SYSCALL (geteuid, 0, shim_do_geteuid, uid_t)
 
@@ -528,12 +536,6 @@ SHIM_SYSCALL_PASSTHROUGH (setreuid, 2, int, uid_t, ruid, uid_t, euid)
 
 SHIM_SYSCALL_PASSTHROUGH (setregid, 2, int, gid_t, rgid, gid_t, egid)
 
-SHIM_SYSCALL_PASSTHROUGH (getgroups, 2, int, int, gidsetsize, gid_t *,
-                          grouplist)
-
-SHIM_SYSCALL_PASSTHROUGH (setgroups, 2, int, int, gidsetsize, gid_t *,
-                          grouplist)
-
 SHIM_SYSCALL_PASSTHROUGH (setresuid, 3, int, uid_t, ruid, uid_t, euid, uid_t,
                           suid)
 

+ 60 - 1
LibOS/shim/src/sys/shim_getpid.c

@@ -19,12 +19,15 @@
  *
  * Implementation of system call "getpid", "gettid", "getppid",
  * "set_tid_address", "getuid", "getgid", "setuid", "setgid", "geteuid",
- * "getegid", "setpgid", "getpgid", "getpgrp", "setsid" and "getsid".
+ * "getegid", "setpgid", "getpgid", "getpgrp", "setgroups", "getgroups",
+ * "setsid" and "getsid".
  */
 
 #include <shim_internal.h>
 #include <shim_table.h>
 #include <shim_thread.h>
+#include <shim_ipc.h>
+#include <shim_checkpoint.h>
 
 #include <pal.h>
 #include <pal_error.h>
@@ -86,6 +89,62 @@ int shim_do_setgid (gid_t gid)
     return 0;
 }
 
+/* shim_do_set{get}groups() do not propagate group info to host OS but rather are dummies */
+#define NGROUPS_MAX 65536  /* # of supplemental group IDs; has to be same as host OS */
+
+static struct groups_info_t {
+    int size;
+    gid_t spl_gid[NGROUPS_MAX];
+} g_groups_info __attribute_migratable = { .size = -1 };
+
+int shim_do_setgroups(int gidsetsize, gid_t* grouplist) {
+    if ((unsigned)gidsetsize > NGROUPS_MAX)
+        return -EINVAL;
+
+    if (gidsetsize && test_user_memory(grouplist, gidsetsize * sizeof(gid_t), true))
+        return -EFAULT;
+
+    lock(&cur_process.lock);
+    g_groups_info.size = gidsetsize;
+    for (int i = 0; i < gidsetsize; i++)
+        g_groups_info.spl_gid[i] = grouplist[i];
+    unlock(&cur_process.lock);
+
+    return 0;
+}
+
+int shim_do_getgroups(int gidsetsize, gid_t* grouplist) {
+    int cur_groups_size;
+
+    if (gidsetsize < 0)
+        return -EINVAL;
+
+    if (gidsetsize && test_user_memory(grouplist, gidsetsize * sizeof(gid_t), true))
+        return -EFAULT;
+
+    lock(&cur_process.lock);
+
+    if (g_groups_info.size == -1) {
+        /* initialize with getgid() */
+        g_groups_info.size = 1;
+        g_groups_info.spl_gid[0] = shim_do_getgid();
+    }
+
+    cur_groups_size = g_groups_info.size;
+    if (gidsetsize) {
+        if (cur_groups_size > gidsetsize) {
+            unlock(&cur_process.lock);
+            return -EINVAL;
+        }
+
+        for (int i = 0; i < cur_groups_size; i++)
+            grouplist[i] = g_groups_info.spl_gid[i];
+    }
+
+    unlock(&cur_process.lock);
+    return cur_groups_size;
+}
+
 uid_t shim_do_geteuid (void)
 {
     struct shim_thread * cur = get_cur_thread();