dm0 / rpms / systemd

Forked from rpms/systemd 5 years ago
Clone
e43452d
From 3ad4e947bb0312940d56059328dd518d01718f6f Mon Sep 17 00:00:00 2001
e43452d
From: Lennart Poettering <lennart@poettering.net>
e43452d
Date: Tue, 11 Oct 2011 22:30:31 +0200
f1996ec
Subject: [PATCH] util: properly detect what the last capability is (cherry
f1996ec
 picked from commit
e43452d
 64685e0cea62b4937f0804e47ce2cb7929f58223)
e43452d
e43452d
---
e43452d
 src/execute.c |    7 ++-----
e43452d
 src/nspawn.c  |    8 +-------
e43452d
 src/util.c    |   33 +++++++++++++++++++++++++++++++++
e43452d
 src/util.h    |    2 ++
e43452d
 4 files changed, 38 insertions(+), 12 deletions(-)
e43452d
e43452d
diff --git a/src/execute.c b/src/execute.c
e43452d
index 53e7e77..866e8bf 100644
e43452d
--- a/src/execute.c
e43452d
+++ b/src/execute.c
e43452d
@@ -895,12 +895,9 @@ static int do_capability_bounding_set_drop(uint64_t drop) {
e43452d
                 }
e43452d
         }
e43452d
 
e43452d
-        for (i = 0; i <= MAX(63LU, (unsigned long) CAP_LAST_CAP); i++)
e43452d
+        for (i = 0; i <= cap_last_cap(); i++)
e43452d
                 if (drop & ((uint64_t) 1ULL << (uint64_t) i)) {
e43452d
                         if (prctl(PR_CAPBSET_DROP, i) < 0) {
e43452d
-                                if (errno == EINVAL)
e43452d
-                                        break;
e43452d
-
e43452d
                                 r = -errno;
e43452d
                                 goto finish;
e43452d
                         }
e43452d
@@ -1720,7 +1717,7 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
e43452d
                 unsigned long l;
e43452d
                 fprintf(f, "%sCapabilityBoundingSet:", prefix);
e43452d
 
e43452d
-                for (l = 0; l <= (unsigned long) CAP_LAST_CAP; l++)
e43452d
+                for (l = 0; l <= cap_last_cap(); l++)
e43452d
                         if (!(c->capability_bounding_set_drop & ((uint64_t) 1ULL << (uint64_t) l))) {
e43452d
                                 char *t;
e43452d
 
e43452d
diff --git a/src/nspawn.c b/src/nspawn.c
e43452d
index 8441c05..653d7db 100644
e43452d
--- a/src/nspawn.c
e43452d
+++ b/src/nspawn.c
e43452d
@@ -361,7 +361,7 @@ static int drop_capabilities(void) {
e43452d
 
e43452d
         unsigned long l;
e43452d
 
e43452d
-        for (l = 0; l <= MAX(63LU, (unsigned long) CAP_LAST_CAP); l++) {
e43452d
+        for (l = 0; l <= cap_last_cap(); l++) {
e43452d
                 unsigned i;
e43452d
 
e43452d
                 for (i = 0; i < ELEMENTSOF(retain); i++)
e43452d
@@ -372,12 +372,6 @@ static int drop_capabilities(void) {
e43452d
                         continue;
e43452d
 
e43452d
                 if (prctl(PR_CAPBSET_DROP, l) < 0) {
e43452d
-
e43452d
-                        /* If this capability is not known, EINVAL
e43452d
-                         * will be returned, let's ignore this. */
e43452d
-                        if (errno == EINVAL)
e43452d
-                                break;
e43452d
-
e43452d
                         log_error("PR_CAPBSET_DROP failed: %m");
e43452d
                         return -errno;
e43452d
                 }
e43452d
diff --git a/src/util.c b/src/util.c
e43452d
index e46606d..e93e6f6 100644
e43452d
--- a/src/util.c
e43452d
+++ b/src/util.c
e43452d
@@ -5703,3 +5703,36 @@ int strdup_or_null(const char *a, char **b) {
e43452d
         *b = c;
e43452d
         return 0;
e43452d
 }
e43452d
+
e43452d
+unsigned long cap_last_cap(void) {
e43452d
+        static __thread unsigned long saved;
e43452d
+        static __thread bool valid = false;
e43452d
+        unsigned long p;
e43452d
+
e43452d
+        if (valid)
e43452d
+                return saved;
e43452d
+
e43452d
+        p = (unsigned long) CAP_LAST_CAP;
e43452d
+
e43452d
+        if (prctl(PR_CAPBSET_READ, p) < 0) {
e43452d
+
e43452d
+                /* Hmm, look downwards, until we find one that
e43452d
+                 * works */
e43452d
+                for (p--; p > 0; p --)
e43452d
+                        if (prctl(PR_CAPBSET_READ, p) >= 0)
e43452d
+                                break;
e43452d
+
e43452d
+        } else {
e43452d
+
e43452d
+                /* Hmm, look upwards, until we find one that doesn't
e43452d
+                 * work */
e43452d
+                for (;; p++)
e43452d
+                        if (prctl(PR_CAPBSET_READ, p+1) < 0)
e43452d
+                                break;
e43452d
+        }
e43452d
+
e43452d
+        saved = p;
e43452d
+        valid = true;
e43452d
+
e43452d
+        return p;
e43452d
+}
e43452d
diff --git a/src/util.h b/src/util.h
e43452d
index ccbe8a3..a71a297 100644
e43452d
--- a/src/util.h
e43452d
+++ b/src/util.h
e43452d
@@ -506,4 +506,6 @@ extern char **saved_argv;
e43452d
 
e43452d
 bool kexec_loaded(void);
e43452d
 
e43452d
+unsigned long cap_last_cap(void);
e43452d
+
e43452d
 #endif