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