aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Seiler <christian@iwakd.de>2012-02-23 09:57:13 +0100
committerDaniel Lezcano <daniel.lezcano@free.fr>2012-02-23 09:57:13 +0100
commit20d816599f954e7e5864d39884cc0de56f9358fd (patch)
tree1efa6ecaad05c9d4ad497b6a98407f4db953c7a5
parentcorrectly install signal handler for lxc-init (diff)
downloadlxc-20d816599f954e7e5864d39884cc0de56f9358fd.tar.gz
lxc-20d816599f954e7e5864d39884cc0de56f9358fd.tar.bz2
lxc-20d816599f954e7e5864d39884cc0de56f9358fd.zip
Add function to determine CAP_LAST_CAP of the current kernel dynamically
The function lxc_caps_last_cap() determines CAP_LAST_CAP of the current kernel dynamically. It first tries to read /proc/sys/kernel/cap_last_cap. If that fails, because the kernel does not support this interface yet, it loops through all capabilities and tries to determine whether the current capability is part of the bounding set. The first capability for which prctl() fails is considered to be CAP_LAST_CAP. Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
-rw-r--r--src/lxc/caps.c46
-rw-r--r--src/lxc/caps.h2
2 files changed, 48 insertions, 0 deletions
diff --git a/src/lxc/caps.c b/src/lxc/caps.c
index 46a2766..1610002 100644
--- a/src/lxc/caps.c
+++ b/src/lxc/caps.c
@@ -23,6 +23,9 @@
#define _GNU_SOURCE
#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <limits.h>
#include <sys/prctl.h>
#include <sys/capability.h>
@@ -167,3 +170,46 @@ int lxc_caps_init(void)
return 0;
}
+
+static int _real_caps_last_cap(void)
+{
+ int fd;
+ int result = -1;
+
+ /* try to get the maximum capability over the kernel
+ * interface introduced in v3.2 */
+ fd = open("/proc/sys/kernel/cap_last_cap", O_RDONLY);
+ if (fd >= 0) {
+ char buf[32];
+ char *ptr;
+ int n;
+
+ if ((n = read(fd, buf, 31)) >= 0) {
+ buf[n] = '\0';
+ result = strtol(buf, &ptr, 10);
+ if (!ptr || (*ptr != '\0' && *ptr != '\n') ||
+ result == LONG_MIN || result == LONG_MAX)
+ result = -1;
+ }
+
+ close(fd);
+ }
+
+ /* try to get it manually by trying to get the status of
+ * each capability indiviually from the kernel */
+ if (result < 0) {
+ int cap = 0;
+ while (prctl(PR_CAPBSET_READ, cap) >= 0) cap++;
+ result = cap - 1;
+ }
+
+ return result;
+}
+
+int lxc_caps_last_cap(void)
+{
+ static int last_cap = -1;
+ if (last_cap < 0) last_cap = _real_caps_last_cap();
+
+ return last_cap;
+}
diff --git a/src/lxc/caps.h b/src/lxc/caps.h
index 4c07b69..e4e0d42 100644
--- a/src/lxc/caps.h
+++ b/src/lxc/caps.h
@@ -28,6 +28,8 @@ extern int lxc_caps_down(void);
extern int lxc_caps_up(void);
extern int lxc_caps_init(void);
+extern int lxc_caps_last_cap(void);
+
#define lxc_priv(__lxc_function) \
({ \
int __ret, __ret2, __errno = 0; \