We can apply this patch to libcap.
It enables to obtain the list of capabilities running kernel
supported dynamically, from /sys/kernel/capability.

When we use libcap with this patch on the previous kernel,
it apply static list of capabilities instead.

Thanks,
----
Signed-off-by: KaiGai Kohei <[EMAIL PROTECTED]>

diff --git a/libcap/_makenames.c b/libcap/_makenames.c
index 212f0b4..c57e940 100644
--- a/libcap/_makenames.c
+++ b/libcap/_makenames.c
@@ -43,7 +43,7 @@ int main(void)
           "#define __CAP_BITS   %d\n"
           "\n"
           "#ifdef LIBCAP_PLEASE_INCLUDE_ARRAY\n"
-          "  char const *_cap_names[__CAP_BITS] = {\n", maxcaps);
+          "  static const char *_cap_names_fallback[__CAP_BITS] = {\n", 
maxcaps);

     for (i=0; i<maxcaps; ++i) {
        if (pointers[i])
diff --git a/libcap/cap_flag.c b/libcap/cap_flag.c
index e521fcd..f490b29 100644
--- a/libcap/cap_flag.c
+++ b/libcap/cap_flag.c
@@ -21,7 +21,7 @@ int cap_get_flag(cap_t cap_d, cap_value_t value, cap_flag_t 
set,
      * Is it a known capability?
      */

-    if (raised && good_cap_t(cap_d) && value >= 0 && value < __CAP_BITS
+    if (raised && good_cap_t(cap_d) && value >= 0 && value < _cap_names_num
        && set >= 0 && set < NUMBER_OF_CAP_SETS) {
        *raised = isset_cap(cap_d,value,set) ? CAP_SET:CAP_CLEAR;
        return 0;
@@ -45,12 +45,12 @@ int cap_set_flag(cap_t cap_d, cap_flag_t set,
      * Is it a known capability?
      */

-    if (good_cap_t(cap_d) && no_values > 0 && no_values <= __CAP_BITS
+    if (good_cap_t(cap_d) && no_values > 0 && no_values <= _cap_names_num
        && (set >= 0) && (set < NUMBER_OF_CAP_SETS)
        && (raise == CAP_SET || raise == CAP_CLEAR) ) {
        int i;
        for (i=0; i<no_values; ++i) {
-           if (array_values[i] < 0 || array_values[i] >= __CAP_BITS) {
+           if (array_values[i] < 0 || array_values[i] >= _cap_names_num) {
                _cap_debug("weird capability (%d) - skipped", array_values[i]);
            } else {
                int value = array_values[i];
diff --git a/libcap/cap_text.c b/libcap/cap_text.c
index 06f61d9..7337bca 100644
--- a/libcap/cap_text.c
+++ b/libcap/cap_text.c
@@ -8,9 +8,11 @@

 #define LIBCAP_PLEASE_INCLUDE_ARRAY
 #include "libcap.h"
+#include "cap_names.h"

 #include <ctype.h>
 #include <stdio.h>
+#include <dirent.h>

 /* Maximum output text length (16 per cap) */
 #define CAP_TEXT_SIZE    (16*__CAP_BITS)
@@ -19,6 +21,10 @@
 #define LIBCAP_INH   02
 #define LIBCAP_PER   04

+/* array of capability names initialized at _init() */
+int _cap_names_num = __CAP_BITS;
+char **_cap_names = _cap_names_fallback;
+
 /*
  * Parse a textual representation of capabilities, returning an internal
  * representation.
@@ -71,14 +77,14 @@ static int lookupname(char const **strp)
     str.constp = *strp;
     if (isdigit(*str.constp)) {
        unsigned long n = strtoul(str.constp, &str.p, 0);
-       if (n >= __CAP_BITS)
+       if (n >= _cap_names_num)
            return -1;
        *strp = str.constp;
        return n;
     } else {
        char const *s;
        int n;
-       for (n = __CAP_BITS; n--; )
+       for (n = _cap_names_num; n--; )
            if (_cap_names[n] && (s = namcmp(str.constp, _cap_names[n]))) {
                *strp = s;
                return n;
@@ -270,7 +276,7 @@ char *cap_to_text(cap_t caps, ssize_t *length_p)
     _cap_debugcap("i = ", *caps, CAP_INHERITABLE);
     _cap_debugcap("p = ", *caps, CAP_PERMITTED);

-    for (n = __CAP_BITS; n--; )
+    for (n = _cap_names_num; n--; )
        histo[getstateflags(caps, n)]++;

     for (m=t=7; t--; )
@@ -286,7 +292,7 @@ char *cap_to_text(cap_t caps, ssize_t *length_p)
     for (t = 8; t--; )
        if (t != m && histo[t]) {
            *p++ = ' ';
-           for (n = 0; n != __CAP_BITS; n++)
+           for (n = 0; n != _cap_names_num; n++)
                if (getstateflags(caps, n) == t) {
                    if (_cap_names[n])
                        p += sprintf(p, "%s,", _cap_names[n]);
@@ -323,3 +329,66 @@ char *cap_to_text(cap_t caps, ssize_t *length_p)

     return (_libcap_strdup(buf));
 }
+
+#define SYSFS_CAP_BASE "/sys/kernel/capability"
+void __cap_names_init(void);
+void __attribute__ ((constructor)) __cap_names_init(void)
+{
+    DIR *dirp;
+    FILE *filp;
+    struct dirent *dent;
+    char pathname[256];
+    char **local_cap_names;
+    unsigned int i, code, local_cap_names_num;
+
+    /* compute size of array */
+    filp = fopen(SYSFS_CAP_BASE "/index", "rb");
+    if (!filp)
+       return;
+    if (fscanf(filp, "%u", &local_cap_names_num) != 1) {
+       fclose(filp);
+       return;
+    }
+    fclose(filp);
+
+    local_cap_names_num++;
+    local_cap_names = malloc(sizeof(char *) * local_cap_names_num);
+    if (!local_cap_names)
+       return;
+    memset(local_cap_names, 0, sizeof(char *) * local_cap_names_num);
+
+    /* scan /sys/kernel/capability */
+    dirp = opendir(SYSFS_CAP_BASE);
+    if (!dirp)
+       goto error1;
+
+    while (!!(dent = readdir(dirp))) {
+       if (!!strncmp("cap_", dent->d_name, 4))
+           continue;
+
+       snprintf(pathname, sizeof(pathname), SYSFS_CAP_BASE "/%s", 
dent->d_name);
+       filp = fopen(pathname, "rb");
+       if (!filp)
+           goto error2;
+       if (fscanf(filp, "%u", &code) != 1 || code >= local_cap_names_num) {
+           fclose(filp);
+           goto error2;
+       }
+       fclose(filp);
+
+       local_cap_names[code] = strdup(dent->d_name);
+       if (!local_cap_names[code])
+           goto error2;
+    }
+    _cap_names = local_cap_names;
+    _cap_names_num = local_cap_names_num;
+
+  error2:
+    for (i=0; i < local_cap_names_num; i++)
+       free(local_cap_names[i]);
+    closedir(dirp);
+  error1:
+    free(local_cap_names);
+
+    return;
+}
diff --git a/libcap/libcap.h b/libcap/libcap.h
index 0e4a167..b5a5deb 100644
--- a/libcap/libcap.h
+++ b/libcap/libcap.h
@@ -22,8 +22,8 @@
 #define __u32   unsigned int
 #endif /* __u32 */

-/* include the names for the caps and a definition of __CAP_BITS */
-#include "cap_names.h"
+extern char **_cap_names;
+extern int _cap_names_num;

 /*
  * Do we match the local kernel?

-- 
OSS Platform Development Division, NEC
KaiGai Kohei <[EMAIL PROTECTED]>
-
To unsubscribe from this list: send the line "unsubscribe 
linux-security-module" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to