]> git.ipfire.org Git - people/ms/pakfire.git/blobdiff - src/libpakfire/file.c
file: Write capabilities
[people/ms/pakfire.git] / src / libpakfire / file.c
index 5b5e1b6b21e48a7a3003fc98788bc75e864ba781..756b9f913942f40283b15245152aff15b0236b96 100644 (file)
@@ -221,6 +221,66 @@ ERROR:
        return r;
 }
 
+int pakfire_file_write_fcaps(struct pakfire_file* file, struct vfs_cap_data* cap_data) {
+       cap_flag_value_t cap_permitted;
+       cap_flag_value_t cap_inheritable;
+       cap_flag_value_t cap_effective;
+       int r;
+
+       // This should not be called when we have no caps
+       if (!file->caps) {
+               errno = EINVAL;
+               return 1;
+       }
+
+       uint32_t magic = VFS_CAP_REVISION_2;
+
+       for (unsigned int cap = 0; cap_valid(cap); cap++) {
+               // Find the index where to find this cap
+               int index = CAP_TO_INDEX(cap);
+               int mask  = CAP_TO_MASK(cap);
+
+               // Fetch CAP_PERMITTED
+               r = cap_get_flag(file->caps, cap, CAP_PERMITTED, &cap_permitted);
+               if (r) {
+                       ERROR(file->pakfire, "Could not fetch capability %d: %m\n", cap);
+                       goto ERROR;
+               }
+
+               // Fetch CAP_INHERITABLE
+               r = cap_get_flag(file->caps, cap, CAP_INHERITABLE, &cap_inheritable);
+               if (r) {
+                       ERROR(file->pakfire, "Could not fetch capability %d: %m\n", cap);
+                       goto ERROR;
+               }
+
+               // Fetch CAP_EFFECTIVE
+               r = cap_get_flag(file->caps, cap, CAP_EFFECTIVE, &cap_effective);
+               if (r) {
+                       ERROR(file->pakfire, "Could not fetch capability %d: %m\n", cap);
+                       goto ERROR;
+               }
+
+               // Store CAP_PERMITTED
+               if (cap_permitted)
+                       cap_data->data[index].permitted |= htole32(mask);
+
+               // Store CAP_INHERITED
+               if (cap_inheritable)
+                       cap_data->data[index].inheritable |= htole32(mask);
+
+               // Set EFFECTIVE flag if CAP_EFFECTIVE is set
+               if (cap_effective)
+                       magic |= VFS_CAP_FLAGS_EFFECTIVE;
+       }
+
+       // Store the magic value
+       cap_data->magic_etc = htole32(magic);
+
+ERROR:
+       return r;
+}
+
 static int pakfire_file_from_archive_entry(struct pakfire_file* file, struct archive_entry* entry) {
        char* buffer = NULL;
        const char* path = NULL;
@@ -440,6 +500,7 @@ ERROR:
 }
 
 struct archive_entry* pakfire_file_archive_entry(struct pakfire_file* file, int digest_types) {
+       struct vfs_cap_data cap_data = {};
        const char* path = NULL;
        int r;
 
@@ -540,6 +601,19 @@ struct archive_entry* pakfire_file_archive_entry(struct pakfire_file* file, int
                archive_entry_xattr_add_entry(entry, "PAKFIRE.digests.sha2_256",
                        file->digests.sha2_256, sizeof(file->digests.sha2_256));
 
+       // Capabilities
+       if (file->caps) {
+               r = pakfire_file_write_fcaps(file, &cap_data);
+               if (r) {
+                       ERROR(file->pakfire, "Could not export capabilities: %m\n");
+                       goto ERROR;
+               }
+
+               // Store capabilities in archive entry
+               archive_entry_xattr_add_entry(entry,
+                       "security.capability", &cap_data, sizeof(cap_data));
+       }
+
        return entry;
 
 ERROR:
@@ -1113,6 +1187,38 @@ PAKFIRE_EXPORT int pakfire_file_set_digest(struct pakfire_file* file,
        return 0;
 }
 
+PAKFIRE_EXPORT int pakfire_file_has_caps(struct pakfire_file* file) {
+       if (file->caps)
+               return 1;
+
+       return 0;
+}
+
+PAKFIRE_EXPORT char* pakfire_file_get_caps(struct pakfire_file* file) {
+       char* copy = NULL;
+       char* text = NULL;
+       ssize_t length = 0;
+
+       if (file->caps) {
+               text = cap_to_text(file->caps, &length);
+               if (!text) {
+                       ERROR(file->pakfire, "Could not export capabilities: %m\n");
+                       goto ERROR;
+               }
+
+               // libcap is being weird and uses its own allocator so we have to copy the string
+               copy = strndup(text, length);
+               if (!copy)
+                       goto ERROR;
+       }
+
+ERROR:
+       if (text)
+               cap_free(text);
+
+       return copy;
+}
+
 static int pakfire_file_levels(struct pakfire_file* file) {
        if (!*file->path)
                return 0;