]> err.no Git - systemd/commitdiff
util: properly detect what the last capability is
authorLennart Poettering <lennart@poettering.net>
Tue, 11 Oct 2011 20:30:31 +0000 (22:30 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 11 Oct 2011 20:30:31 +0000 (22:30 +0200)
src/execute.c
src/nspawn.c
src/util.c
src/util.h

index 53e7e77fdec0536bee1188940f88f322f9f22237..866e8bf2f69ed9e088e47dea5afd3eebff44d851 100644 (file)
@@ -895,12 +895,9 @@ static int do_capability_bounding_set_drop(uint64_t drop) {
                 }
         }
 
-        for (i = 0; i <= MAX(63LU, (unsigned long) CAP_LAST_CAP); i++)
+        for (i = 0; i <= cap_last_cap(); i++)
                 if (drop & ((uint64_t) 1ULL << (uint64_t) i)) {
                         if (prctl(PR_CAPBSET_DROP, i) < 0) {
-                                if (errno == EINVAL)
-                                        break;
-
                                 r = -errno;
                                 goto finish;
                         }
@@ -1720,7 +1717,7 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
                 unsigned long l;
                 fprintf(f, "%sCapabilityBoundingSet:", prefix);
 
-                for (l = 0; l <= (unsigned long) CAP_LAST_CAP; l++)
+                for (l = 0; l <= cap_last_cap(); l++)
                         if (!(c->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) l))) {
                                 char *t;
 
index 8441c057b9fcf7b4f875cfb82bc9b05d04a82e80..653d7db730a80361b08a2b002415c0cb2e6fcaa6 100644 (file)
@@ -361,7 +361,7 @@ static int drop_capabilities(void) {
 
         unsigned long l;
 
-        for (l = 0; l <= MAX(63LU, (unsigned long) CAP_LAST_CAP); l++) {
+        for (l = 0; l <= cap_last_cap(); l++) {
                 unsigned i;
 
                 for (i = 0; i < ELEMENTSOF(retain); i++)
@@ -372,12 +372,6 @@ static int drop_capabilities(void) {
                         continue;
 
                 if (prctl(PR_CAPBSET_DROP, l) < 0) {
-
-                        /* If this capability is not known, EINVAL
-                         * will be returned, let's ignore this. */
-                        if (errno == EINVAL)
-                                break;
-
                         log_error("PR_CAPBSET_DROP failed: %m");
                         return -errno;
                 }
index e46606dabb39551e0b0b5b3df5a39ef311ee861b..e93e6f6cf5c962e90ac7b8a4a29cc8cfe00a80ce 100644 (file)
@@ -5703,3 +5703,36 @@ int strdup_or_null(const char *a, char **b) {
         *b = c;
         return 0;
 }
+
+unsigned long cap_last_cap(void) {
+        static __thread unsigned long saved;
+        static __thread bool valid = false;
+        unsigned long p;
+
+        if (valid)
+                return saved;
+
+        p = (unsigned long) CAP_LAST_CAP;
+
+        if (prctl(PR_CAPBSET_READ, p) < 0) {
+
+                /* Hmm, look downwards, until we find one that
+                 * works */
+                for (p--; p > 0; p --)
+                        if (prctl(PR_CAPBSET_READ, p) >= 0)
+                                break;
+
+        } else {
+
+                /* Hmm, look upwards, until we find one that doesn't
+                 * work */
+                for (;; p++)
+                        if (prctl(PR_CAPBSET_READ, p+1) < 0)
+                                break;
+        }
+
+        saved = p;
+        valid = true;
+
+        return p;
+}
index ccbe8a3efa4ab0bc9d2f77b9eac43f88feb05e8a..a71a297eab6b56740efe070d3473dd3118b183f3 100644 (file)
@@ -506,4 +506,6 @@ extern char **saved_argv;
 
 bool kexec_loaded(void);
 
+unsigned long cap_last_cap(void);
+
 #endif