libsepol: Support nlmsg extended permissions

Add support for AVTAB_XPERMS_NLMSG as extended permissions for netlink
sockets. The behaviour is similar to the existing
AVTAB_XPERMS_IOCTLFUNCTION.

Signed-off-by: Thiébaud Weksteen <tweek@google.com>
Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
This commit is contained in:
Thiébaud Weksteen 2024-08-22 10:37:56 +10:00 committed by James Carter
parent 5421320d3a
commit ba7945a250
16 changed files with 200 additions and 41 deletions

View File

@ -2342,8 +2342,8 @@ static int avrule_ioctl_completedriver(struct av_xperm_range_list *rangelist,
return 0;
}
static int avrule_ioctl_func(struct av_xperm_range_list *rangelist,
av_extended_perms_t **extended_perms, unsigned int driver)
static int avrule_xperm_func(struct av_xperm_range_list *rangelist,
av_extended_perms_t **extended_perms, unsigned int driver, uint8_t specified)
{
struct av_xperm_range_list *r;
av_extended_perms_t *xperms;
@ -2379,7 +2379,7 @@ static int avrule_ioctl_func(struct av_xperm_range_list *rangelist,
high = IOC_FUNC(high);
avrule_xperm_setrangebits(low, high, xperms);
xperms->driver = driver;
xperms->specified = AVRULE_XPERMS_IOCTLFUNCTION;
xperms->specified = specified;
r = r->next;
}
@ -2495,7 +2495,61 @@ static int define_te_avtab_ioctl(const avrule_t *avrule_template)
*/
i = 0;
while (xperms_for_each_bit(&i, partial_driver)) {
if (avrule_ioctl_func(rangelist, &xperms, i))
if (avrule_xperm_func(rangelist, &xperms, i, AVRULE_XPERMS_IOCTLFUNCTION))
return -1;
if (xperms) {
avrule = (avrule_t *) calloc(1, sizeof(avrule_t));
if (!avrule) {
yyerror("out of memory");
return -1;
}
if (avrule_cpy(avrule, avrule_template))
return -1;
avrule->xperms = xperms;
append_avrule(avrule);
}
}
done:
if (partial_driver)
free(partial_driver);
while (rangelist != NULL) {
r = rangelist;
rangelist = rangelist->next;
free(r);
}
return 0;
}
static int define_te_avtab_netlink(const avrule_t *avrule_template)
{
avrule_t *avrule;
struct av_xperm_range_list *rangelist, *r;
av_extended_perms_t *partial_driver, *xperms;
unsigned int i;
/* organize ranges */
if (avrule_xperm_ranges(&rangelist))
return -1;
/* flag driver codes that are partially enabled */
if (avrule_xperm_partialdriver(rangelist, NULL, &partial_driver))
return -1;
if (!partial_driver || !avrule_xperms_used(partial_driver))
goto done;
/*
* create rule for each partially used driver codes
* "partially used" meaning that the code number e.g. socket 0x89
* has some permission bits set and others not set.
*/
i = 0;
while (xperms_for_each_bit(&i, partial_driver)) {
if (avrule_xperm_func(rangelist, &xperms, i, AVRULE_XPERMS_NLMSG))
return -1;
if (xperms) {
@ -2546,6 +2600,8 @@ int define_te_avtab_extended_perms(int which)
id = queue_remove(id_queue);
if (strcmp(id,"ioctl") == 0) {
rc = define_te_avtab_ioctl(avrule_template);
} else if (strcmp(id,"nlmsg") == 0) {
rc = define_te_avtab_netlink(avrule_template);
} else {
yyerror2("only ioctl extended permissions are supported, found %s", id);
rc = -1;

View File

@ -353,6 +353,8 @@ static int display_avrule(avrule_t * avrule, policydb_t * policy,
xperms.specified = AVTAB_XPERMS_IOCTLFUNCTION;
else if (avrule->xperms->specified == AVRULE_XPERMS_IOCTLDRIVER)
xperms.specified = AVTAB_XPERMS_IOCTLDRIVER;
else if (avrule->xperms->specified == AVRULE_XPERMS_NLMSG)
xperms.specified = AVTAB_XPERMS_NLMSG;
else {
fprintf(fp, " ERROR: no valid xperms specified\n");
return -1;

View File

@ -221,6 +221,7 @@ char *CIL_KEY_DONTAUDITX;
char *CIL_KEY_NEVERALLOWX;
char *CIL_KEY_PERMISSIONX;
char *CIL_KEY_IOCTL;
char *CIL_KEY_NLMSG;
char *CIL_KEY_UNORDERED;
char *CIL_KEY_SRC_INFO;
char *CIL_KEY_SRC_CIL;
@ -393,6 +394,7 @@ static void cil_init_keys(void)
CIL_KEY_NEVERALLOWX = cil_strpool_add("neverallowx");
CIL_KEY_PERMISSIONX = cil_strpool_add("permissionx");
CIL_KEY_IOCTL = cil_strpool_add("ioctl");
CIL_KEY_NLMSG = cil_strpool_add("nlmsg");
CIL_KEY_UNORDERED = cil_strpool_add("unordered");
CIL_KEY_SRC_INFO = cil_strpool_add("<src_info>");
CIL_KEY_SRC_CIL = cil_strpool_add("cil");

View File

@ -66,6 +66,7 @@ struct cil_args_binary {
int pass;
hashtab_t role_trans_table;
hashtab_t avrulex_ioctl_table;
hashtab_t avrulex_nlmsg_table;
void **type_value_to_cil;
};
@ -1671,11 +1672,22 @@ static void __avrule_xperm_setrangebits(uint16_t low, uint16_t high, struct avta
}
}
static char* __cil_xperm_kind_to_str(uint32_t xperm_kind)
{
switch (xperm_kind) {
case CIL_PERMX_KIND_IOCTL:
return CIL_KEY_IOCTL;
case CIL_PERMX_KIND_NLMSG:
return CIL_KEY_NLMSG;
default:
return (char *) "unknown";
}
}
#define IOC_DRIV(x) (x >> 8)
#define IOC_FUNC(x) (x & 0xff)
static int __cil_permx_bitmap_to_sepol_xperms_list(ebitmap_t *xperms, struct cil_list **xperms_list)
static int __cil_permx_bitmap_to_sepol_xperms_list(uint32_t kind, ebitmap_t *xperms, struct cil_list **xperms_list)
{
ebitmap_node_t *node;
unsigned int i;
@ -1705,7 +1717,7 @@ static int __cil_permx_bitmap_to_sepol_xperms_list(ebitmap_t *xperms, struct cil
high = i;
start_new_range = 1;
if (IOC_FUNC(low) == 0x00 && IOC_FUNC(high) == 0xff) {
if (kind == CIL_PERMX_KIND_IOCTL && IOC_FUNC(low) == 0x00 && IOC_FUNC(high) == 0xff) {
if (!complete) {
complete = cil_calloc(1, sizeof(*complete));
complete->driver = 0x0;
@ -1722,7 +1734,14 @@ static int __cil_permx_bitmap_to_sepol_xperms_list(ebitmap_t *xperms, struct cil
if (!partial) {
partial = cil_calloc(1, sizeof(*partial));
partial->driver = IOC_DRIV(low);
partial->specified = AVTAB_XPERMS_IOCTLFUNCTION;
switch (kind) {
case CIL_PERMX_KIND_IOCTL:
partial->specified = AVTAB_XPERMS_IOCTLFUNCTION;
break;
case CIL_PERMX_KIND_NLMSG:
partial->specified = AVTAB_XPERMS_NLMSG;
break;
}
}
__avrule_xperm_setrangebits(IOC_FUNC(low), IOC_FUNC(high), partial);
@ -1740,7 +1759,7 @@ static int __cil_permx_bitmap_to_sepol_xperms_list(ebitmap_t *xperms, struct cil
return SEPOL_OK;
}
static int __cil_avrulex_ioctl_to_policydb(hashtab_key_t k, hashtab_datum_t datum, void *args)
static int __cil_avrulex_xperm_to_policydb(hashtab_key_t k, hashtab_datum_t datum, uint32_t xperm_kind, void *args)
{
int rc = SEPOL_OK;
struct policydb *pdb;
@ -1750,6 +1769,7 @@ static int __cil_avrulex_ioctl_to_policydb(hashtab_key_t k, hashtab_datum_t datu
struct cil_list_item *item;
class_datum_t *sepol_obj;
uint32_t data = 0;
char *kind = NULL;
avtab_key = (avtab_key_t *)k;
pdb = args;
@ -1759,13 +1779,14 @@ static int __cil_avrulex_ioctl_to_policydb(hashtab_key_t k, hashtab_datum_t datu
// setting the data for an extended avtab isn't really necessary because
// it is ignored by the kernel. However, neverallow checking requires that
// the data value be set, so set it for that to work.
rc = __perm_str_to_datum(CIL_KEY_IOCTL, sepol_obj, &data);
kind = __cil_xperm_kind_to_str(xperm_kind);
rc = __perm_str_to_datum(kind, sepol_obj, &data);
if (rc != SEPOL_OK) {
goto exit;
}
avtab_datum.data = data;
rc = __cil_permx_bitmap_to_sepol_xperms_list(datum, &xperms_list);
rc = __cil_permx_bitmap_to_sepol_xperms_list(xperm_kind, datum, &xperms_list);
if (rc != SEPOL_OK) {
goto exit;
}
@ -1790,7 +1811,15 @@ exit:
return rc;
}
static int __cil_avrulex_ioctl_to_hashtable(hashtab_t h, uint16_t kind, uint32_t src, uint32_t tgt, uint32_t obj, ebitmap_t *xperms)
static int __cil_avrulex_ioctl_to_policydb(hashtab_key_t k, hashtab_datum_t datum, void *args) {
return __cil_avrulex_xperm_to_policydb(k, datum, CIL_PERMX_KIND_IOCTL, args);
}
static int __cil_avrulex_nlmsg_to_policydb(hashtab_key_t k, hashtab_datum_t datum, void *args) {
return __cil_avrulex_xperm_to_policydb(k, datum, CIL_PERMX_KIND_NLMSG, args);
}
static int __cil_avrulex_xperm_to_hashtable(hashtab_t h, uint16_t kind, uint32_t src, uint32_t tgt, uint32_t obj, ebitmap_t *xperms)
{
uint16_t specified;
avtab_key_t *avtab_key;
@ -1870,7 +1899,11 @@ static int __cil_avrulex_to_hashtable_helper(policydb_t *pdb, uint16_t kind, str
switch (permx->kind) {
case CIL_PERMX_KIND_IOCTL:
rc = __cil_avrulex_ioctl_to_hashtable(args->avrulex_ioctl_table, kind, sepol_src->s.value, sepol_tgt->s.value, sepol_obj->s.value, permx->perms);
rc = __cil_avrulex_xperm_to_hashtable(args->avrulex_ioctl_table, kind, sepol_src->s.value, sepol_tgt->s.value, sepol_obj->s.value, permx->perms);
if (rc != SEPOL_OK) goto exit;
break;
case CIL_PERMX_KIND_NLMSG:
rc = __cil_avrulex_xperm_to_hashtable(args->avrulex_nlmsg_table, kind, sepol_src->s.value, sepol_tgt->s.value, sepol_obj->s.value, permx->perms);
if (rc != SEPOL_OK) goto exit;
break;
default:
@ -2037,7 +2070,7 @@ exit:
return rc;
}
static int __cil_avrulex_ioctl_destroy(hashtab_key_t k, hashtab_datum_t datum, __attribute__((unused)) void *args)
static int __cil_avrulex_xperm_destroy(hashtab_key_t k, hashtab_datum_t datum, __attribute__((unused)) void *args)
{
free(k);
ebitmap_destroy(datum);
@ -4630,6 +4663,9 @@ static int __cil_permx_to_sepol_class_perms(policydb_t *pdb, struct cil_permissi
case CIL_PERMX_KIND_IOCTL:
perm_str = CIL_KEY_IOCTL;
break;
case CIL_PERMX_KIND_NLMSG:
perm_str = CIL_KEY_NLMSG;
break;
default:
rc = SEPOL_ERR;
goto exit;
@ -4769,17 +4805,10 @@ static void __cil_print_classperm(struct cil_list *cp_list)
static void __cil_print_permissionx(struct cil_permissionx *px)
{
const char *kind_str = "";
const char *kind_str = NULL;
char *expr_str;
switch (px->kind) {
case CIL_PERMX_KIND_IOCTL:
kind_str = CIL_KEY_IOCTL;
break;
default:
kind_str = "unknown";
break;
}
kind_str = __cil_xperm_kind_to_str(px->kind);
__cil_expr_to_string(px->expr_str, CIL_PERMISSIONX, &expr_str);
@ -4928,7 +4957,7 @@ static int cil_check_neverallow(const struct cil_db *db, policydb_t *pdb, struct
goto exit;
}
rc = __cil_permx_bitmap_to_sepol_xperms_list(cil_rule->perms.x.permx->perms, &xperms);
rc = __cil_permx_bitmap_to_sepol_xperms_list(cil_rule->perms.x.permx->kind, cil_rule->perms.x.permx->perms, &xperms);
if (rc != SEPOL_OK) {
goto exit;
}
@ -5137,6 +5166,7 @@ int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *p
struct cil_list *neverallows = NULL;
hashtab_t role_trans_table = NULL;
hashtab_t avrulex_ioctl_table = NULL;
hashtab_t avrulex_nlmsg_table = NULL;
void **type_value_to_cil = NULL;
struct cil_class **class_value_to_cil = NULL;
struct cil_perm ***perm_value_to_cil = NULL;
@ -5184,6 +5214,12 @@ int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *p
goto exit;
}
avrulex_nlmsg_table = hashtab_create(avrulex_hash, avrulex_compare, AVRULEX_TABLE_SIZE);
if (!avrulex_nlmsg_table) {
cil_log(CIL_INFO, "Failure to create hashtab for avrulex\n");
goto exit;
}
cil_list_init(&neverallows, CIL_LIST_ITEM);
extra_args.db = db;
@ -5191,6 +5227,7 @@ int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *p
extra_args.neverallows = neverallows;
extra_args.role_trans_table = role_trans_table;
extra_args.avrulex_ioctl_table = avrulex_ioctl_table;
extra_args.avrulex_nlmsg_table = avrulex_nlmsg_table;
extra_args.type_value_to_cil = type_value_to_cil;
for (i = 1; i <= 3; i++) {
@ -5216,6 +5253,11 @@ int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *p
cil_log(CIL_INFO, "Failure creating avrulex rules\n");
goto exit;
}
rc = hashtab_map(avrulex_nlmsg_table, __cil_avrulex_nlmsg_to_policydb, pdb);
if (rc != SEPOL_OK) {
cil_log(CIL_INFO, "Failure creating avrulex rules\n");
goto exit;
}
}
}
@ -5287,8 +5329,10 @@ int cil_binary_create_allocated_pdb(const struct cil_db *db, sepol_policydb_t *p
exit:
hashtab_destroy(role_trans_table);
hashtab_map(avrulex_ioctl_table, __cil_avrulex_ioctl_destroy, NULL);
hashtab_map(avrulex_ioctl_table, __cil_avrulex_xperm_destroy, NULL);
hashtab_destroy(avrulex_ioctl_table);
hashtab_map(avrulex_nlmsg_table, __cil_avrulex_xperm_destroy, NULL);
hashtab_destroy(avrulex_nlmsg_table);
free(type_value_to_cil);
free(class_value_to_cil);
if (perm_value_to_cil != NULL) {

View File

@ -2153,8 +2153,10 @@ static int cil_fill_permissionx(struct cil_tree_node *parse_current, struct cil_
if (parse_current->data == CIL_KEY_IOCTL) {
permx->kind = CIL_PERMX_KIND_IOCTL;
} else if (parse_current->data == CIL_KEY_NLMSG) {
permx->kind = CIL_PERMX_KIND_NLMSG;
} else {
cil_log(CIL_ERR, "Unknown permissionx kind, %s. Must be \"ioctl\"\n", (char *)parse_current->data);
cil_log(CIL_ERR, "Unknown permissionx kind, %s. Must be \"ioctl\" or \"nlmsg\"\n", (char *)parse_current->data);
rc = SEPOL_ERR;
goto exit;
}

View File

@ -238,6 +238,7 @@ extern char *CIL_KEY_DONTAUDITX;
extern char *CIL_KEY_NEVERALLOWX;
extern char *CIL_KEY_PERMISSIONX;
extern char *CIL_KEY_IOCTL;
extern char *CIL_KEY_NLMSG;
extern char *CIL_KEY_UNORDERED;
extern char *CIL_KEY_SRC_INFO;
extern char *CIL_KEY_SRC_CIL;
@ -636,6 +637,7 @@ struct cil_avrule {
};
#define CIL_PERMX_KIND_IOCTL 1
#define CIL_PERMX_KIND_NLMSG 2
struct cil_permissionx {
struct cil_symtab_datum datum;
uint32_t kind;

View File

@ -1112,6 +1112,8 @@ static void cil_xperms_to_policy(FILE *out, struct cil_permissionx *permx)
if (permx->kind == CIL_PERMX_KIND_IOCTL) {
kind = "ioctl";
} else if (permx->kind == CIL_PERMX_KIND_NLMSG) {
kind = "nlmsg";
} else {
kind = "???";
}

View File

@ -1513,6 +1513,9 @@ static int __cil_verify_permissionx(struct cil_permissionx *permx, struct cil_tr
case CIL_PERMX_KIND_IOCTL:
kind_str = CIL_KEY_IOCTL;
break;
case CIL_PERMX_KIND_NLMSG:
kind_str = CIL_KEY_NLMSG;
break;
default:
cil_tree_log(node, CIL_ERR, "Invalid permissionx kind (%d)", permx->kind);
rc = SEPOL_ERR;

View File

@ -303,7 +303,13 @@ static void write_permx(FILE *out, struct cil_permissionx *permx)
fprintf(out, "%s", datum_to_str(DATUM(permx)));
} else {
fprintf(out, "(");
fprintf(out, "%s ", permx->kind == CIL_PERMX_KIND_IOCTL ? "ioctl" : "<?KIND>");
if (permx->kind == CIL_PERMX_KIND_IOCTL) {
fprintf(out, "ioctl ");
} else if (permx->kind == CIL_PERMX_KIND_NLMSG) {
fprintf(out, "nlmsg ");
} else {
fprintf(out, "<?KIND> ");
}
fprintf(out, "%s ", datum_or_str(DATUM(permx->obj), permx->obj_str));
write_expr(out, permx->expr_str);
fprintf(out, ")");
@ -823,7 +829,13 @@ void cil_write_ast_node(FILE *out, struct cil_tree_node *node)
case CIL_PERMISSIONX: {
struct cil_permissionx *permx = node->data;
fprintf(out, "(permissionx %s (", datum_to_str(DATUM(permx)));
fprintf(out, "%s ", permx->kind == CIL_PERMX_KIND_IOCTL ? "ioctl" : "<?KIND>");
if (permx->kind == CIL_PERMX_KIND_IOCTL) {
fprintf(out, "ioctl ");
} else if (permx->kind == CIL_PERMX_KIND_NLMSG) {
fprintf(out, "nlmsg ");
} else {
fprintf(out, "<?KIND> ");
}
fprintf(out, "%s ", datum_or_str(DATUM(permx->obj), permx->obj_str));
write_expr(out, permx->expr_str);
fprintf(out, "))\n");

View File

@ -74,6 +74,7 @@ typedef struct avtab_extended_perms {
#define AVTAB_XPERMS_IOCTLFUNCTION 0x01
#define AVTAB_XPERMS_IOCTLDRIVER 0x02
#define AVTAB_XPERMS_NLMSG 0x03
/* extension of the avtab_key specified */
uint8_t specified;
uint8_t driver;

View File

@ -259,6 +259,7 @@ typedef struct class_perm_node {
typedef struct av_extended_perms {
#define AVRULE_XPERMS_IOCTLFUNCTION 0x01
#define AVRULE_XPERMS_IOCTLDRIVER 0x02
#define AVRULE_XPERMS_NLMSG 0x03
uint8_t specified;
uint8_t driver;
/* 256 bits of permissions */

View File

@ -1821,6 +1821,9 @@ static int allocate_xperms(sepol_handle_t * handle, avtab_datum_t * avdatump,
case AVRULE_XPERMS_IOCTLDRIVER:
xperms->specified = AVTAB_XPERMS_IOCTLDRIVER;
break;
case AVRULE_XPERMS_NLMSG:
xperms->specified = AVTAB_XPERMS_NLMSG;
break;
default:
return -1;
}

View File

@ -1651,7 +1651,8 @@ static char *xperms_to_str(const avtab_extended_perms_t *xperms)
size_t remaining, size = 128;
if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
&& (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)) {
&& (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)
&& (xperms->specified != AVTAB_XPERMS_NLMSG)) {
return NULL;
}
@ -1681,7 +1682,8 @@ retry:
continue;
}
if (xperms->specified & AVTAB_XPERMS_IOCTLFUNCTION) {
if ((xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION)
|| (xperms->specified == AVTAB_XPERMS_NLMSG)) {
value = xperms->driver<<8 | bit;
if (in_range) {
low_value = xperms->driver<<8 | low_bit;
@ -1690,7 +1692,7 @@ retry:
} else {
len = snprintf(p, remaining, " 0x%hx", value);
}
} else if (xperms->specified & AVTAB_XPERMS_IOCTLDRIVER) {
} else if (xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) {
value = bit << 8;
if (in_range) {
low_value = low_bit << 8;
@ -1728,7 +1730,7 @@ static char *avtab_node_to_str(struct policydb *pdb, avtab_key_t *key, avtab_dat
uint32_t data = datum->data;
type_datum_t *type;
const char *flavor, *tgt;
char *src, *class, *perms, *new;
char *src, *class, *perms, *new, *xperm;
char *rule = NULL;
switch (0xFFF & key->specified) {
@ -1795,9 +1797,16 @@ static char *avtab_node_to_str(struct policydb *pdb, avtab_key_t *key, avtab_dat
ERR(NULL, "Failed to generate extended permission string");
goto exit;
}
if (datum->xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION || datum->xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) {
xperm = (char *) "ioctl";
} else if (datum->xperms->specified == AVTAB_XPERMS_NLMSG) {
xperm = (char *) "nlmsg";
} else {
ERR(NULL, "Unknown extended permssion");
goto exit;
}
rule = create_str("(%s %s %s (%s %s (%s)))",
flavor, src, tgt, "ioctl", class, perms);
flavor, src, tgt, xperm, class, perms);
free(perms);
} else {
new = pdb->p_type_val_to_name[data - 1];

View File

@ -630,7 +630,8 @@ static int xperms_to_cil(const av_extended_perms_t *xperms)
int first = 1;
if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
&& (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER))
&& (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)
&& (xperms->specified != AVTAB_XPERMS_NLMSG))
return -1;
for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) {
@ -652,7 +653,8 @@ static int xperms_to_cil(const av_extended_perms_t *xperms)
else
first = 0;
if (xperms->specified & AVTAB_XPERMS_IOCTLFUNCTION) {
if ((xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION)
|| (xperms->specified == AVTAB_XPERMS_NLMSG)) {
value = xperms->driver<<8 | bit;
if (in_range) {
low_value = xperms->driver<<8 | low_bit;
@ -661,7 +663,7 @@ static int xperms_to_cil(const av_extended_perms_t *xperms)
} else {
cil_printf("0x%hx", value);
}
} else if (xperms->specified & AVTAB_XPERMS_IOCTLDRIVER) {
} else if (xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) {
value = bit << 8;
if (in_range) {
low_value = low_bit << 8;
@ -680,6 +682,7 @@ static int avrulex_to_cil(int indent, struct policydb *pdb, uint32_t type, const
{
int rc = -1;
const char *rule;
const char *xperm;
const struct class_perm_node *classperm;
switch (type) {
@ -701,10 +704,19 @@ static int avrulex_to_cil(int indent, struct policydb *pdb, uint32_t type, const
goto exit;
}
if (xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION || xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) {
xperm = "ioctl";
} else if (xperms->specified == AVTAB_XPERMS_NLMSG) {
xperm = "nlmsg";
} else {
ERR(NULL, "Unkown avrule xperms->specified: %i", xperms->specified);
rc = -1;
goto exit;
}
for (classperm = classperms; classperm != NULL; classperm = classperm->next) {
cil_indent(indent);
cil_printf("(%s %s %s (%s %s (", rule, src, tgt,
"ioctl", pdb->p_class_val_to_name[classperm->tclass - 1]);
xperm, pdb->p_class_val_to_name[classperm->tclass - 1]);
xperms_to_cil(xperms);
cil_printf(")))\n");
}

View File

@ -921,6 +921,7 @@ static int validate_xperms(const avtab_extended_perms_t *xperms)
switch (xperms->specified) {
case AVTAB_XPERMS_IOCTLDRIVER:
case AVTAB_XPERMS_IOCTLFUNCTION:
case AVTAB_XPERMS_NLMSG:
break;
default:
goto bad;
@ -1067,6 +1068,7 @@ static int validate_avrules(sepol_handle_t *handle, const avrule_t *avrule, int
switch (avrule->xperms->specified) {
case AVRULE_XPERMS_IOCTLFUNCTION:
case AVRULE_XPERMS_IOCTLDRIVER:
case AVRULE_XPERMS_NLMSG:
break;
default:
goto bad;

View File

@ -146,7 +146,8 @@ char *sepol_extended_perms_to_string(const avtab_extended_perms_t *xperms)
size_t remaining, size = 128;
if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
&& (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER))
&& (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER)
&& (xperms->specified != AVTAB_XPERMS_NLMSG))
return NULL;
retry:
@ -158,7 +159,12 @@ retry:
buffer = p;
remaining = size;
len = snprintf(p, remaining, "ioctl { ");
if ((xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION)
|| (xperms->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
len = snprintf(p, remaining, "ioctl { ");
} else {
len = snprintf(p, remaining, "nlmsg { ");
}
if (len < 0 || (size_t)len >= remaining)
goto err;
p += len;
@ -179,7 +185,7 @@ retry:
continue;
}
if (xperms->specified & AVTAB_XPERMS_IOCTLFUNCTION) {
if (xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION || xperms->specified == AVTAB_XPERMS_NLMSG) {
value = xperms->driver<<8 | bit;
if (in_range) {
low_value = xperms->driver<<8 | low_bit;
@ -187,7 +193,7 @@ retry:
} else {
len = snprintf(p, remaining, "0x%hx ", value);
}
} else if (xperms->specified & AVTAB_XPERMS_IOCTLDRIVER) {
} else if (xperms->specified == AVTAB_XPERMS_IOCTLDRIVER) {
value = bit << 8;
if (in_range) {
low_value = low_bit << 8;