Allow for running with --disable_newuser started as root
authorRobert Swiecki <robert@swiecki.net>
Sun, 1 Oct 2017 03:32:07 +0000 (05:32 +0200)
committerRobert Swiecki <robert@swiecki.net>
Sun, 1 Oct 2017 03:32:07 +0000 (05:32 +0200)
caps.c
cmdline.c
contain.c

diff --git a/caps.c b/caps.c
index 4a5cc091886c7ebef8038e537460537f289caf13..466361ac8fed5d39f99cac37b9ba9ada1899fc54 100644 (file)
--- a/caps.c
+++ b/caps.c
@@ -152,6 +152,13 @@ static bool capsGetPermitted(cap_user_data_t cap_data, unsigned int cap)
        return cap_data[off_byte].permitted & (1U << off_bit);
 }
 
+static bool capsGetEffective(cap_user_data_t cap_data, unsigned int cap)
+{
+       size_t off_byte = cap / (sizeof(cap_data->effective) * 8);
+       size_t off_bit = cap % (sizeof(cap_data->effective) * 8);
+       return cap_data[off_byte].effective & (1U << off_bit);
+}
+
 static bool capsGetInheritable(cap_user_data_t cap_data, unsigned int cap)
 {
        size_t off_byte = cap / (sizeof(cap_data->inheritable) * 8);
@@ -169,6 +176,7 @@ static void capsSetInheritable(cap_user_data_t cap_data, unsigned int cap)
 #if !defined(PR_CAP_AMBIENT)
 #define PR_CAP_AMBIENT 47
 #define PR_CAP_AMBIENT_RAISE 2
+#define PR_CAP_AMBIENT_CLEAR_ALL 4
 #endif                         /* !defined(PR_CAP_AMBIENT) */
 static bool CapsInitNsKeepCaps(cap_user_data_t cap_data)
 {
@@ -236,30 +244,35 @@ bool capsInitNs(struct nsjconf_t * nsjconf)
        }
        LOG_D("Adding the following capabilities to the inheritable set:%s", dbgmsg);
 
+       if (capsSet(cap_data) == false) {
+               return false;
+       }
+
        /*
         * Make sure all other caps (those which were not explicitly requested) are removed from the
         * bounding set
         */
-       dbgmsg[0] = '\0';
-       for (size_t i = 0; i < ARRAYSIZE(capNames); i++) {
-               if (capsGetInheritable(cap_data, capNames[i].val) == true) {
-                       continue;
-               }
-               utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capNames[i].name);
-               if (prctl(PR_CAPBSET_DROP, (unsigned long)capNames[i].val, 0UL, 0UL, 0UL) == -1) {
-                       PLOG_W("prctl(PR_CAPBSET_DROP, %s)", capNames[i].name);
-                       return false;
+       if (capsGetEffective(cap_data, CAP_SETPCAP) == true) {
+               dbgmsg[0] = '\0';
+               for (size_t i = 0; i < ARRAYSIZE(capNames); i++) {
+                       if (capsGetInheritable(cap_data, capNames[i].val) == true) {
+                               continue;
+                       }
+                       utilSSnPrintf(dbgmsg, sizeof(dbgmsg), " %s", capNames[i].name);
+                       if (prctl(PR_CAPBSET_DROP, (unsigned long)capNames[i].val, 0UL, 0UL, 0UL) ==
+                           -1) {
+                               PLOG_W("prctl(PR_CAPBSET_DROP, %s)", capNames[i].name);
+                               return false;
+                       }
                }
-       }
-       LOG_D("Dropped the following capabilities from the bounding set:%s", dbgmsg);
-
-       /* Must be performed after CAPBSET has been manipulated */
-       if (capsSet(cap_data) == false) {
-               return false;
+               LOG_D("Dropped the following capabilities from the bounding set:%s", dbgmsg);
        }
 
        /* Make sure inheritable set is preserved across execve via the modified ambient set */
        dbgmsg[0] = '\0';
+       if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0UL, 0UL, 0UL) == -1) {
+               PLOG_W("prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL)");
+       }
        TAILQ_FOREACH(p, &nsjconf->caps, pointers) {
                if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, (unsigned long)p->val, 0UL, 0UL) ==
                    -1) {
index 19f92810c060cf99f25658a2273047c317924f7b..9f42786850086b240f3517e40961de5a692854be 100644 (file)
--- a/cmdline.c
+++ b/cmdline.c
@@ -234,7 +234,7 @@ void cmdlineLogParams(struct nsjconf_t *nsjconf)
                        LOG_I("Uid map: inside_uid:%lu outside_uid:%lu count:%zu newuidmap:%s",
                              (unsigned long)p->inside_id, (unsigned long)p->outside_id, p->count,
                              p->is_newidmap ? "true" : "false");
-                       if (p->outside_id == 0) {
+                       if (p->outside_id == 0 && nsjconf->clone_newuser) {
                                LOG_W
                                    ("Process will be UID/EUID=0 in the global user namespace, and will have user root-level access to files");
                        }
@@ -243,7 +243,7 @@ void cmdlineLogParams(struct nsjconf_t *nsjconf)
                        LOG_I("Gid map: inside_gid:%lu outside_gid:%lu count:%zu newgidmap:%s",
                              (unsigned long)p->inside_id, (unsigned long)p->outside_id, p->count,
                              p->is_newidmap ? "true" : "false");
-                       if (p->outside_id == 0) {
+                       if (p->outside_id == 0 && nsjconf->clone_newuser) {
                                LOG_W
                                    ("Process will be GID/EGID=0 in the global user namespace, and will have group root-level access to files");
                        }
index 29570020a537baa14b52eb45bd4cab60342857ec..a511cfbdb41ebd9a6c1661b8a319b6a9044bf6f4 100644 (file)
--- a/contain.c
+++ b/contain.c
@@ -84,7 +84,7 @@ static bool containDropPrivs(struct nsjconf_t *nsjconf)
 #define PR_SET_NO_NEW_PRIVS 38
 #endif
        if (nsjconf->disable_no_new_privs == false) {
-               if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) {
+               if (prctl(PR_SET_NO_NEW_PRIVS, 1UL, 0UL, 0UL, 0UL) == -1) {
                        /* Only new kernels support it */
                        PLOG_W("prctl(PR_SET_NO_NEW_PRIVS, 1)");
                }