static int __pakfire_extract(struct pakfire* pakfire, struct archive* a,
struct archive_entry* entry, void* p) {
struct pakfire_file* file = NULL;
+ struct vfs_cap_data cap_data = {};
char buffer[PATH_MAX];
int r;
// Remove any extended attributes which we never write to disk
archive_entry_xattr_clear(entry);
+ // Set capabilities
+ if (pakfire_file_has_caps(file)) {
+ r = pakfire_file_write_fcaps(file, &cap_data);
+ if (r)
+ goto ERROR;
+
+ // Store capabilities in archive entry
+ archive_entry_xattr_add_entry(entry, "security.capability",
+ &cap_data, sizeof(cap_data));
+ }
+
// Write payload
r = archive_read_extract2(data->archive, entry, data->writer);
switch (r) {
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;
}
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;
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:
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;
int pakfire_file_set_digest(struct pakfire_file* file,
const enum pakfire_digest_types type, const unsigned char* digest, const size_t length);
+// Capabilities
+int pakfire_file_has_caps(struct pakfire_file* file);
+char* pakfire_file_get_caps(struct pakfire_file* file);
+
// MIME Type
const char* pakfire_file_get_mimetype(struct pakfire_file* file);
int pakfire_file_set_mimetype(struct pakfire_file* file, const char* mimetype);
#include <archive_entry.h>
+#include <sys/capability.h>
+
enum pakfire_file_classes {
PAKFIRE_FILE_UNKNOWN = 0,
PAKFIRE_FILE_RUNTIME_LINKER = (1 << 14),
};
+int pakfire_file_write_fcaps(struct pakfire_file* file, struct vfs_cap_data* cap_data);
+
int pakfire_file_create_from_path(struct pakfire_file** file,
struct pakfire* pakfire, const char* path);
int pakfire_file_create_from_archive_entry(struct pakfire_file** file, struct pakfire* pakfire,