>From 644c0e75a5a4fd03ab1939e801633dcf2e3ccb20 Mon Sep 17 00:00:00 2001 From: John Johansen <[email protected]> Date: Thu, 16 Jul 2015 17:26:16 -0700 Subject: [PATCH 2/4] Add base function to query generic label data under a given key
Signed-off-by: John Johansen <[email protected]> --- libraries/libapparmor/doc/aa_query_label.pod | 6 ++ libraries/libapparmor/include/sys/apparmor.h | 22 +++++ libraries/libapparmor/src/kernel.c | 124 ++++++++++++++++++++++++++ libraries/libapparmor/src/libapparmor.map | 9 ++ libraries/libapparmor/swig/SWIG/libapparmor.i | 2 + 5 files changed, 163 insertions(+) diff --git a/libraries/libapparmor/doc/aa_query_label.pod b/libraries/libapparmor/doc/aa_query_label.pod index 900e2d0..8717df0 100644 --- a/libraries/libapparmor/doc/aa_query_label.pod +++ b/libraries/libapparmor/doc/aa_query_label.pod @@ -31,6 +31,9 @@ B<#include E<lt>sys/apparmor.hE<gt>> B<int aa_query_cmd(const char *cmd, size_t cmd_size, char *query, size_t size, char *buffer, size_t bsize);> +B<extern int aa_query_label_data(const char *label, const char *key, + char *buffer, size_t bsize);> + B<int aa_query_label(uint32_t mask, char *query, size_t size, int *allowed, int *audited);> @@ -57,6 +60,9 @@ Link with B<-lapparmor> when compiling. The aa_query_cmd function setup and does the raw query of the kernel. It is the basis of the other query_X functions. +The aa_query_label_data function does a raw query of any extra data +stored as I<key> in the label. + The aa_query_label function fetches the current permissions granted by the specified I<label> in the I<query> string. diff --git a/libraries/libapparmor/include/sys/apparmor.h b/libraries/libapparmor/include/sys/apparmor.h index 61629bc..b8d5601 100644 --- a/libraries/libapparmor/include/sys/apparmor.h +++ b/libraries/libapparmor/include/sys/apparmor.h @@ -98,6 +98,8 @@ extern int aa_getpeercon(int fd, char **label, char **mode); */ #define AA_QUERY_CMD_LABEL "label" #define AA_QUERY_CMD_LABEL_SIZE sizeof(AA_QUERY_CMD_LABEL) +#define AA_QUERY_CMD_DATA "data" +#define AA_QUERY_CMD_DATA_SIZE sizeof(AA_QUERY_CMD_DATA) extern int aa_query_cmd(const char *cmd, size_t cmd_size, char *query, size_t size, char *buffer, size_t bsize); @@ -115,6 +117,26 @@ extern int aa_query_link_path_len(const char *label, size_t label_len, extern int aa_query_link_path(const char *label, const char *target, const char *link, int *allowed, int *audited); + +typedef struct { + size_t n; /* length of s */ + const char *entry; /* not necessarily NULL-terminated */ +} aa_label_data_ent; + +typedef struct { + char *data; /* free data */ + size_t n; /* number of ents */ + aa_label_data_ent *ents; /* free vec of entries */ +} aa_label_data_info; + +extern int aa_query_label_data(const char *label, const char *key, + aa_label_data_info *out); +extern void aa_clear_label_data(aa_label_data_info *info); + + + + + #define __macroarg_counter(Y...) __macroarg_count1 ( , ##Y) #define __macroarg_count1(Y...) __macroarg_count2 (Y, 16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0) #define __macroarg_count2(_,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,n,Y...) n diff --git a/libraries/libapparmor/src/kernel.c b/libraries/libapparmor/src/kernel.c index 1de4e54..8371405 100644 --- a/libraries/libapparmor/src/kernel.c +++ b/libraries/libapparmor/src/kernel.c @@ -47,6 +47,7 @@ #define UNCONFINED "unconfined" #define UNCONFINED_SIZE strlen(UNCONFINED) + /** * aa_find_mountpoint - find where the apparmor interface filesystem is mounted * @mnt: returns buffer with the mountpoint string @@ -1030,3 +1031,126 @@ int aa_query_link_path(const char *label, const char *target, const char *link, strlen(target), link, strlen(link), allowed, audited); } + +/** + * aa_query_label_data_open - query + * @label: security label + * @key: key of data blob to lookup + * + * Returns: fd waiting to read data else -1 and sets errno. + * + * TODO: fold into calling fn??? + */ +static int aa_query_label_data_open(const char *label, const char *key) +{ + autofree char *query = NULL; + + size_t label_len = strlen(label); + size_t key_len = strlen(key); + + /* + 1s for null separators */ + size_t size = AA_QUERY_CMD_DATA_SIZE + label_len + 1 + key_len + 1; + query = malloc(size + 1); + if (!query) + return -1; + memcpy(query + AA_QUERY_CMD_DATA_SIZE, label, label_len + 1); + memcpy(query + AA_QUERY_CMD_DATA_SIZE + label_len + 1, key, key_len + 1); + return aa_query_cmd_open(AA_QUERY_CMD_DATA, AA_QUERY_CMD_DATA_SIZE, query, + size); +} + +/** + * aa_query_label_data - query data associated with @key for @label + * @key: key of data blob to get data for + * @out: data found if any + * + * Returns: ???? + * + * This fn will extract any data associated with @key in @label. Since + * @label is a compound label there maybe multiple data items associated + * with the key (up to one per profile). The data items are broken out into + * an ??? + * + * When multiple items are returned for @key, this function does not + * provide any indication of which subcomponents of the @label the data + * belonged to. To obtain that information use the compound label iterator + * and call this function once for each iteration. + */ +int aa_query_label_data(const char *label, const char *key, aa_data_info *out) +{ + autoclose FILE *file = NULL; + const char *p; + uint32_t bytes; + uint32_t tmp; + int fd, ret; + + if (!out) + return 0; /* this should probably be an error ??? */ + + memset(out, 0, sizeof(*out)); + + /* TODO: fold in if not being used else where */ + fd = aa_query_label_data_open(label, key); + if (fd == -1) + return -1; + + file = fdopen(fd, "r+"); + if (!file) + return -1; + + /* TODO: ??? kernel transaction file only support a page size of + * data. Is it worth doing 2 reads to get the data size + * allocated correct? + * Or is it better to just do a single read to a page size + * buffer and then allocate. + */ + if (fread(&tmp, sizeof(tmp), 1, file) != 1) { + errno = EPROTO; + goto done; + } + + bytes = le32toh(tmp); + out->data = malloc(bytes); + if (!out->data) { + errno = ENOMEM; + goto done; + } + + if (fread(out->data, sizeof(char), bytes, file) != bytes) { + errno = EPROTO; + goto done; + } + + p = out->data; + memcpy(&tmp, p, sizeof(tmp)); + out->n = le32toh(tmp); + p += sizeof(tmp); + + out->ents = malloc(out->n * sizeof(*out->ents)); + if (!out->p) { + errno = ENOMEM; + goto done; + } + + for (int i = 0; i < out->n; i++) { + memcpy(&tmp, p, sizeof(tmp)); + out->ents[i].n = le32toh(tmp); + p += sizeof(tmp); + out->ents[i].entry = p; + p += out->entry[i].n; + } + +done: + if (errno) + aa_clear_data_info(out); + + return errno ? -1 : 0; +} + +void aa_clear_label_data(aa_label_data_info *info) +{ + free(info->ents); + free(info->data); + + memset(info, 0, sizeof(*info)); +} diff --git a/libraries/libapparmor/src/libapparmor.map b/libraries/libapparmor/src/libapparmor.map index 98d97ea..9ce35ab 100644 --- a/libraries/libapparmor/src/libapparmor.map +++ b/libraries/libapparmor/src/libapparmor.map @@ -87,6 +87,15 @@ APPARMOR_2.10 { *; } APPARMOR_2.9; +APPARMOR_2.10 { + global: + aa_query_label_data; + aa_clear_label_data; + local: + *; +} APPARMOR_2.10; + + PRIVATE { global: _aa_is_blacklisted; diff --git a/libraries/libapparmor/swig/SWIG/libapparmor.i b/libraries/libapparmor/swig/SWIG/libapparmor.i index 3e1950a..7908e07 100644 --- a/libraries/libapparmor/swig/SWIG/libapparmor.i +++ b/libraries/libapparmor/swig/SWIG/libapparmor.i @@ -70,5 +70,7 @@ extern int aa_query_link_path_len(const char *label, size_t label_len, int *allowed, int *audited); extern int aa_query_link_path(const char *label, const char *target, const char *link, int *allowed, int *audited); +extern int aa_query_label_data(const char *label, const char *key, + char *buffer, size_t bsize); %exception; -- 2.1.4 -- AppArmor mailing list [email protected] Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
