#include <linux/limits.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/capability.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
// Stat
struct stat st;
+ // Capabilities
+ cap_t caps;
+
// Flags
int flags;
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;
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);
}
}
static void pakfire_file_free(struct pakfire_file* file) {
+ // Free capabilities
+ if (file->caps)
+ cap_free(file->caps);
+
pakfire_unref(file->pakfire);
free(file);
}