df98bb
From 240c55f1526300daac640ef2c1f4941de4579493 Mon Sep 17 00:00:00 2001
df98bb
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
df98bb
Date: Thu, 9 Jul 2020 23:15:47 +0200
df98bb
Subject: [PATCH] basic/cap-list: parse/print numerical capabilities
df98bb
df98bb
We would refuse to print capabilities which were didn't have a name
df98bb
for. The kernel adds new capabilities from time to time, most recently
df98bb
cap_bpf. 'systmectl show -p CapabilityBoundingSet ...' would fail with
df98bb
"Failed to parse bus message: Invalid argument" because
df98bb
capability_set_to_string_alloc() would fail with -EINVAL. So let's
df98bb
print such capabilities in hexadecimal:
df98bb
df98bb
CapabilityBoundingSet=cap_chown cap_dac_override cap_dac_read_search
df98bb
  cap_fowner cap_fsetid cap_kill cap_setgid cap_setuid cap_setpcap
df98bb
  cap_linux_immutable cap_net_bind_service cap_net_broadcast cap_net_admin
df98bb
  cap_net_raw cap_ipc_lock cap_ipc_owner 0x10 0x11 0x12 0x13 0x14 0x15 0x16
df98bb
  0x17 0x18 0x19 0x1a ...
df98bb
df98bb
For symmetry, also allow capabilities that we don't know to be specified.
df98bb
df98bb
Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1853736.
df98bb
df98bb
(cherry picked from commit 417770f3033c426ca848b158d0bf057cd8ad1329)
df98bb
df98bb
Resolves: #1946943
df98bb
---
df98bb
 src/basic/cap-list.c     | 10 +++++++---
df98bb
 src/test/test-cap-list.c |  4 +++-
df98bb
 2 files changed, 10 insertions(+), 4 deletions(-)
df98bb
df98bb
diff --git a/src/basic/cap-list.c b/src/basic/cap-list.c
df98bb
index bfcda33520..56a81c7dfc 100644
df98bb
--- a/src/basic/cap-list.c
df98bb
+++ b/src/basic/cap-list.c
df98bb
@@ -10,6 +10,7 @@
df98bb
 #include "macro.h"
df98bb
 #include "missing.h"
df98bb
 #include "parse-util.h"
df98bb
+#include "stdio-util.h"
df98bb
 #include "util.h"
df98bb
 
df98bb
 static const struct capability_name* lookup_capability(register const char *str, register GPERF_LEN_TYPE len);
df98bb
@@ -37,7 +38,7 @@ int capability_from_name(const char *name) {
df98bb
         /* Try to parse numeric capability */
df98bb
         r = safe_atoi(name, &i);
df98bb
         if (r >= 0) {
df98bb
-                if (i >= 0 && i < (int) ELEMENTSOF(capability_names))
df98bb
+                if (i >= 0 && i < 64)
df98bb
                         return i;
df98bb
                 else
df98bb
                         return -EINVAL;
df98bb
@@ -65,11 +66,14 @@ int capability_set_to_string_alloc(uint64_t set, char **s) {
df98bb
         for (i = 0; i < cap_last_cap(); i++)
df98bb
                 if (set & (UINT64_C(1) << i)) {
df98bb
                         const char *p;
df98bb
+                        char buf[2 + 16 + 1];
df98bb
                         size_t add;
df98bb
 
df98bb
                         p = capability_to_name(i);
df98bb
-                        if (!p)
df98bb
-                                return -EINVAL;
df98bb
+                        if (!p) {
df98bb
+                                xsprintf(buf, "0x%lx", i);
df98bb
+                                p = buf;
df98bb
+                        }
df98bb
 
df98bb
                         add = strlen(p);
df98bb
 
df98bb
diff --git a/src/test/test-cap-list.c b/src/test/test-cap-list.c
df98bb
index de5fa729cc..84bbb7b7e7 100644
df98bb
--- a/src/test/test-cap-list.c
df98bb
+++ b/src/test/test-cap-list.c
df98bb
@@ -30,6 +30,8 @@ static void test_cap_list(void) {
df98bb
         assert_se(capability_from_name("cAp_aUdIt_rEAd") == CAP_AUDIT_READ);
df98bb
         assert_se(capability_from_name("0") == 0);
df98bb
         assert_se(capability_from_name("15") == 15);
df98bb
+        assert_se(capability_from_name("63") == 63);
df98bb
+        assert_se(capability_from_name("64") == -EINVAL);
df98bb
         assert_se(capability_from_name("-1") == -EINVAL);
df98bb
 
df98bb
         for (i = 0; i < capability_list_length(); i++) {
df98bb
@@ -64,7 +66,7 @@ static void test_capability_set_one(uint64_t c, const char *t) {
df98bb
 
df98bb
         free(t1);
df98bb
         assert_se(t1 = strjoin("'cap_chown cap_dac_override' \"cap_setgid cap_setuid\"", t,
df98bb
-                               " hogehoge foobar 12345 3.14 -3 ", t));
df98bb
+                               " hogehoge foobar 18446744073709551616 3.14 -3 ", t));
df98bb
         assert_se(capability_set_from_string(t1, &c1) == 0);
df98bb
         assert_se(c1 == c_masked);
df98bb
 }