From: Michael Tremer Date: Sat, 18 Mar 2023 17:11:45 +0000 (+0000) Subject: file: Read capabilities X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c2fe443d8b9ca8fcfca0a88a4c52c86c945dd2c5;p=people%2Fstevee%2Fpakfire.git file: Read capabilities Signed-off-by: Michael Tremer --- diff --git a/src/libpakfire/file.c b/src/libpakfire/file.c index cc5054a1..5b5e1b6b 100644 --- a/src/libpakfire/file.c +++ b/src/libpakfire/file.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -73,6 +74,9 @@ struct pakfire_file { // Stat struct stat st; + // Capabilities + cap_t caps; + // Flags int flags; @@ -96,11 +100,127 @@ struct pakfire_file { int issues; int check_done:1; - #warning TODO capabilities, data - // capabilities + #warning TODO data //int is_datafile; }; +/* + Capabilities +*/ +static int pakfire_file_read_fcaps(struct pakfire_file* file, + const struct vfs_cap_data* cap_data, size_t length) { + int max = 0; + int r; + + uint32_t magic_etc = le32toh(cap_data->magic_etc); + + // Which version are we dealing with? + switch (magic_etc & VFS_CAP_REVISION_MASK) { + case VFS_CAP_REVISION_1: + length -= XATTR_CAPS_SZ_1; + max = VFS_CAP_U32_1; + break; + + case VFS_CAP_REVISION_2: + length -= XATTR_CAPS_SZ_2; + max = VFS_CAP_U32_2; + break; + + case VFS_CAP_REVISION_3: + length -= XATTR_CAPS_SZ_3; + max = VFS_CAP_U32_3; + break; + + // Unknown version + default: + errno = EINVAL; + return 1; + } + + // Check if we have received the correct data + if (length) { + errno = EINVAL; + return 1; + } + + // Allocate capabilities + file->caps = cap_init(); + if (!file->caps) { + ERROR(file->pakfire, "Could not allocate capabilities: %m\n"); + r = 1; + goto ERROR; + } + + int mask; + int index; + + int cap_permitted; + int cap_inheritable; + int cap_effective = 0; + + for (unsigned int cap = 0; cap_valid(cap); cap++) { + // Find the index where to find this cap + index = CAP_TO_INDEX(cap); + mask = CAP_TO_MASK(cap); + + // End if we have reached the end of the data + if (index > max) + break; + + // Check for permitted/inheritable flag set + cap_permitted = le32toh(cap_data->data[index].permitted) & mask; + cap_inheritable = le32toh(cap_data->data[index].inheritable) & mask; + + // Check for effective + if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE) + cap_effective = cap_permitted | cap_inheritable; + + cap_value_t caps[] = { cap }; + + if (cap_permitted) { + r = cap_set_flag(file->caps, CAP_PERMITTED, 1, caps, CAP_SET); + if (r) { + ERROR(file->pakfire, "Could not set capability %d: %m\n", cap); + goto ERROR; + } + } + + if (cap_inheritable) { + r = cap_set_flag(file->caps, CAP_INHERITABLE, 1, caps, CAP_SET); + if (r) { + ERROR(file->pakfire, "Could not set capability %d: %m\n", cap); + goto ERROR; + } + } + + if (cap_effective) { + r = cap_set_flag(file->caps, CAP_EFFECTIVE, 1, caps, CAP_SET); + if (r) { + ERROR(file->pakfire, "Could not set capability %d: %m\n", cap); + goto ERROR; + } + } + } + +#ifdef ENABLE_DEBUG + char* text = cap_to_text(file->caps, NULL); + if (text) { + DEBUG(file->pakfire, "%s: Capabilities %s\n", file->path, text); + cap_free(text); + } +#endif + + return 0; + +ERROR: + if (file->caps) { + cap_free(file->caps); + file->caps = NULL; + } + + return r; +} + static int pakfire_file_from_archive_entry(struct pakfire_file* file, struct archive_entry* entry) { char* buffer = NULL; const char* path = NULL; @@ -224,6 +344,12 @@ static int pakfire_file_from_archive_entry(struct pakfire_file* file, struct arc if (r) goto ERROR; + // Capabilities + } else if (strcmp(attr, "security.capability") == 0) { + r = pakfire_file_read_fcaps(file, value, size); + if (r) + goto ERROR; + } else { DEBUG(file->pakfire, "Received an unknown extended attribute: %s\n", attr); } @@ -424,6 +550,10 @@ ERROR: } static void pakfire_file_free(struct pakfire_file* file) { + // Free capabilities + if (file->caps) + cap_free(file->caps); + pakfire_unref(file->pakfire); free(file); }