The setpriv executable from util-linux also dumps out information on the
different capability sets known by the kernel. By default, these are the
inheritable capabilities, bounding capabilities and (not yet released)
the ambient capabilities, which have been introduced with Linux 4.3.
This patch introduces the ability to dump the set of inheritable
capabilities.
---
 util-linux/setpriv.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 110 insertions(+), 2 deletions(-)

diff --git a/util-linux/setpriv.c b/util-linux/setpriv.c
index c7be492a2..673943654 100644
--- a/util-linux/setpriv.c
+++ b/util-linux/setpriv.c
@@ -45,6 +45,8 @@
 // --selinux-label <label>  set SELinux label
 // --apparmor-profile <pr>  set AppArmor profile
 
+#include <linux/capability.h>
+#include <sys/capability.h>
 #include <sys/prctl.h>
 #include <unistd.h>
 #include "libbb.h"
@@ -57,17 +59,106 @@
 #define PR_GET_NO_NEW_PRIVS 39
 #endif
 
+static cap_user_header_t cap_header;
+static int cap_u32s;
+
 enum {
        OPT_DUMP = (1 << 0),
        OPT_NNP  = (1 << 1),
 };
 
+static const char *capabilities[] = {
+       "chown",
+       "dac_override",
+       "dac_read_search",
+       "fowner",
+       "fsetid",
+       "kill",
+       "setgid",
+       "setuid",
+       "setpcap",
+       "linux_immutable",
+       "net_bind_service",
+       "net_broadcast",
+       "net_admin",
+       "net_raw",
+       "ipc_lock",
+       "ipc_owner",
+       "sys_module",
+       "sys_rawio",
+       "sys_chroot",
+       "sys_ptrace",
+       "sys_pacct",
+       "sys_admin",
+       "sys_boot",
+       "sys_nice",
+       "sys_resource",
+       "sys_time",
+       "sys_tty_config",
+       "mknod",
+       "lease",
+       "audit_write",
+       "audit_control",
+       "setfcap",
+       "mac_override",
+       "mac_admin",
+       "syslog",
+       "wake_alarm",
+       "block_suspend",
+       "audit_read",
+};
+
+static void initcaps(void)
+{
+       cap_header = xmalloc(sizeof(*cap_header));
+
+       cap_header->pid = 0;
+       cap_header->version = _LINUX_CAPABILITY_VERSION;
+
+       if ((capget(cap_header, NULL)) < 0)
+               bb_simple_perror_msg_and_die("capget");
+
+       switch (cap_header->version) {
+               case _LINUX_CAPABILITY_VERSION_1:
+                       cap_u32s = _LINUX_CAPABILITY_U32S_1;
+                       break;
+               case _LINUX_CAPABILITY_VERSION_2:
+                       cap_u32s = _LINUX_CAPABILITY_U32S_2;
+                       break;
+               case _LINUX_CAPABILITY_VERSION_3:
+                       cap_u32s = _LINUX_CAPABILITY_U32S_3;
+                       break;
+               default:
+                       bb_error_msg_and_die("unsupported capability version");
+       }
+}
+
+static cap_user_data_t getcaps(void)
+{
+       cap_user_data_t result;
+
+       result = xmalloc(sizeof(*result) * cap_u32s);
+       if (capget(cap_header, result) < 0)
+               bb_simple_perror_msg_and_die("capget");
+
+       return result;
+}
+
+static void printcap(unsigned long cap)
+{
+       if (cap < ARRAY_SIZE(capabilities))
+               printf(capabilities[cap]);
+       else
+               printf("cap_%lu", cap);
+}
+
 static int dump(void)
 {
+       cap_user_data_t caps;
        uid_t ruid, euid, suid;
        gid_t rgid, egid, sgid;
        gid_t *gids;
-       int ngids, nnp;
+       int i, n, ngids, nnp;
 
        if (getresuid(&ruid, &euid, &suid) < 0)
                bb_simple_perror_msg_and_die("getresgid");
@@ -84,6 +175,8 @@ static int dump(void)
        if ((nnp = prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0)) < 0)
                bb_simple_perror_msg_and_die("prctl: GET_NO_NEW_PRIVS");
 
+       caps = getcaps();
+
        printf("uid: %d\n", ruid);
        printf("euid: %d\n", euid);
        printf("gid: %d\n", rgid);
@@ -93,7 +186,6 @@ static int dump(void)
        if (ngids == 0) {
                printf("[none]");
        } else {
-               int i;
                for (i = 0; i < ngids; i++) {
                        if (i)
                                putchar(',');
@@ -104,7 +196,21 @@ static int dump(void)
 
        printf("no_new_privs: %d\n", nnp);
 
+       printf("Inheritable capabilities: ");
+       for (n = 0, i = 0; cap_valid(i); i++) {
+               if (caps->inheritable & CAP_TO_MASK(i)) {
+                       if (n)
+                               putchar(',');
+                       printcap(i);
+                       n++;
+               }
+       }
+       if (!n)
+               printf("[none]");
+       putchar('\n');
+
        free(gids);
+       free(caps);
        return 0;
 }
 
@@ -125,6 +231,8 @@ int setpriv_main(int argc UNUSED_PARAM, char **argv)
        argc -= optind;
        argv += optind;
 
+       initcaps();
+
        if (opts & OPT_DUMP) {
                if ((opts & ~OPT_DUMP) || argc)
                        bb_error_msg_and_die("setpriv: --dump is incompatible 
with all other options");
-- 
2.13.2

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to