checkpolicy: switch operations to extended perms

The ioctl operations code is being renamed to the more generic
"extended permissions." This commit brings the policy compiler
up to date with the kernel patch.

Signed-off-by: Jeff Vander Stoep <jeffv@google.com>
This commit is contained in:
Jeff Vander Stoep 2015-06-12 09:01:12 -07:00 committed by Stephen Smalley
parent 1af0ed6f13
commit 915fa8f08f
11 changed files with 384 additions and 346 deletions

View File

@ -1729,32 +1729,31 @@ avrule_t *define_cond_pol_list(avrule_t * avlist, avrule_t * sl)
return sl;
}
#define operation_perm_test(x, p) (1 & (p[x >> 5] >> (x & 0x1f)))
#define operation_perm_set(x, p) (p[x >> 5] |= (1 << (x & 0x1f)))
#define operation_perm_clear(x, p) (p[x >> 5] &= ~(1 << (x & 0x1f)))
#define xperm_test(x, p) (1 & (p[x >> 5] >> (x & 0x1f)))
#define xperm_set(x, p) (p[x >> 5] |= (1 << (x & 0x1f)))
#define xperm_clear(x, p) (p[x >> 5] &= ~(1 << (x & 0x1f)))
typedef struct av_operations_range {
typedef struct av_ioctl_range {
uint16_t low;
uint16_t high;
} av_operations_range_t;
} av_ioctl_range_t;
struct av_operations_range_list {
struct av_ioctl_range_list {
uint8_t omit;
av_operations_range_t range;
struct av_operations_range_list *next;
av_ioctl_range_t range;
struct av_ioctl_range_list *next;
};
int avrule_sort_operations(
struct av_operations_range_list **rangehead)
int avrule_sort_ioctls(struct av_ioctl_range_list **rangehead)
{
struct av_operations_range_list *r, *r2, *sorted, *sortedhead = NULL;
struct av_ioctl_range_list *r, *r2, *sorted, *sortedhead = NULL;
/* order list by range.low */
for (r = *rangehead; r != NULL; r = r->next) {
sorted = malloc(sizeof(struct av_operations_range_list));
sorted = malloc(sizeof(struct av_ioctl_range_list));
if (sorted == NULL)
goto error;
memcpy(sorted, r, sizeof(struct av_operations_range_list));
memcpy(sorted, r, sizeof(struct av_ioctl_range_list));
sorted->next = NULL;
if (sortedhead == NULL) {
sortedhead = sorted;
@ -1793,9 +1792,9 @@ error:
return -1;
}
int avrule_merge_operations(struct av_operations_range_list **rangehead)
int avrule_merge_ioctls(struct av_ioctl_range_list **rangehead)
{
struct av_operations_range_list *r, *tmp;
struct av_ioctl_range_list *r, *tmp;
r = *rangehead;
while (r != NULL && r->next != NULL) {
/* merge */
@ -1813,14 +1812,14 @@ int avrule_merge_operations(struct av_operations_range_list **rangehead)
return 0;
}
int avrule_read_operations(struct av_operations_range_list **rangehead)
int avrule_read_ioctls(struct av_ioctl_range_list **rangehead)
{
char *id;
struct av_operations_range_list *rnew, *r = NULL;
struct av_ioctl_range_list *rnew, *r = NULL;
*rangehead = NULL;
uint8_t omit = 0;
/* read in all the operations */
/* read in all the ioctl commands */
while ((id = queue_remove(id_queue))) {
if (strcmp(id,"~") == 0) {
/* these are values to be omitted */
@ -1838,7 +1837,7 @@ int avrule_read_operations(struct av_operations_range_list **rangehead)
free(id);
} else {
/* read in new low value */
rnew = malloc(sizeof(struct av_operations_range_list));
rnew = malloc(sizeof(struct av_ioctl_range_list));
if (rnew == NULL)
goto error;
rnew->next = NULL;
@ -1863,11 +1862,11 @@ error:
}
/* flip to included ranges */
int avrule_omit_operations(struct av_operations_range_list **rangehead)
int avrule_omit_ioctls(struct av_ioctl_range_list **rangehead)
{
struct av_operations_range_list *rnew, *r, *newhead, *r2;
struct av_ioctl_range_list *rnew, *r, *newhead, *r2;
rnew = calloc(1, sizeof(struct av_operations_range_list));
rnew = calloc(1, sizeof(struct av_ioctl_range_list));
if (!rnew)
goto error;
@ -1885,7 +1884,7 @@ int avrule_omit_operations(struct av_operations_range_list **rangehead)
while (r) {
r2->range.high = r->range.low - 1;
rnew = calloc(1, sizeof(struct av_operations_range_list));
rnew = calloc(1, sizeof(struct av_ioctl_range_list));
if (!rnew)
goto error;
r2->next = rnew;
@ -1911,27 +1910,27 @@ error:
return -1;
}
int avrule_operation_ranges(struct av_operations_range_list **rangelist)
int avrule_ioctl_ranges(struct av_ioctl_range_list **rangelist)
{
struct av_operations_range_list *rangehead;
struct av_ioctl_range_list *rangehead;
uint8_t omit;
/* read in ranges to include and omit */
if (avrule_read_operations(&rangehead))
if (avrule_read_ioctls(&rangehead))
return -1;
omit = rangehead->omit;
if (rangehead == NULL) {
yyerror("error processing ioctl operations");
yyerror("error processing ioctl commands");
return -1;
}
/* sort and merge the input operations */
if (avrule_sort_operations(&rangehead))
/* sort and merge the input ioctls */
if (avrule_sort_ioctls(&rangehead))
return -1;
if (avrule_merge_operations(&rangehead))
if (avrule_merge_ioctls(&rangehead))
return -1;
/* flip ranges if these are ommited*/
if (omit) {
if (avrule_omit_operations(&rangehead))
if (avrule_omit_ioctls(&rangehead))
return -1;
}
@ -1939,7 +1938,7 @@ int avrule_operation_ranges(struct av_operations_range_list **rangelist)
return 0;
}
int define_te_avtab_operation_helper(int which, avrule_t ** rule)
int define_te_avtab_xperms_helper(int which, avrule_t ** rule)
{
char *id;
class_perm_node_t *perms, *tail = NULL, *cur_perms = NULL;
@ -1960,7 +1959,7 @@ int define_te_avtab_operation_helper(int which, avrule_t ** rule)
avrule->line = policydb_lineno;
avrule->source_line = source_lineno;
avrule->source_filename = strdup(source_file);
avrule->ops = NULL;
avrule->xperms = NULL;
if (!avrule->source_filename) {
yyerror("out of memory");
return -1;
@ -2024,95 +2023,102 @@ out:
}
/* index of the u32 containing the permission */
#define OP_IDX(x) (x >> 5)
#define XPERM_IDX(x) (x >> 5)
/* set bits 0 through x-1 within the u32 */
#define OP_SETBITS(x) ((1 << (x & 0x1f)) - 1)
#define XPERM_SETBITS(x) ((1 << (x & 0x1f)) - 1)
/* low value for this u32 */
#define OP_LOW(x) (x << 5)
#define XPERM_LOW(x) (x << 5)
/* high value for this u32 */
#define OP_HIGH(x) (((x + 1) << 5) - 1)
void avrule_operation_setrangebits(uint16_t low, uint16_t high, av_operations_t *ops)
#define XPERM_HIGH(x) (((x + 1) << 5) - 1)
void avrule_xperm_setrangebits(uint16_t low, uint16_t high,
av_extended_perms_t *xperms)
{
unsigned int i;
uint16_t h = high + 1;
/* for each u32 that this low-high range touches, set type permissions */
for (i = OP_IDX(low); i <= OP_IDX(high); i++) {
/* for each u32 that this low-high range touches, set driver permissions */
for (i = XPERM_IDX(low); i <= XPERM_IDX(high); i++) {
/* set all bits in u32 */
if ((low <= OP_LOW(i)) && (high >= OP_HIGH(i)))
ops->perms[i] |= ~0U;
if ((low <= XPERM_LOW(i)) && (high >= XPERM_HIGH(i)))
xperms->perms[i] |= ~0U;
/* set low bits */
else if ((low <= OP_LOW(i)) && (high < OP_HIGH(i)))
ops->perms[i] |= OP_SETBITS(h);
else if ((low <= XPERM_LOW(i)) && (high < XPERM_HIGH(i)))
xperms->perms[i] |= XPERM_SETBITS(h);
/* set high bits */
else if ((low > OP_LOW(i)) && (high >= OP_HIGH(i)))
ops->perms[i] |= ~0U - OP_SETBITS(low);
else if ((low > XPERM_LOW(i)) && (high >= XPERM_HIGH(i)))
xperms->perms[i] |= ~0U - XPERM_SETBITS(low);
/* set middle bits */
else if ((low > OP_LOW(i)) && (high <= OP_HIGH(i)))
ops->perms[i] |= OP_SETBITS(h) - OP_SETBITS(low);
else if ((low > XPERM_LOW(i)) && (high <= XPERM_HIGH(i)))
xperms->perms[i] |= XPERM_SETBITS(h) - XPERM_SETBITS(low);
}
}
int avrule_operation_used(av_operations_t *ops)
int avrule_xperms_used(av_extended_perms_t *xperms)
{
unsigned int i;
for (i = 0; i < sizeof(ops->perms)/sizeof(ops->perms[0]); i++) {
if (ops->perms[i])
for (i = 0; i < sizeof(xperms->perms)/sizeof(xperms->perms[0]); i++) {
if (xperms->perms[i])
return 1;
}
return 0;
}
#define OP_TYPE(x) (x >> 8)
#define OP_NUM(x) (x & 0xff)
#define OP_CMD(type, num) ((type << 8) + num)
int avrule_operation_partialtype(struct av_operations_range_list *rangelist,
av_operations_t *complete_type,
av_operations_t **operations)
/*
* using definitions found in kernel document ioctl-number.txt
* The kernel components of an ioctl command are:
* dir, size, driver, and fucntion. Only the driver and function fields
* are considered here
*/
#define IOC_DRIV(x) (x >> 8)
#define IOC_FUNC(x) (x & 0xff)
#define IOC_CMD(driver, func) ((driver << 8) + func)
int avrule_ioctl_partialdriver(struct av_ioctl_range_list *rangelist,
av_extended_perms_t *complete_driver,
av_extended_perms_t **extended_perms)
{
struct av_operations_range_list *r;
av_operations_t *ops;
struct av_ioctl_range_list *r;
av_extended_perms_t *xperms;
uint8_t low, high;
ops = calloc(1, sizeof(av_operations_t));
if (!ops) {
xperms = calloc(1, sizeof(av_extended_perms_t));
if (!xperms) {
yyerror("out of memory");
return - 1;
}
r = rangelist;
while(r) {
low = OP_TYPE(r->range.low);
high = OP_TYPE(r->range.high);
if (complete_type) {
if (!operation_perm_test(low, complete_type->perms))
operation_perm_set(low, ops->perms);
if (!operation_perm_test(high, complete_type->perms))
operation_perm_set(high, ops->perms);
low = IOC_DRIV(r->range.low);
high = IOC_DRIV(r->range.high);
if (complete_driver) {
if (!xperm_test(low, complete_driver->perms))
xperm_set(low, xperms->perms);
if (!xperm_test(high, complete_driver->perms))
xperm_set(high, xperms->perms);
} else {
operation_perm_set(low, ops->perms);
operation_perm_set(high, ops->perms);
xperm_set(low, xperms->perms);
xperm_set(high, xperms->perms);
}
r = r->next;
}
if (avrule_operation_used(ops)) {
*operations = ops;
if (avrule_xperms_used(xperms)) {
*extended_perms = xperms;
} else {
free(ops);
*operations = NULL;
free(xperms);
*extended_perms = NULL;
}
return 0;
}
int avrule_operation_completetype(struct av_operations_range_list *rangelist,
av_operations_t **operations)
int avrule_ioctl_completedriver(struct av_ioctl_range_list *rangelist,
av_extended_perms_t **extended_perms)
{
struct av_operations_range_list *r;
av_operations_t *ops;
struct av_ioctl_range_list *r;
av_extended_perms_t *xperms;
uint16_t low, high;
ops = calloc(1, sizeof(av_operations_t));
if (!ops) {
xperms = calloc(1, sizeof(av_extended_perms_t));
if (!xperms) {
yyerror("out of memory");
return - 1;
}
@ -2120,83 +2126,86 @@ int avrule_operation_completetype(struct av_operations_range_list *rangelist,
r = rangelist;
while(r) {
/*
* Any type that has numbers 0x00 - 0xff is a complete type,
* Any driver code that has sequence 0x00 - 0xff is a complete code,
*
* if command number = 0xff, then round high up to next type,
* else 0x00 - 0xfe keep current type
* if command number = 0xff, then round high up to next code,
* else 0x00 - 0xfe keep current code
* of this range. temporarily u32 for the + 1
* to account for possible rollover before right shift
*/
high = OP_TYPE((uint32_t) (r->range.high + 1));
/* if 0x00 keep current type else 0x01 - 0xff round up to next type */
low = OP_TYPE(r->range.low);
if (OP_NUM(r->range.low))
high = IOC_DRIV((uint32_t) (r->range.high + 1));
/* if 0x00 keep current driver code else 0x01 - 0xff round up to next code*/
low = IOC_DRIV(r->range.low);
if (IOC_FUNC(r->range.low))
low++;
if (high > low)
avrule_operation_setrangebits(low, high - 1, ops);
avrule_xperm_setrangebits(low, high - 1, xperms);
r = r->next;
}
if (avrule_operation_used(ops)) {
*operations = ops;
if (avrule_xperms_used(xperms)) {
xperms->driver = 0x00;
xperms->specified = AVRULE_XPERMS_IOCTLDRIVER;
*extended_perms = xperms;
} else {
free(ops);
*operations = NULL;
free(xperms);
*extended_perms = NULL;
}
return 0;
}
int avrule_operation_num(struct av_operations_range_list *rangelist,
av_operations_t **operations, unsigned int type)
int avrule_ioctl_func(struct av_ioctl_range_list *rangelist,
av_extended_perms_t **extended_perms, unsigned int driver)
{
struct av_operations_range_list *r;
av_operations_t *ops;
struct av_ioctl_range_list *r;
av_extended_perms_t *xperms;
uint16_t low, high;
*operations = NULL;
ops = calloc(1, sizeof(av_operations_t));
if (!ops) {
*extended_perms = NULL;
xperms = calloc(1, sizeof(av_extended_perms_t));
if (!xperms) {
yyerror("out of memory");
return - 1;
}
r = rangelist;
/* for the passed in types, find the ranges that apply */
/* for the passed in driver code, find the ranges that apply */
while (r) {
low = r->range.low;
high = r->range.high;
if ((type != OP_TYPE(low)) && (type != OP_TYPE(high))) {
if ((driver != IOC_DRIV(low)) && (driver != IOC_DRIV(high))) {
r = r->next;
continue;
}
if (type == OP_TYPE(low)) {
if (high > OP_CMD(type, 0xff))
high = OP_CMD(type, 0xff);
if (driver == IOC_DRIV(low)) {
if (high > IOC_CMD(driver, 0xff))
high = IOC_CMD(driver, 0xff);
} else {
if (low < OP_CMD(type, 0))
low = OP_CMD(type, 0);
if (low < IOC_CMD(driver, 0))
low = IOC_CMD(driver, 0);
}
low = OP_NUM(low);
high = OP_NUM(high);
avrule_operation_setrangebits(low, high, ops);
ops->type = type;
low = IOC_FUNC(low);
high = IOC_FUNC(high);
avrule_xperm_setrangebits(low, high, xperms);
xperms->driver = driver;
xperms->specified = AVRULE_XPERMS_IOCTLFUNCTION;
r = r->next;
}
if (avrule_operation_used(ops)) {
*operations = ops;
if (avrule_xperms_used(xperms)) {
*extended_perms = xperms;
} else {
free(ops);
*operations = NULL;
free(xperms);
*extended_perms = NULL;
}
return 0;
}
void avrule_operation_freeranges(struct av_operations_range_list *rangelist)
void avrule_ioctl_freeranges(struct av_ioctl_range_list *rangelist)
{
struct av_operations_range_list *r, *tmp;
struct av_ioctl_range_list *r, *tmp;
r = rangelist;
while (r) {
tmp = r;
@ -2205,12 +2214,12 @@ void avrule_operation_freeranges(struct av_operations_range_list *rangelist)
}
}
unsigned int operation_for_each_bit(unsigned int *bit, av_operations_t *ops)
unsigned int xperms_for_each_bit(unsigned int *bit, av_extended_perms_t *xperms)
{
unsigned int i;
for (i = *bit; i < sizeof(ops->perms)*8; i++) {
if (operation_perm_test(i,ops->perms)) {
operation_perm_clear(i, ops->perms);
for (i = *bit; i < sizeof(xperms->perms)*8; i++) {
if (xperm_test(i,xperms->perms)) {
xperm_clear(i, xperms->perms);
*bit = i;
return 1;
}
@ -2262,14 +2271,75 @@ int avrule_cpy(avrule_t *dest, avrule_t *src)
return 0;
}
int define_te_avtab_operation(int which)
int define_te_avtab_ioctl(avrule_t *avrule_template)
{
avrule_t *avrule;
struct av_ioctl_range_list *rangelist;
av_extended_perms_t *complete_driver, *partial_driver, *xperms;
unsigned int i;
/* organize ioctl ranges */
if (avrule_ioctl_ranges(&rangelist))
return -1;
/* create rule for ioctl driver types that are entirely enabled */
if (avrule_ioctl_completedriver(rangelist, &complete_driver))
return -1;
if (complete_driver) {
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 = complete_driver;
append_avrule(avrule);
}
/* flag ioctl driver codes that are partially enabled */
if (avrule_ioctl_partialdriver(rangelist, complete_driver, &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_ioctl_func(rangelist, &xperms, i))
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);
return 0;
}
int define_te_avtab_extended_perms(int which)
{
char *id;
avrule_t *avrule_template;
avrule_t *avrule;
struct av_operations_range_list *rangelist;
av_operations_t *complete_type, *partial_type, *ops;
unsigned int i;
avrule_t *avrule_template;
if (pass == 1) {
for (i = 0; i < 4; i++) {
@ -2280,65 +2350,18 @@ int define_te_avtab_operation(int which)
}
/* populate avrule template with source/target/tclass */
if (define_te_avtab_operation_helper(which, &avrule_template))
if (define_te_avtab_xperms_helper(which, &avrule_template))
return -1;
/* organize operation ranges */
if (avrule_operation_ranges(&rangelist))
return -1;
/* create rule for ioctl operation types that are entirely enabled */
if (avrule_operation_completetype(rangelist, &complete_type))
return -1;
if (complete_type) {
avrule = (avrule_t *) calloc(1, sizeof(avrule_t));
if (!avrule) {
yyerror("out of memory");
id = queue_remove(id_queue);
if (strcmp(id,"ioctl") == 0) {
if (define_te_avtab_ioctl(avrule_template))
return -1;
}
if (avrule_cpy(avrule, avrule_template))
return -1;
avrule->ops = complete_type;
if (which == AVRULE_OPNUM_ALLOWED)
avrule->specified = AVRULE_OPTYPE_ALLOWED;
else if (which == AVRULE_OPNUM_AUDITALLOW)
avrule->specified = AVRULE_OPTYPE_AUDITALLOW;
else if (which == AVRULE_OPNUM_DONTAUDIT)
avrule->specified = AVRULE_OPTYPE_DONTAUDIT;
append_avrule(avrule);
free(id);
} else {
yyerror("only ioctl extended permissions are supported");
return -1;
}
/* flag ioctl types that are partially enabled */
if (avrule_operation_partialtype(rangelist, complete_type, &partial_type))
return -1;
if (!partial_type || !avrule_operation_used(partial_type))
goto done;
/* create rule for each partially enabled type */
i = 0;
while (operation_for_each_bit(&i, partial_type)) {
if (avrule_operation_num(rangelist, &ops, i))
return -1;
if (ops) {
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->ops = ops;
append_avrule(avrule);
}
}
done:
if (partial_type)
free(partial_type);
return 0;
}
@ -2366,7 +2389,7 @@ int define_te_avtab_helper(int which, avrule_t ** rule)
avrule->line = policydb_lineno;
avrule->source_line = source_lineno;
avrule->source_filename = strdup(source_file);
avrule->ops = NULL;
avrule->xperms = NULL;
if (!avrule->source_filename) {
yyerror("out of memory");
return -1;

View File

@ -58,7 +58,7 @@ int define_roleattribute(void);
int define_filename_trans(void);
int define_sens(void);
int define_te_avtab(int which);
int define_te_avtab_operation(int which);
int define_te_avtab_extended_perms(int which);
int define_typealias(void);
int define_typeattribute(void);
int define_typebounds(void);

View File

@ -126,6 +126,9 @@ typedef int (* require_func_t)(int pass);
%token AUDITALLOW
%token AUDITDENY
%token DONTAUDIT
%token ALLOWXPERM
%token AUDITALLOWXPERM
%token DONTAUDITXPERM
%token SOURCE
%token TARGET
%token SAMEUSER
@ -457,9 +460,9 @@ te_avtab_def : allow_def
| auditdeny_def
| dontaudit_def
| neverallow_def
| operation_allow_def
| operation_auditallow_def
| operation_dontaudit_def
| xperm_allow_def
| xperm_auditallow_def
| xperm_dontaudit_def
;
allow_def : ALLOW names names ':' names names ';'
{if (define_te_avtab(AVRULE_ALLOWED)) return -1; }
@ -476,14 +479,14 @@ dontaudit_def : DONTAUDIT names names ':' names names ';'
neverallow_def : NEVERALLOW names names ':' names names ';'
{if (define_te_avtab(AVRULE_NEVERALLOW)) return -1; }
;
operation_allow_def : ALLOW names names ':' names operations ';'
{if (define_te_avtab_operation(AVRULE_OPNUM_ALLOWED)) return -1; }
xperm_allow_def : ALLOWXPERM names names ':' names identifier xperms ';'
{if (define_te_avtab_extended_perms(AVRULE_XPERMS_ALLOWED)) return -1; }
;
operation_auditallow_def: AUDITALLOW names names ':' names operations ';'
{if (define_te_avtab_operation(AVRULE_OPNUM_AUDITALLOW)) return -1; }
xperm_auditallow_def : AUDITALLOWXPERM names names ':' names identifier xperms ';'
{if (define_te_avtab_extended_perms(AVRULE_XPERMS_AUDITALLOW)) return -1; }
;
operation_dontaudit_def : DONTAUDIT names names ':' names operations ';'
{if (define_te_avtab_operation(AVRULE_OPNUM_DONTAUDIT)) return -1; }
xperm_dontaudit_def : DONTAUDITXPERM names names ':' names identifier xperms ';'
{if (define_te_avtab_extended_perms(AVRULE_XPERMS_DONTAUDIT)) return -1; }
;
attribute_role_def : ATTRIBUTE_ROLE identifier ';'
{if (define_attrib_role()) return -1; }
@ -749,26 +752,26 @@ genfs_context_def : GENFSCON filesystem path '-' identifier security_context_def
ipv4_addr_def : IPV4_ADDR
{ if (insert_id(yytext,0)) return -1; }
;
operations : operation
xperms : xperm
{ if (insert_separator(0)) return -1; }
| nested_operation_set
| nested_xperm_set
{ if (insert_separator(0)) return -1; }
| tilde operation
| tilde xperm
{ if (insert_id("~", 0)) return -1; }
| tilde nested_operation_set
| tilde nested_xperm_set
{ if (insert_id("~", 0)) return -1;
if (insert_separator(0)) return -1; }
;
nested_operation_set : '{' nested_operation_list '}'
nested_xperm_set : '{' nested_xperm_list '}'
;
nested_operation_list : nested_operation_element
| nested_operation_list nested_operation_element
nested_xperm_list : nested_xperm_element
| nested_xperm_list nested_xperm_element
;
nested_operation_element: operation '-' { if (insert_id("-", 0)) return -1; } operation
| operation
| nested_operation_set
nested_xperm_element: xperm '-' { if (insert_id("-", 0)) return -1; } xperm
| xperm
| nested_xperm_set
;
operation : number
xperm : number
{ if (insert_id(yytext,0)) return -1; }
;
security_context_def : identifier ':' identifier ':' identifier opt_mls_range_def

View File

@ -142,6 +142,12 @@ AUDITDENY |
auditdeny { return(AUDITDENY); }
DONTAUDIT |
dontaudit { return(DONTAUDIT); }
ALLOWXPERM |
allowxperm { return(ALLOWXPERM); }
AUDITALLOWXPERM |
auditallowxperm { return(AUDITALLOWXPERM); }
DONTAUDITXPERM |
dontauditxperm { return(DONTAUDITXPERM); }
SOURCE |
source { return(SOURCE); }
TARGET |

View File

@ -54,11 +54,11 @@ int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p,
return 0;
}
#define operation_perm_test(x, p) (1 & (p[x >> 5] >> (x & 0x1f)))
#define xperms_test(x, p) (1 & (p[x >> 5] >> (x & 0x1f)))
#define next_bit_in_range(i, p) \
((i + 1 < sizeof(p)*8) && operation_perm_test((i + 1), p))
((i + 1 < sizeof(p)*8) && xperms_test((i + 1), p))
int render_operations(avtab_operations_t *ops, avtab_key_t * key, FILE * fp)
int render_ioctl(avtab_extended_perms_t * xperms, FILE * fp)
{
uint16_t value;
uint16_t low_bit;
@ -67,28 +67,28 @@ int render_operations(avtab_operations_t *ops, avtab_key_t * key, FILE * fp)
unsigned int in_range = 0;
fprintf(fp, "{ ");
for (bit = 0; bit < sizeof(ops->perms)*8; bit++) {
if (!operation_perm_test(bit, ops->perms))
for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) {
if (!xperms_test(bit, xperms->perms))
continue;
if (in_range && next_bit_in_range(bit, ops->perms)) {
if (in_range && next_bit_in_range(bit, xperms->perms)) {
/* continue until high value found */
continue;
} else if (next_bit_in_range(bit, ops->perms)) {
} else if (next_bit_in_range(bit, xperms->perms)) {
/* low value */
low_bit = bit;
in_range = 1;
continue;
}
if (key->specified & AVTAB_OPNUM) {
value = ops->type<<8 | bit;
low_value = ops->type<<8 | low_bit;
if (xperms->specified & AVTAB_XPERMS_IOCTLFUNCTION) {
value = xperms->driver<<8 | bit;
low_value = xperms->driver<<8 | low_bit;
if (in_range)
fprintf(fp, "0x%hx-0x%hx ", low_value, value);
else
fprintf(fp, "0x%hx ", value);
} else if (key->specified & AVTAB_OPTYPE) {
} else if (xperms->specified & AVTAB_XPERMS_IOCTLDRIVER) {
value = bit << 8;
low_value = low_bit << 8;
if (in_range)
@ -104,6 +104,15 @@ int render_operations(avtab_operations_t *ops, avtab_key_t * key, FILE * fp)
return 0;
}
int render_xperms(avtab_extended_perms_t * xperms, FILE * fp)
{
if ((xperms->specified == AVTAB_XPERMS_IOCTLFUNCTION) ||
(xperms->specified == AVTAB_XPERMS_IOCTLDRIVER))
render_ioctl(xperms, fp);
return 0;
}
int render_type(uint32_t type, policydb_t * p, FILE * fp)
{
fprintf(fp, "%s", p->p_type_val_to_name[type - 1]);
@ -197,15 +206,15 @@ int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t what,
render_type(datum->data, p, fp);
fprintf(fp, ";\n");
}
} else if (key->specified & AVTAB_OP) {
if (key->specified & (AVTAB_OPNUM_ALLOWED|AVTAB_OPTYPE_ALLOWED))
fprintf(fp, "allow ");
else if (key->specified & (AVTAB_OPNUM_AUDITALLOW|AVTAB_OPTYPE_AUDITALLOW))
fprintf(fp, "auditallow ");
else if (key->specified & (AVTAB_OPNUM_DONTAUDIT|AVTAB_OPTYPE_DONTAUDIT))
fprintf(fp, "dontaudit ");
} else if (key->specified & AVTAB_XPERMS) {
if (key->specified & AVTAB_XPERMS_ALLOWED)
fprintf(fp, "allowxperm ");
else if (key->specified & AVTAB_XPERMS_AUDITALLOW)
fprintf(fp, "auditallowxperm ");
else if (key->specified & AVTAB_XPERMS_DONTAUDIT)
fprintf(fp, "dontauditxperm ");
render_key(key, p, fp);
render_operations(datum->ops, key, fp);
render_xperms(datum->xperms, fp);
fprintf(fp, ";\n");
} else {
fprintf(fp, " ERROR: no valid rule type specified\n");

View File

@ -59,28 +59,28 @@ typedef struct avtab_key {
#define AVTAB_MEMBER 0x0020
#define AVTAB_CHANGE 0x0040
#define AVTAB_TYPE (AVTAB_TRANSITION | AVTAB_MEMBER | AVTAB_CHANGE)
#define AVTAB_OPNUM_ALLOWED 0x0100
#define AVTAB_OPNUM_AUDITALLOW 0x0200
#define AVTAB_OPNUM_DONTAUDIT 0x0400
#define AVTAB_OPNUM (AVTAB_OPNUM_ALLOWED | AVTAB_OPNUM_AUDITALLOW | AVTAB_OPNUM_DONTAUDIT)
#define AVTAB_OPTYPE_ALLOWED 0x1000
#define AVTAB_OPTYPE_AUDITALLOW 0x2000
#define AVTAB_OPTYPE_DONTAUDIT 0x4000
#define AVTAB_OPTYPE (AVTAB_OPTYPE_ALLOWED | AVTAB_OPTYPE_AUDITALLOW | AVTAB_OPTYPE_DONTAUDIT)
#define AVTAB_OP (AVTAB_OPNUM | AVTAB_OPTYPE)
#define AVTAB_XPERMS_ALLOWED 0x0100
#define AVTAB_XPERMS_AUDITALLOW 0x0200
#define AVTAB_XPERMS_DONTAUDIT 0x0400
#define AVTAB_XPERMS (AVTAB_XPERMS_ALLOWED | AVTAB_XPERMS_AUDITALLOW | AVTAB_XPERMS_DONTAUDIT)
#define AVTAB_ENABLED_OLD 0x80000000
#define AVTAB_ENABLED 0x8000 /* reserved for used in cond_avtab */
uint16_t specified; /* what fields are specified */
} avtab_key_t;
typedef struct avtab_operations {
uint8_t type;
typedef struct avtab_extended_perms {
#define AVTAB_XPERMS_IOCTLFUNCTION 0x01
#define AVTAB_XPERMS_IOCTLDRIVER 0x02
/* extension of the avtab_key specified */
uint8_t specified;
uint8_t driver;
uint32_t perms[8];
} avtab_operations_t;
} avtab_extended_perms_t;
typedef struct avtab_datum {
uint32_t data; /* access vector or type */
avtab_operations_t *ops;
avtab_extended_perms_t *xperms;
} avtab_datum_t;
typedef struct avtab_node *avtab_ptr_t;

View File

@ -241,11 +241,14 @@ typedef struct class_perm_node {
struct class_perm_node *next;
} class_perm_node_t;
typedef struct av_operations {
uint8_t type;
/* 256 bits of ioctl number permissions */
typedef struct av_extended_perms {
#define AVRULE_XPERMS_IOCTLFUNCTION 0x01
#define AVRULE_XPERMS_IOCTLDRIVER 0x02
uint8_t specified;
uint8_t driver;
/* 256 bits of permissions */
uint32_t perms[8];
} av_operations_t;
} av_extended_perms_t;
typedef struct avrule {
/* these typedefs are almost exactly the same as those in avtab.h - they are
@ -260,24 +263,18 @@ typedef struct avrule {
#define AVRULE_MEMBER 0x0020
#define AVRULE_CHANGE 0x0040
#define AVRULE_TYPE (AVRULE_TRANSITION | AVRULE_MEMBER | AVRULE_CHANGE)
#define AVRULE_OPNUM_ALLOWED 0x0100
#define AVRULE_OPNUM_AUDITALLOW 0x0200
#define AVRULE_OPNUM_DONTAUDIT 0x0400
#define AVRULE_OPNUM (AVRULE_OPNUM_ALLOWED | AVRULE_OPNUM_AUDITALLOW | \
AVRULE_OPNUM_DONTAUDIT)
#define AVRULE_OPTYPE_ALLOWED 0x1000
#define AVRULE_OPTYPE_AUDITALLOW 0x2000
#define AVRULE_OPTYPE_DONTAUDIT 0x4000
#define AVRULE_OPTYPE (AVRULE_OPTYPE_ALLOWED | AVRULE_OPTYPE_AUDITALLOW | \
AVRULE_OPTYPE_DONTAUDIT)
#define AVRULE_OP (AVRULE_OPNUM | AVRULE_OPTYPE)
#define AVRULE_XPERMS_ALLOWED 0x0100
#define AVRULE_XPERMS_AUDITALLOW 0x0200
#define AVRULE_XPERMS_DONTAUDIT 0x0400
#define AVRULE_XPERMS (AVRULE_XPERMS_ALLOWED | AVRULE_XPERMS_AUDITALLOW | \
AVRULE_XPERMS_DONTAUDIT)
uint32_t specified;
#define RULE_SELF 1
uint32_t flags;
type_set_t stypes;
type_set_t ttypes;
class_perm_node_t *perms;
av_operations_t * ops;
av_extended_perms_t *xperms;
unsigned long line; /* line number from policy.conf where
* this rule originated */
/* source file name and line number (e.g. .te file) */
@ -709,11 +706,11 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
#define POLICYDB_VERSION_DEFAULT_TYPE 28
#define POLICYDB_VERSION_CONSTRAINT_NAMES 29
#define POLICYDB_VERSION_XEN_DEVICETREE 30 /* Xen-specific */
#define POLICYDB_VERSION_IOCTL_OPERATIONS 30 /* Linux-specific */
#define POLICYDB_VERSION_XPERMS_IOCTL 30 /* Linux-specific */
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_IOCTL_OPERATIONS
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_XPERMS_IOCTL
/* Module versions and specific changes*/
#define MOD_POLICYDB_VERSION_BASE 4

View File

@ -93,7 +93,7 @@ avtab_insert_node(avtab_t * h, int hvalue, avtab_ptr_t prev, avtab_key_t * key,
avtab_datum_t * datum)
{
avtab_ptr_t newnode;
avtab_operations_t *ops;
avtab_extended_perms_t *xperms;
newnode = (avtab_ptr_t) malloc(sizeof(struct avtab_node));
if (newnode == NULL)
@ -101,16 +101,16 @@ avtab_insert_node(avtab_t * h, int hvalue, avtab_ptr_t prev, avtab_key_t * key,
memset(newnode, 0, sizeof(struct avtab_node));
newnode->key = *key;
if (key->specified & AVTAB_OP) {
ops = calloc(1, sizeof(avtab_operations_t));
if (ops == NULL) {
if (key->specified & AVTAB_XPERMS) {
xperms = calloc(1, sizeof(avtab_extended_perms_t));
if (xperms == NULL) {
free(newnode);
return NULL;
}
if (datum->ops) /* else caller populates ops*/
*ops = *(datum->ops);
if (datum->xperms) /* else caller populates xperms */
*xperms = *(datum->xperms);
newnode->datum.ops = ops;
newnode->datum.xperms = xperms;
} else {
newnode->datum = *datum;
}
@ -144,7 +144,8 @@ int avtab_insert(avtab_t * h, avtab_key_t * key, avtab_datum_t * datum)
key->target_type == cur->key.target_type &&
key->target_class == cur->key.target_class &&
(specified & cur->key.specified)) {
if (specified & AVTAB_OPNUM)
/* Extended permissions are not necessarily unique */
if (specified & AVTAB_XPERMS)
break;
return SEPOL_EEXIST;
}
@ -416,12 +417,9 @@ static uint16_t spec_order[] = {
AVTAB_TRANSITION,
AVTAB_CHANGE,
AVTAB_MEMBER,
AVTAB_OPNUM_ALLOWED,
AVTAB_OPNUM_AUDITALLOW,
AVTAB_OPNUM_DONTAUDIT,
AVTAB_OPTYPE_ALLOWED,
AVTAB_OPTYPE_AUDITALLOW,
AVTAB_OPTYPE_DONTAUDIT
AVTAB_XPERMS_ALLOWED,
AVTAB_XPERMS_AUDITALLOW,
AVTAB_XPERMS_DONTAUDIT
};
int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a,
@ -433,14 +431,14 @@ int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a,
uint32_t buf32[8], items, items2, val;
avtab_key_t key;
avtab_datum_t datum;
avtab_operations_t ops;
avtab_extended_perms_t xperms;
unsigned set;
unsigned int i;
int rc;
memset(&key, 0, sizeof(avtab_key_t));
memset(&datum, 0, sizeof(avtab_datum_t));
memset(&ops, 0, sizeof(avtab_operations_t));
memset(&xperms, 0, sizeof(avtab_extended_perms_t));
if (vers < POLICYDB_VERSION_AVTAB) {
rc = next_entry(buf32, fp, sizeof(uint32_t));
@ -533,26 +531,32 @@ int avtab_read_item(struct policy_file *fp, uint32_t vers, avtab_t * a,
return -1;
}
if ((vers < POLICYDB_VERSION_IOCTL_OPERATIONS) &&
(key.specified & AVTAB_OP)) {
ERR(fp->handle, "policy version %u does not support ioctl "
"operation rules and one was specified\n", vers);
if ((vers < POLICYDB_VERSION_XPERMS_IOCTL) &&
(key.specified & AVTAB_XPERMS)) {
ERR(fp->handle, "policy version %u does not support extended "
"permissions rules and one was specified\n", vers);
return -1;
} else if (key.specified & AVTAB_OP) {
} else if (key.specified & AVTAB_XPERMS) {
rc = next_entry(&buf8, fp, sizeof(uint8_t));
if (rc < 0) {
ERR(fp->handle, "truncated entry");
return -1;
}
ops.type = buf8;
xperms.specified = buf8;
rc = next_entry(&buf8, fp, sizeof(uint8_t));
if (rc < 0) {
ERR(fp->handle, "truncated entry");
return -1;
}
xperms.driver = buf8;
rc = next_entry(buf32, fp, sizeof(uint32_t)*8);
if (rc < 0) {
ERR(fp->handle, "truncated entry");
return -1;
}
for (i = 0; i < ARRAY_SIZE(ops.perms); i++)
ops.perms[i] = le32_to_cpu(buf32[i]);
datum.ops = &ops;
for (i = 0; i < ARRAY_SIZE(xperms.perms); i++)
xperms.perms[i] = le32_to_cpu(buf32[i]);
datum.xperms = &xperms;
} else {
rc = next_entry(buf32, fp, sizeof(uint32_t));
if (rc < 0) {

View File

@ -1604,24 +1604,25 @@ static int expand_range_trans(expand_state_t * state,
static avtab_ptr_t find_avtab_node(sepol_handle_t * handle,
avtab_t * avtab, avtab_key_t * key,
cond_av_list_t ** cond,
av_operations_t *operations)
av_extended_perms_t *xperms)
{
avtab_ptr_t node;
avtab_datum_t avdatum;
cond_av_list_t *nl;
int type_match = 0;
int match = 0;
/* AVTAB_OPNUM entries are not necessarily unique */
if (key->specified & AVTAB_OPNUM) {
/* AVTAB_XPERMS entries are not necessarily unique */
if (key->specified & AVTAB_XPERMS) {
node = avtab_search_node(avtab, key);
while (node) {
if (node->datum.ops->type == operations->type) {
type_match = 1;
if ((node->datum.xperms->specified == xperms->specified) &&
(node->datum.xperms->driver == xperms->driver)) {
match = 1;
break;
}
node = avtab_search_node_next(node, key->specified);
}
if (!type_match)
if (!match)
node = NULL;
} else {
node = avtab_search_node(avtab, key);
@ -1780,11 +1781,11 @@ static int expand_avrule_helper(sepol_handle_t * handle,
cond_av_list_t ** cond,
uint32_t stype, uint32_t ttype,
class_perm_node_t * perms, avtab_t * avtab,
int enabled, av_operations_t *operations)
int enabled, av_extended_perms_t *extended_perms)
{
avtab_key_t avkey;
avtab_datum_t *avdatump;
avtab_operations_t *ops;
avtab_extended_perms_t *xperms;
avtab_ptr_t node;
class_perm_node_t *cur;
uint32_t spec = 0;
@ -1802,22 +1803,14 @@ static int expand_avrule_helper(sepol_handle_t * handle,
spec = AVTAB_AUDITDENY;
} else if (specified & AVRULE_NEVERALLOW) {
spec = AVTAB_NEVERALLOW;
} else if (specified & AVRULE_OPNUM_ALLOWED) {
spec = AVTAB_OPNUM_ALLOWED;
} else if (specified & AVRULE_OPNUM_AUDITALLOW) {
spec = AVTAB_OPNUM_AUDITALLOW;
} else if (specified & AVRULE_OPNUM_DONTAUDIT) {
} else if (specified & AVRULE_XPERMS_ALLOWED) {
spec = AVTAB_XPERMS_ALLOWED;
} else if (specified & AVRULE_XPERMS_AUDITALLOW) {
spec = AVTAB_XPERMS_AUDITALLOW;
} else if (specified & AVRULE_XPERMS_DONTAUDIT) {
if (handle && handle->disable_dontaudit)
return EXPAND_RULE_SUCCESS;
spec = AVTAB_OPNUM_DONTAUDIT;
} else if (specified & AVRULE_OPTYPE_ALLOWED) {
spec = AVTAB_OPTYPE_ALLOWED;
} else if (specified & AVRULE_OPTYPE_AUDITALLOW) {
spec = AVTAB_OPTYPE_AUDITALLOW;
} else if (specified & AVRULE_OPTYPE_DONTAUDIT) {
if (handle && handle->disable_dontaudit)
return EXPAND_RULE_SUCCESS;
spec = AVTAB_OPTYPE_DONTAUDIT;
spec = AVTAB_XPERMS_DONTAUDIT;
} else {
assert(0); /* unreachable */
}
@ -1829,7 +1822,7 @@ static int expand_avrule_helper(sepol_handle_t * handle,
avkey.target_class = cur->tclass;
avkey.specified = spec;
node = find_avtab_node(handle, avtab, &avkey, cond, operations);
node = find_avtab_node(handle, avtab, &avkey, cond, extended_perms);
if (!node)
return EXPAND_RULE_ERROR;
if (enabled) {
@ -1859,20 +1852,21 @@ static int expand_avrule_helper(sepol_handle_t * handle,
avdatump->data &= ~cur->data;
else
avdatump->data = ~cur->data;
} else if (specified & AVRULE_OP) {
if (!avdatump->ops) {
ops = (avtab_operations_t *)
calloc(1, sizeof(avtab_operations_t));
if (!ops) {
} else if (specified & AVRULE_XPERMS) {
if (!avdatump->xperms) {
xperms = (avtab_extended_perms_t *)
calloc(1, sizeof(avtab_extended_perms_t));
if (!xperms) {
ERR(handle, "Out of memory!");
return -1;
}
node->datum.ops = ops;
}
node->datum.ops->type = operations->type;
for (i = 0; i < ARRAY_SIZE(operations->perms); i++) {
node->datum.ops->perms[i] |= operations->perms[i];
node->datum.xperms = xperms;
}
node->datum.xperms->specified = extended_perms->specified;
node->datum.xperms->driver = extended_perms->driver;
for (i = 0; i < ARRAY_SIZE(xperms->perms); i++)
node->datum.xperms->perms[i] |= extended_perms->perms[i];
} else {
assert(0); /* should never occur */
}
@ -1897,10 +1891,10 @@ static int expand_rule_helper(sepol_handle_t * handle,
if (!ebitmap_node_get_bit(snode, i))
continue;
if (source_rule->flags & RULE_SELF) {
if (source_rule->specified & (AVRULE_AV | AVRULE_OP)) {
if (source_rule->specified & (AVRULE_AV | AVRULE_XPERMS)) {
retval = expand_avrule_helper(handle, source_rule->specified,
cond, i, i, source_rule->perms,
dest_avtab, enabled, source_rule->ops);
dest_avtab, enabled, source_rule->xperms);
if (retval != EXPAND_RULE_SUCCESS)
return retval;
} else {
@ -1915,10 +1909,10 @@ static int expand_rule_helper(sepol_handle_t * handle,
ebitmap_for_each_bit(ttypes, tnode, j) {
if (!ebitmap_node_get_bit(tnode, j))
continue;
if (source_rule->specified & (AVRULE_AV | AVRULE_OP)) {
if (source_rule->specified & (AVRULE_AV | AVRULE_XPERMS)) {
retval = expand_avrule_helper(handle, source_rule->specified,
cond, i, j, source_rule->perms,
dest_avtab, enabled, source_rule->ops);
dest_avtab, enabled, source_rule->xperms);
if (retval != EXPAND_RULE_SUCCESS)
return retval;
} else {
@ -3155,24 +3149,25 @@ static int expand_avtab_insert(avtab_t * a, avtab_key_t * k, avtab_datum_t * d)
{
avtab_ptr_t node;
avtab_datum_t *avd;
avtab_operations_t *ops;
avtab_extended_perms_t *xperms;
unsigned int i;
unsigned int type_match = 0;
unsigned int match = 0;
if (k->specified & AVTAB_OPNUM) {
if (k->specified & AVTAB_XPERMS) {
/*
* AVTAB_OPNUM entries are not necessarily unique.
* find node with matching ops->type
* AVTAB_XPERMS entries are not necessarily unique.
* find node with matching xperms
*/
node = avtab_search_node(a, k);
while (node) {
if (node->datum.ops->type == d->ops->type) {
type_match = 1;
if ((node->datum.xperms->specified == d->xperms->specified) &&
(node->datum.xperms->driver == d->xperms->driver)) {
match = 1;
break;
}
node = avtab_search_node_next(node, k->specified);
}
if (!type_match)
if (!match)
node = NULL;
} else {
node = avtab_search_node(a, k);
@ -3189,7 +3184,7 @@ static int expand_avtab_insert(avtab_t * a, avtab_key_t * k, avtab_datum_t * d)
}
avd = &node->datum;
ops = node->datum.ops;
xperms = node->datum.xperms;
switch (k->specified & ~AVTAB_ENABLED) {
case AVTAB_ALLOWED:
case AVTAB_AUDITALLOW:
@ -3198,14 +3193,11 @@ static int expand_avtab_insert(avtab_t * a, avtab_key_t * k, avtab_datum_t * d)
case AVTAB_AUDITDENY:
avd->data &= d->data;
break;
case AVTAB_OPNUM_ALLOWED:
case AVTAB_OPNUM_AUDITALLOW:
case AVTAB_OPNUM_DONTAUDIT:
case AVTAB_OPTYPE_ALLOWED:
case AVTAB_OPTYPE_AUDITALLOW:
case AVTAB_OPTYPE_DONTAUDIT:
for (i = 0; i < ARRAY_SIZE(ops->perms); i++)
ops->perms[i] |= d->ops->perms[i];
case AVTAB_XPERMS_ALLOWED:
case AVTAB_XPERMS_AUDITALLOW:
case AVTAB_XPERMS_DONTAUDIT:
for (i = 0; i < ARRAY_SIZE(xperms->perms); i++)
xperms->perms[i] |= d->xperms->perms[i];
break;
default:
ERR(NULL, "Type conflict!");

View File

@ -180,7 +180,7 @@ static struct policydb_compat_info policydb_compat[] = {
},
{
.type = POLICY_KERN,
.version = POLICYDB_VERSION_IOCTL_OPERATIONS,
.version = POLICYDB_VERSION_XPERMS_IOCTL,
.sym_num = SYM_NUM,
.ocon_num = OCON_NODE6 + 1,
.target_platform = SEPOL_TARGET_SELINUX,

View File

@ -221,28 +221,32 @@ static int avtab_write_item(policydb_t * p,
items = put_entry(buf16, sizeof(uint16_t), 4, fp);
if (items != 4)
return POLICYDB_ERROR;
if ((p->policyvers < POLICYDB_VERSION_IOCTL_OPERATIONS) &&
(cur->key.specified & AVTAB_OP)) {
ERR(fp->handle, "policy version %u does not support ioctl operation"
" rules and one was specified", p->policyvers);
if ((p->policyvers < POLICYDB_VERSION_XPERMS_IOCTL) &&
(cur->key.specified & AVTAB_XPERMS)) {
ERR(fp->handle, "policy version %u does not support ioctl extended"
"permissions rules and one was specified", p->policyvers);
return POLICYDB_ERROR;
}
if (p->target_platform != SEPOL_TARGET_SELINUX &&
(cur->key.specified & AVTAB_OP)) {
(cur->key.specified & AVTAB_XPERMS)) {
ERR(fp->handle, "Target platform %s does not support ioctl "
"operation rules and one was specified",
"extended permissions rules and one was specified",
policydb_target_strings[p->target_platform]);
return POLICYDB_ERROR;
}
if (cur->key.specified & AVTAB_OP) {
buf8 = cur->datum.ops->type;
if (cur->key.specified & AVTAB_XPERMS) {
buf8 = cur->datum.xperms->specified;
items = put_entry(&buf8, sizeof(uint8_t),1,fp);
if (items != 1)
return POLICYDB_ERROR;
for (i = 0; i < ARRAY_SIZE(cur->datum.ops->perms); i++)
buf32[i] = cpu_to_le32(cur->datum.ops->perms[i]);
buf8 = cur->datum.xperms->driver;
items = put_entry(&buf8, sizeof(uint8_t),1,fp);
if (items != 1)
return POLICYDB_ERROR;
for (i = 0; i < ARRAY_SIZE(cur->datum.xperms->perms); i++)
buf32[i] = cpu_to_le32(cur->datum.xperms->perms[i]);
items = put_entry(buf32, sizeof(uint32_t),8,fp);
if (items != 8)
return POLICYDB_ERROR;
@ -1546,9 +1550,9 @@ static int avrule_write(avrule_t * avrule, struct policy_file *fp)
uint32_t buf[32], len;
class_perm_node_t *cur;
if (avrule->specified & AVRULE_OP) {
ERR(fp->handle, "module policy does not support ioctl operation"
" rules and one was specified");
if (avrule->specified & AVRULE_XPERMS) {
ERR(fp->handle, "module policy does not support extended"
" permissions rules and one was specified");
return POLICYDB_ERROR;
}