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