]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
basic: secure_bits_to_strv()
authorIvan Kruglov <mail@ikruglov.com>
Thu, 9 Oct 2025 13:42:35 +0000 (06:42 -0700)
committerIvan Kruglov <mail@ikruglov.com>
Thu, 16 Oct 2025 10:29:14 +0000 (03:29 -0700)
src/shared/securebits-util.c
src/shared/securebits-util.h
src/test/test-secure-bits.c

index 92c7415337e8a023055601d27f9a752a68038fb7..783953aa6045c8a7b6654ddbfbb413cc4dbf8acb 100644 (file)
@@ -6,30 +6,71 @@
 #include "extract-word.h"
 #include "securebits-util.h"
 #include "string-util.h"
+#include "strv.h"
 
-int secure_bits_to_string_alloc(int i, char **s) {
-        _cleanup_free_ char *str = NULL;
-        size_t len;
+static inline const char* secure_bit_to_string(int i) {
+        /* match a single bit */
+
+        switch (i) {
+                case SECURE_KEEP_CAPS:
+                        return "keep-caps";
+                case SECURE_KEEP_CAPS_LOCKED:
+                        return "keep-caps-locked";
+                case SECURE_NO_SETUID_FIXUP:
+                        return "no-setuid-fixup";
+                case SECURE_NO_SETUID_FIXUP_LOCKED:
+                        return "no-setuid-fixup-locked";
+                case SECURE_NOROOT:
+                        return "noroot";
+                case SECURE_NOROOT_LOCKED:
+                        return "noroot-locked";
+                default:
+                        assert_not_reached();
+        }
+}
+
+int secure_bits_to_string_alloc(int i, char **ret) {
+        _cleanup_strv_free_ char **sv = NULL;
+        _cleanup_free_ char *joined = NULL;
         int r;
 
-        assert(s);
+        assert(ret);
 
-        r = asprintf(&str, "%s%s%s%s%s%s",
-                     (i & (1 << SECURE_KEEP_CAPS)) ? "keep-caps " : "",
-                     (i & (1 << SECURE_KEEP_CAPS_LOCKED)) ? "keep-caps-locked " : "",
-                     (i & (1 << SECURE_NO_SETUID_FIXUP)) ? "no-setuid-fixup " : "",
-                     (i & (1 << SECURE_NO_SETUID_FIXUP_LOCKED)) ? "no-setuid-fixup-locked " : "",
-                     (i & (1 << SECURE_NOROOT)) ? "noroot " : "",
-                     (i & (1 << SECURE_NOROOT_LOCKED)) ? "noroot-locked " : "");
+        r = secure_bits_to_strv(i, &sv);
         if (r < 0)
+                return r;
+
+        joined = strv_join(sv, " ");
+        if (!joined)
                 return -ENOMEM;
 
-        len = strlen(str);
-        if (len != 0)
-                str[len - 1] = '\0';
+        *ret = TAKE_PTR(joined);
+        return 0;
+}
+
+int secure_bits_to_strv(int i, char ***ret) {
+        _cleanup_strv_free_ char **sv = NULL;
+        static const int bits[] = {
+                SECURE_KEEP_CAPS,
+                SECURE_KEEP_CAPS_LOCKED,
+                SECURE_NO_SETUID_FIXUP,
+                SECURE_NO_SETUID_FIXUP_LOCKED,
+                SECURE_NOROOT,
+                SECURE_NOROOT_LOCKED,
+        };
+        int r;
 
-        *s = TAKE_PTR(str);
+        assert(ret);
+
+        FOREACH_ELEMENT(bit, bits) {
+                if (i & (1 << *bit)) {
+                        r = strv_extend(&sv, secure_bit_to_string(*bit));
+                        if (r < 0)
+                                return r;
+                }
+        }
 
+        *ret = TAKE_PTR(sv);
         return 0;
 }
 
index 19b836b4e7b5a8f97785c83f21fd192f886758f0..553b717a5762e89ef6dc2d624e7fdd2e83247620 100644 (file)
@@ -5,7 +5,8 @@
 
 #include "forward.h"
 
-int secure_bits_to_string_alloc(int i, char **s);
+int secure_bits_to_strv(int i, char ***ret);
+int secure_bits_to_string_alloc(int i, char **ret);
 int secure_bits_from_string(const char *s);
 
 static inline bool secure_bits_is_valid(int i) {
index 37771d0ce8719c06c0652095de1d8ee14c9a0f1f..d217876e2c08f0becbd6b1c0cea6b68a2e575595 100644 (file)
@@ -15,20 +15,27 @@ static const char * const string_bits[] = {
 };
 
 TEST(secure_bits_basic) {
-        _cleanup_free_ char *joined = NULL, *str = NULL;
+        _cleanup_free_ char *joined = NULL, *str = NULL, *joined_ssv = NULL;
+        _cleanup_strv_free_ char **ssv = NULL;
         int r;
 
         /* Check if converting each bit from string and back to string yields
          * the same value */
         STRV_FOREACH(bit, string_bits) {
                 _cleanup_free_ char *s = NULL;
+                _cleanup_strv_free_ char **sv = NULL;
 
                 r = secure_bits_from_string(*bit);
                 assert_se(r > 0);
                 assert_se(secure_bits_is_valid(r));
+
                 assert_se(secure_bits_to_string_alloc(r, &s) >= 0);
                 printf("%s = 0x%x = %s\n", *bit, (unsigned)r, s);
                 ASSERT_STREQ(*bit, s);
+
+                ASSERT_OK(secure_bits_to_strv(r, &sv));
+                ASSERT_EQ(strv_length(sv), (size_t) 1);
+                ASSERT_STREQ(*bit, sv[0]);
         }
 
         /* Ditto, but with all bits at once */
@@ -41,7 +48,12 @@ TEST(secure_bits_basic) {
         printf("%s = 0x%x = %s\n", joined, (unsigned)r, str);
         ASSERT_STREQ(joined, str);
 
+        ASSERT_OK(secure_bits_to_strv(r, &ssv));
+        joined_ssv = strv_join(ssv, " ");
+        ASSERT_STREQ(joined, joined_ssv);
+
         str = mfree(str);
+        ssv = strv_free(ssv);
 
         /* Empty string */
         assert_se(secure_bits_from_string("") == 0);
@@ -51,8 +63,10 @@ TEST(secure_bits_basic) {
         assert_se(secure_bits_from_string("foo bar baz") == 0);
 
         /* Empty secure bits */
-        assert_se(secure_bits_to_string_alloc(0, &str) >= 0);
-        assert_se(isempty(str));
+        ASSERT_OK(secure_bits_to_string_alloc(0, &str));
+        ASSERT_TRUE(isempty(str));
+        ASSERT_OK(secure_bits_to_strv(0, &ssv));
+        ASSERT_TRUE(strv_isempty(ssv));
 
         str = mfree(str);