Merge remote-tracking branch 'aosp/upstream-master' into mymerge

This commit is contained in:
Jeff Vander Stoep 2015-10-28 13:14:22 -07:00
commit 10ca689116
160 changed files with 13712 additions and 7611 deletions

View File

@ -11,7 +11,6 @@ common_src_files := \
common_cflags := \
-Wall -Wshadow -O2 \
-pipe -fno-strict-aliasing \
-Wno-return-type
ifeq ($(HOST_OS),darwin)
common_cflags += -DDARWIN

View File

@ -1,3 +1,8 @@
* Add neverallow support for ioctl extended permissions, from Jeff Vander Stoep.
* fix double free on name-based type transitions, from Stephen Smalley.
* switch operations to extended perms, from Jeff Vander Stoep.
* policy_define.c: fix compiler warnings, from Nick Kralevich.
* Remove uses of -Wno-return-type, from Dan Albert.
* Fix -Wreturn-type issues, from Dan Albert.
* dispol: display operations as ranges, from Jeff Vander Stoep.
* dispol: Extend to display operations, from Stephen Smalley.

View File

@ -1521,7 +1521,8 @@ int define_compute_type_helper(int which, avrule_t ** rule)
ebitmap_node_t *node;
avrule_t *avrule;
class_perm_node_t *perm;
int i, add = 1;
uint32_t i;
int add = 1;
avrule = malloc(sizeof(avrule_t));
if (!avrule) {
@ -1728,32 +1729,27 @@ 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)))
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;
@ -1792,9 +1788,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 */
@ -1812,14 +1808,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 */
@ -1837,7 +1833,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;
@ -1862,11 +1858,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;
@ -1884,7 +1880,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;
@ -1910,27 +1906,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;
}
@ -1938,10 +1934,12 @@ 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;
class_datum_t *cladatum;
perm_datum_t *perdatum = NULL;
ebitmap_t tclasses;
ebitmap_node_t *node;
avrule_t *avrule;
@ -1959,7 +1957,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;
@ -1968,7 +1966,7 @@ int define_te_avtab_operation_helper(int which, avrule_t ** rule)
while ((id = queue_remove(id_queue))) {
if (set_types
(&avrule->stypes, id, &add,
which == AVRULE_NEVERALLOW ? 1 : 0)) {
which == AVRULE_XPERMS_NEVERALLOW ? 1 : 0)) {
ret = -1;
goto out;
}
@ -1982,7 +1980,7 @@ int define_te_avtab_operation_helper(int which, avrule_t ** rule)
}
if (set_types
(&avrule->ttypes, id, &add,
which == AVRULE_NEVERALLOW ? 1 : 0)) {
which == AVRULE_XPERMS_NEVERALLOW ? 1 : 0)) {
ret = -1;
goto out;
}
@ -1994,6 +1992,7 @@ int define_te_avtab_operation_helper(int which, avrule_t ** rule)
goto out;
perms = NULL;
id = queue_head(id_queue);
ebitmap_for_each_bit(&tclasses, node, i) {
if (!ebitmap_node_get_bit(node, i))
continue;
@ -2011,6 +2010,29 @@ int define_te_avtab_operation_helper(int which, avrule_t ** rule)
if (tail)
tail->next = cur_perms;
tail = cur_perms;
cladatum = policydbp->class_val_to_struct[i];
perdatum = hashtab_search(cladatum->permissions.table, id);
if (!perdatum) {
if (cladatum->comdatum) {
perdatum = hashtab_search(cladatum->comdatum->
permissions.table,
id);
}
}
if (!perdatum) {
yyerror2("permission %s is not defined"
" for class %s", id,
policydbp->p_class_val_to_name[i]);
continue;
} else if (!is_perm_in_scope (id, policydbp->p_class_val_to_name[i])) {
yyerror2("permission %s of class %s is"
" not within scope", id,
policydbp->p_class_val_to_name[i]);
continue;
} else {
cur_perms->data |= 1U << (perdatum->s.value - 1);
}
}
ebitmap_destroy(&tclasses);
@ -2023,95 +2045,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;
}
@ -2119,83 +2148,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;
@ -2204,12 +2236,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;
}
@ -2236,6 +2268,10 @@ int avrule_cpy(avrule_t *dest, avrule_t *src)
}
dest->line = src->line;
dest->source_filename = strdup(source_file);
if (!dest->source_filename) {
yyerror("out of memory");
return -1;
}
dest->source_line = src->source_line;
/* increment through the class perms and copy over */
@ -2261,14 +2297,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++) {
@ -2279,65 +2376,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;
}
@ -2365,7 +2415,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;
@ -2745,7 +2795,7 @@ static int dominate_role_recheck(hashtab_key_t key __attribute__ ((unused)),
role_datum_t *rdp = (role_datum_t *) arg;
role_datum_t *rdatum = (role_datum_t *) datum;
ebitmap_node_t *node;
int i;
uint32_t i;
/* Don't bother to process against self role */
if (rdatum->s.value == rdp->s.value)
@ -3291,8 +3341,14 @@ int define_filename_trans(void)
append_filename_trans(ftr);
ftr->name = strdup(name);
ftr->stypes = stypes;
ftr->ttypes = ttypes;
if (type_set_cpy(&ftr->stypes, &stypes)) {
yyerror("out of memory");
goto bad;
}
if (type_set_cpy(&ftr->ttypes, &ttypes)) {
yyerror("out of memory");
goto bad;
}
ftr->tclass = c + 1;
ftr->otype = otype;
}

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,10 @@ typedef int (* require_func_t)(int pass);
%token AUDITALLOW
%token AUDITDENY
%token DONTAUDIT
%token ALLOWXPERM
%token AUDITALLOWXPERM
%token DONTAUDITXPERM
%token NEVERALLOWXPERM
%token SOURCE
%token TARGET
%token SAMEUSER
@ -457,9 +461,10 @@ 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
| xperm_neverallow_def
;
allow_def : ALLOW names names ':' names names ';'
{if (define_te_avtab(AVRULE_ALLOWED)) return -1; }
@ -476,14 +481,17 @@ 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; }
;
xperm_neverallow_def : NEVERALLOWXPERM names names ':' names identifier xperms ';'
{if (define_te_avtab_extended_perms(AVRULE_XPERMS_NEVERALLOW)) return -1; }
;
attribute_role_def : ATTRIBUTE_ROLE identifier ';'
{if (define_attrib_role()) return -1; }
@ -749,26 +757,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,14 @@ AUDITDENY |
auditdeny { return(AUDITDENY); }
DONTAUDIT |
dontaudit { return(DONTAUDIT); }
ALLOWXPERM |
allowxperm { return(ALLOWXPERM); }
AUDITALLOWXPERM |
auditallowxperm { return(AUDITALLOWXPERM); }
DONTAUDITXPERM |
dontauditxperm { return(DONTAUDITXPERM); }
NEVERALLOWXPERM |
neverallowxperm { return(NEVERALLOWXPERM); }
SOURCE |
source { return(SOURCE); }
TARGET |

View File

@ -54,56 +54,6 @@ 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 next_bit_in_range(i, p) \
((i + 1 < sizeof(p)*8) && operation_perm_test((i + 1), p))
int render_operations(avtab_operations_t *ops, avtab_key_t * key, FILE * fp)
{
uint16_t value;
uint16_t low_bit;
uint16_t low_value;
unsigned int bit;
unsigned int in_range = 0;
fprintf(fp, "{ ");
for (bit = 0; bit < sizeof(ops->perms)*8; bit++) {
if (!operation_perm_test(bit, ops->perms))
continue;
if (in_range && next_bit_in_range(bit, ops->perms)) {
/* continue until high value found */
continue;
} else if (next_bit_in_range(bit, ops->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 (in_range)
fprintf(fp, "0x%hx-0x%hx ", low_value, value);
else
fprintf(fp, "0x%hx ", value);
} else if (key->specified & AVTAB_OPTYPE) {
value = bit << 8;
low_value = low_bit << 8;
if (in_range)
fprintf(fp, "0x%hx-0x%hx ", low_value, (uint16_t) (value|0xff));
else
fprintf(fp, "0x%hx-0x%hx ", value, (uint16_t) (value|0xff));
}
if (in_range)
in_range = 0;
}
fprintf(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,16 +147,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);
fprintf(fp, ";\n");
fprintf(fp, "%s;\n", sepol_extended_perms_to_string(datum->xperms));
} else {
fprintf(fp, " ERROR: no valid rule type specified\n");
return -1;

View File

@ -1,3 +1,30 @@
* label_file: fix memory leaks and uninitialized jump, from William Roberts.
* Replace selabel_digest hash function, from Richard Haines.
* Fix selabel_open(3) services if no digest requested, from Richard Haines.
* Add selabel_digest function, from Richard Haines.
* Fix parallel build with swig python, from Jason Zaman.
* Flush the class/perm string mapping cache on policy reload, from Stephen Smalley.
* Fix restorecon when path has no context, from Nir Soffer.
* Free memory when processing media and x specfiles, from Richard Haines.
* Fix mmap memory release for file labeling, from Richard Haines.
* Add explicit dependency for pywrap on selinux.py, from Wenzong Fan.
* Add policy context validation to sefcontext_compile, from Richard Haines.
* Do not treat an empty file_contexts(.local) as an error, from Stephen Smalley.
* Fail hard on invalid property_contexts entries, from Stephen Smalley.
* Fail hard on invalid file_contexts entries, from Stephen Smalley.
* Support context validation on file_contexts.bin, from Stephen Smalley.
* Test for file_contexts.bin format by magic number, from Stephen Smalley.
* Add selabel_cmp interface and label_file backend, from Stephen Smalley.
* Support specifying file_contexts.bin file path, from Stephen Smalley.
* Support file_contexts.bin without file_contexts, from Stephen Smalley.
* Simplify procattr cache, from Stephen Smalley.
* Use /proc/thread-self when available, from Stephen Smalley.
* Add const to selinux_opt for label backends, from Richard Haines.
* Fix binary file labels for regexes with metachars, from Richard Haines.
* Fix file labels for regexes with metachars, from Jeff Vander Stoep.
* Fix if file_contexts not '\n' terminated, from Richard Haines.
* Enhance file context support, from Richard Haines.
* Fix property processing and cleanup formatting, from Richard Haines.
* Add read_spec_entries function to replace sscanf, from Richard Haines.
* Support consistent mode size for bin files, from Richard Haines.
* Expunge remaining references to flask.h and av_permissions.h, from Stephen Smalley.

View File

@ -49,8 +49,10 @@ struct selabel_handle;
#define SELABEL_OPT_PATH 3
/* select a subset of the search space as an optimization (file backend) */
#define SELABEL_OPT_SUBSET 4
/* require a hash calculation on spec files */
#define SELABEL_OPT_DIGEST 5
/* total number of options */
#define SELABEL_NOPT 5
#define SELABEL_NOPT 6
/*
* Label operations
@ -69,7 +71,8 @@ struct selabel_handle;
* @errno set on failure.
*/
struct selabel_handle *selabel_open(unsigned int backend,
struct selinux_opt *opts, unsigned nopts);
const struct selinux_opt *opts,
unsigned nopts);
/**
* selabel_close - Close a labeling handle.
@ -105,6 +108,43 @@ int selabel_lookup_best_match(struct selabel_handle *rec, char **con,
int selabel_lookup_best_match_raw(struct selabel_handle *rec, char **con,
const char *key, const char **aliases, int type);
/**
* selabel_digest - Retrieve the SHA1 digest and the list of specfiles used to
* generate the digest. The SELABEL_OPT_DIGEST option must
* be set in selabel_open() to initiate the digest generation.
* @handle: specifies backend instance to query
* @digest: returns a pointer to the SHA1 digest.
* @digest_len: returns length of digest in bytes.
* @specfiles: a list of specfiles used in the SHA1 digest generation.
* The list is NULL terminated and will hold @num_specfiles entries.
* @num_specfiles: number of specfiles in the list.
*
* Return %0 on success, -%1 with @errno set on failure.
*/
int selabel_digest(struct selabel_handle *rec,
unsigned char **digest, size_t *digest_len,
char ***specfiles, size_t *num_specfiles);
enum selabel_cmp_result {
SELABEL_SUBSET,
SELABEL_EQUAL,
SELABEL_SUPERSET,
SELABEL_INCOMPARABLE
};
/**
* selabel_cmp - Compare two label configurations.
* @h1: handle for the first label configuration
* @h2: handle for the first label configuration
*
* Compare two label configurations.
* Return %SELABEL_SUBSET if @h1 is a subset of @h2, %SELABEL_EQUAL
* if @h1 is identical to @h2, %SELABEL_SUPERSET if @h1 is a superset
* of @h2, and %SELABEL_INCOMPARABLE if @h1 and @h2 are incomparable.
*/
enum selabel_cmp_result selabel_cmp(struct selabel_handle *h1,
struct selabel_handle *h2);
/**
* selabel_stats - log labeling operation statistics.
* @handle: specifies backend instance to query

View File

@ -0,0 +1,61 @@
.TH "selabel_digest" "3" "16 Sept 2015" "" "SELinux API documentation"
.SH "NAME"
selabel_digest \- Return digest of specfiles and list of files used
.
.SH "SYNOPSIS"
.B #include <selinux/selinux.h>
.br
.B #include <selinux/label.h>
.sp
.BI "int selabel_digest(struct selabel_handle *" hnd ,
.in +\w'int selabel_digest('u
.BI "unsigned char **" digest ,
.BI "size_t *" digest_len ,
.br
.BI "char ***" specfiles,
.BI "size_t *" num_specfiles ");"
.in
.
.SH "DESCRIPTION"
.BR selabel_digest ()
performs an operation on the handle
.IR hnd ,
returning the results of the SHA1 digest pointed to by
.IR digest ,
whose length will be
.IR digest_len .
The list of specfiles used in the SHA1 digest calculation is returned in
.I specfiles
with the number of entries in
.IR num_specfiles .
.sp
To enable
.BR selabel_digest ()
to return this information the
.B SELABEL_OPT_DIGEST
option must be enable in
.BR selabel_open (3).
.sp
The result of
.BR selabel_digest ()
must not be used after
.BR selabel_close (3).
.
.SH "RETURN VALUE"
On success, zero is returned. On error, \-1 is returned and
.I errno
is set appropriately.
.
.SH "ERRORS"
.TP
.B EINVAL
No digest available (returned if
.B SELABEL_OPT_DIGEST
option not enabled).
.TP
.B ENOMEM
An attempt to allocate memory failed.
.
.SH "SEE ALSO"
.BR selabel_open (3),
.BR selinux (8)

View File

@ -12,7 +12,7 @@ selabel_open, selabel_close \- userspace SELinux labeling interface
.sp
.BI "struct selabel_handle *selabel_open(int " backend ,
.in +\w'struct selabel_handle *selabel_open('u
.BI "struct selinux_opt *" options ,
.BI "const struct selinux_opt *" options ,
.br
.BI "unsigned " nopt ");"
.in
@ -67,6 +67,11 @@ A non-null value for this option enables context validation. By default,
is used; a custom validation function can be provided via
.BR selinux_set_callback (3).
Note that an invalid context may not be treated as an error unless it is actually encountered during a lookup operation.
.TP
.B SELABEL_OPT_DIGEST
A non-null value for this option enables the generation of an SHA1 digest of
the spec files loaded as described in
.BR selabel_digest (3)
.
.SH "BACKENDS"
.TP

View File

@ -1,15 +1,67 @@
.TH "sefcontext_compile" "8" "27 Jun 2013" "dwalsh@redhat.com" "SELinux Command Line documentation"
.TH "sefcontext_compile" "8" "12 Aug 2015" "dwalsh@redhat.com" "SELinux Command Line documentation"
.SH "NAME"
sefcontext_compile \- compile file context regular expression files
.
.SH "SYNOPSIS"
.B sefcontext_compile inputfile
.B sefcontext_compile
.RB [ \-o
.IR outputfile ]
.RB [ \-p
.IR policyfile ]
.I inputfile
.
.SH "DESCRIPTION"
sefcontext_compile is used libsemanage to compile file context regular expressions into prce format. sefcontext_compile writes the compiled prce file with the .bin suffix appended "inputfile".bin. This compiled file is used by libselinux file labeling functions.
.B sefcontext_compile
is used to compile file context regular expressions into
.BR prce (3)
format.
.sp
The compiled file is used by libselinux file labeling functions.
.sp
By default
.B sefcontext_compile
writes the compiled prce file with the
.B .bin
suffix appended (e.g. \fIinputfile\fB.bin\fR).
.SH OPTIONS
.TP
.B \-o
Specify an
.I outputfile
that must be a fully qualified file name as the
.B .bin
suffix is not automatically added.
.TP
.B \-p
Specify a binary
.I policyfile
that will be used to validate the context entries in the
.I inputfile
.br
If an invalid context is found the pcre formatted file will not be written and
an error will be returned.
.SH "EXAMPLE"
.SH "RETURN VALUE"
On error -1 is returned. On success 0 is returned.
.SH "EXAMPLES"
.B Example 1:
.br
sefcontext_compile /etc/selinux/targeted/contexts/files/file_contexts
.sp
Results in the following file being generated:
.RS
/etc/selinux/targeted/contexts/files/file_contexts.bin
.RE
.sp
.B Example 2:
.br
sefcontext_compile -o new_fc.bin /etc/selinux/targeted/contexts/files/file_contexts
.sp
Results in the following file being generated in the cwd:
.RS
new_fc.bin
.RE
.
.SH AUTHOR
Dan Walsh, <dwalsh@redhat.com>

View File

@ -29,11 +29,12 @@ LIBPC=libselinux.pc
SWIGIF= selinuxswig_python.i selinuxswig_python_exception.i
SWIGRUBYIF= selinuxswig_ruby.i
SWIGCOUT= selinuxswig_wrap.c
SWIGPYOUT= selinux.py
SWIGRUBYCOUT= selinuxswig_ruby_wrap.c
SWIGLOBJ:= $(patsubst %.c,$(PYPREFIX)%.lo,$(SWIGCOUT))
SWIGRUBYLOBJ:= $(patsubst %.c,%.lo,$(SWIGRUBYCOUT))
SWIGSO=$(PYPREFIX)_selinux.so
SWIGFILES=$(SWIGSO) selinux.py
SWIGFILES=$(SWIGSO) $(SWIGPYOUT)
SWIGRUBYSO=$(RUBYPREFIX)_selinux.so
LIBSO=$(TARGET).$(LIBVERSION)
AUDIT2WHYLOBJ=$(PYPREFIX)audit2why.lo
@ -90,7 +91,7 @@ SWIGRUBY = swig -Wall -ruby -o $(SWIGRUBYCOUT) -outdir ./
all: $(LIBA) $(LIBSO) $(LIBPC)
pywrap: all $(SWIGSO) $(AUDIT2WHYSO)
pywrap: all $(SWIGFILES) $(AUDIT2WHYSO)
rubywrap: all $(SWIGRUBYSO)
@ -135,6 +136,8 @@ $(AUDIT2WHYSO): $(AUDIT2WHYLOBJ)
$(SWIGCOUT): $(SWIGIF)
$(SWIG) $<
$(SWIGPYOUT): $(SWIGCOUT)
$(SWIGRUBYCOUT): $(SWIGRUBYIF)
$(SWIGRUBY) $<
@ -154,7 +157,7 @@ install-pywrap: pywrap
test -d $(PYLIBDIR)/site-packages/selinux || install -m 755 -d $(PYLIBDIR)/site-packages/selinux
install -m 755 $(SWIGSO) $(PYLIBDIR)/site-packages/selinux/_selinux.so
install -m 755 $(AUDIT2WHYSO) $(PYLIBDIR)/site-packages/selinux/audit2why.so
install -m 644 selinux.py $(PYLIBDIR)/site-packages/selinux/__init__.py
install -m 644 $(SWIGPYOUT) $(PYLIBDIR)/site-packages/selinux/__init__.py
install-rubywrap: rubywrap
test -d $(RUBYINSTALL) || install -m 755 -d $(RUBYINSTALL)

View File

@ -10,11 +10,26 @@
static pthread_once_t once = PTHREAD_ONCE_INIT;
static int selinux_enabled;
static int avc_reset_callback(uint32_t event __attribute__((unused)),
security_id_t ssid __attribute__((unused)),
security_id_t tsid __attribute__((unused)),
security_class_t tclass __attribute__((unused)),
access_vector_t perms __attribute__((unused)),
access_vector_t *out_retained __attribute__((unused)))
{
flush_class_cache();
return 0;
}
static void avc_init_once(void)
{
selinux_enabled = is_selinux_enabled();
if (selinux_enabled == 1)
avc_open(NULL, 0);
if (selinux_enabled == 1) {
if (avc_open(NULL, 0))
return;
avc_add_callback(avc_reset_callback, AVC_CALLBACK_RESET,
0, 0, 0, 0);
}
}
int selinux_check_access(const char *scon, const char *tcon, const char *class, const char *perm, void *aux) {
@ -33,9 +48,11 @@ int selinux_check_access(const char *scon, const char *tcon, const char *class,
if (rc < 0)
return rc;
rc = avc_context_to_sid(tcon, &tcon_id);
if (rc < 0)
return rc;
rc = avc_context_to_sid(tcon, &tcon_id);
if (rc < 0)
return rc;
(void) avc_netlink_check_nb();
sclass = string_to_security_class(class);
if (sclass == 0) {

View File

@ -10,6 +10,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <selinux/selinux.h>
#include "callbacks.h"
#include "label_internal.h"
@ -17,7 +18,8 @@
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
typedef int (*selabel_initfunc)(struct selabel_handle *rec,
struct selinux_opt *opts, unsigned nopts);
const struct selinux_opt *opts,
unsigned nopts);
static selabel_initfunc initfuncs[] = {
&selabel_file_init,
@ -64,15 +66,21 @@ static char *selabel_sub(struct selabel_sub *ptr, const char *src)
return NULL;
}
struct selabel_sub *selabel_subs_init(const char *path, struct selabel_sub *list)
struct selabel_sub *selabel_subs_init(const char *path,
struct selabel_sub *list,
struct selabel_digest *digest)
{
char buf[1024];
FILE *cfg = fopen(path, "r");
struct selabel_sub *sub;
struct selabel_sub *sub = NULL;
struct stat sb;
if (!cfg)
return list;
if (fstat(fileno(cfg), &sb) < 0)
return list;
while (fgets_unlocked(buf, sizeof(buf) - 1, cfg)) {
char *ptr = NULL;
char *src = buf;
@ -114,6 +122,10 @@ struct selabel_sub *selabel_subs_init(const char *path, struct selabel_sub *list
sub->next = list;
list = sub;
}
if (digest_add_specfile(digest, cfg, NULL, sb.st_size, path) < 0)
goto err;
out:
fclose(cfg);
return list;
@ -124,11 +136,63 @@ err:
goto out;
}
static inline struct selabel_digest *selabel_is_digest_set
(const struct selinux_opt *opts,
unsigned n,
struct selabel_digest *entry)
{
struct selabel_digest *digest = NULL;
while (n--) {
if (opts[n].type == SELABEL_OPT_DIGEST &&
opts[n].value == (char *)1) {
digest = calloc(1, sizeof(*digest));
if (!digest)
goto err;
digest->digest = calloc(1, DIGEST_SPECFILE_SIZE + 1);
if (!digest->digest)
goto err;
digest->specfile_list = calloc(DIGEST_FILES_MAX,
sizeof(char *));
if (!digest->specfile_list)
goto err;
entry = digest;
return entry;
}
}
return NULL;
err:
free(digest->digest);
free(digest->specfile_list);
free(digest);
return NULL;
}
static void selabel_digest_fini(struct selabel_digest *ptr)
{
int i;
free(ptr->digest);
free(ptr->hashbuf);
if (ptr->specfile_list) {
for (i = 0; ptr->specfile_list[i]; i++)
free(ptr->specfile_list[i]);
free(ptr->specfile_list);
}
free(ptr);
}
/*
* Validation functions
*/
static inline int selabel_is_validate_set(struct selinux_opt *opts, unsigned n)
static inline int selabel_is_validate_set(const struct selinux_opt *opts,
unsigned n)
{
while (n--)
if (opts[n].type == SELABEL_OPT_VALIDATE)
@ -251,7 +315,8 @@ selabel_lookup_bm_common(struct selabel_handle *rec, int translating,
*/
struct selabel_handle *selabel_open(unsigned int backend,
struct selinux_opt *opts, unsigned nopts)
const struct selinux_opt *opts,
unsigned nopts)
{
struct selabel_handle *rec = NULL;
@ -270,8 +335,10 @@ struct selabel_handle *selabel_open(unsigned int backend,
rec->subs = NULL;
rec->dist_subs = NULL;
rec->digest = selabel_is_digest_set(opts, nopts, rec->digest);
if ((*initfuncs[backend])(rec, opts, nopts)) {
free(rec->spec_file);
free(rec);
rec = NULL;
}
@ -366,10 +433,37 @@ int selabel_lookup_best_match_raw(struct selabel_handle *rec, char **con,
return *con ? 0 : -1;
}
enum selabel_cmp_result selabel_cmp(struct selabel_handle *h1,
struct selabel_handle *h2)
{
if (!h1->func_cmp || h1->func_cmp != h2->func_cmp)
return SELABEL_INCOMPARABLE;
return h1->func_cmp(h1, h2);
}
int selabel_digest(struct selabel_handle *rec,
unsigned char **digest, size_t *digest_len,
char ***specfiles, size_t *num_specfiles)
{
if (!rec->digest) {
errno = EINVAL;
return -1;
}
*digest = rec->digest->digest;
*digest_len = DIGEST_SPECFILE_SIZE;
*specfiles = rec->digest->specfile_list;
*num_specfiles = rec->digest->specfile_cnt;
return 0;
}
void selabel_close(struct selabel_handle *rec)
{
selabel_subs_fini(rec->subs);
selabel_subs_fini(rec->dist_subs);
if (rec->digest)
selabel_digest_fini(rec->digest);
rec->func_close(rec);
free(rec->spec_file);
free(rec);

View File

@ -1,5 +1,5 @@
/*
* Property Service contexts backend for labeling Android
* Property Service contexts backend for labeling Android
* property keys
*/
@ -16,7 +16,7 @@
/* A property security context specification. */
typedef struct spec {
struct selabel_lookup_rec lr; /* holds contexts for lookup result */
char *property_key; /* property key string */
char *property_key; /* property key string */
} spec_t;
/* Our stored configuration */
@ -56,21 +56,23 @@ static int nodups_specs(struct saved_data *data, const char *path)
for (ii = 0; ii < data->nspec; ii++) {
curr_spec = &spec_arr[ii];
for (jj = ii + 1; jj < data->nspec; jj++) {
if (!strcmp(spec_arr[jj].property_key, curr_spec->property_key)) {
if (!strcmp(spec_arr[jj].property_key,
curr_spec->property_key)) {
rc = -1;
errno = EINVAL;
if (strcmp(spec_arr[jj].lr.ctx_raw, curr_spec->lr.ctx_raw)) {
selinux_log(SELINUX_ERROR,
"%s: Multiple different specifications for %s (%s and %s).\n",
path,
curr_spec->property_key,
spec_arr[jj].lr.ctx_raw,
curr_spec->lr.ctx_raw);
if (strcmp(spec_arr[jj].lr.ctx_raw,
curr_spec->lr.ctx_raw)) {
selinux_log
(SELINUX_ERROR,
"%s: Multiple different specifications for %s (%s and %s).\n",
path, curr_spec->property_key,
spec_arr[jj].lr.ctx_raw,
curr_spec->lr.ctx_raw);
} else {
selinux_log(SELINUX_ERROR,
"%s: Multiple same specifications for %s.\n",
path,
curr_spec->property_key);
selinux_log
(SELINUX_ERROR,
"%s: Multiple same specifications for %s.\n",
path, curr_spec->property_key);
}
}
}
@ -92,36 +94,29 @@ static int process_line(struct selabel_handle *rec,
if (items <= 0)
return items;
if (items != 2) {
selinux_log(SELINUX_WARNING,
"%s: line %u is missing fields, skipping\n", path,
selinux_log(SELINUX_ERROR,
"%s: line %u is missing fields\n", path,
lineno);
return 0;
free(prop);
errno = EINVAL;
return -1;
}
if (pass == 1) {
if (pass == 0) {
free(prop);
free(context);
} else if (pass == 1) {
/* On the second pass, process and store the specification in spec. */
spec_arr[nspec].property_key = strdup(prop);
if (!spec_arr[nspec].property_key) {
selinux_log(SELINUX_WARNING,
"%s: out of memory at line %u on prop %s\n",
path, lineno, prop);
return -1;
}
spec_arr[nspec].lr.ctx_raw = strdup(context);
if (!spec_arr[nspec].lr.ctx_raw) {
selinux_log(SELINUX_WARNING,
"%s: out of memory at line %u on context %s\n",
path, lineno, context);
return -1;
}
spec_arr[nspec].property_key = prop;
spec_arr[nspec].lr.ctx_raw = context;
if (rec->validating) {
if (selabel_validate(rec, &spec_arr[nspec].lr) < 0) {
selinux_log(SELINUX_WARNING,
selinux_log(SELINUX_ERROR,
"%s: line %u has invalid context %s\n",
path, lineno, spec_arr[nspec].lr.ctx_raw);
errno = EINVAL;
return -1;
}
}
}
@ -130,7 +125,7 @@ static int process_line(struct selabel_handle *rec,
return 0;
}
static int init(struct selabel_handle *rec, struct selinux_opt *opts,
static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
unsigned n)
{
struct saved_data *data = (struct saved_data *)rec->data;
@ -149,7 +144,7 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
break;
}
if (!path)
if (!path)
return -1;
/* Open the specification file. */
@ -164,17 +159,18 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
/*
* Two passes of the specification file. First is to get the size.
* After the first pass, the spec array is malloced to the appropriate
* size. Second pass is to populate the spec array and check for
* After the first pass, the spec array is malloced to the appropriate
* size. Second pass is to populate the spec array and check for
* dups.
*/
maxnspec = UINT_MAX / sizeof(spec_t);
for (pass = 0; pass < 2; pass++) {
data->nspec = 0;
while (fgets(line_buf, sizeof line_buf - 1, fp)
while (fgets(line_buf, sizeof(line_buf) - 1, fp)
&& data->nspec < maxnspec) {
if (process_line(rec, path, line_buf, pass, ++lineno) != 0)
if (process_line(rec, path, line_buf, pass, ++lineno)
!= 0)
goto finish;
}
@ -186,7 +182,6 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
}
if (pass == 0) {
if (data->nspec == 0) {
status = 0;
goto finish;
@ -204,7 +199,12 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
qsort(data->spec_arr, data->nspec, sizeof(struct spec), cmp);
status = 0;
status = digest_add_specfile(rec->digest, fp, NULL, sb.st_size, path);
if (status)
goto finish;
digest_gen_hash(rec->digest);
finish:
fclose(fp);
return status;
@ -234,7 +234,7 @@ static void closef(struct selabel_handle *rec)
static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
const char *key,
int __attribute__ ((unused)) type)
int __attribute__((unused)) type)
{
struct saved_data *data = (struct saved_data *)rec->data;
spec_t *spec_arr = data->spec_arr;
@ -267,12 +267,13 @@ finish:
return ret;
}
static void stats(struct selabel_handle __attribute__ ((unused)) * rec)
static void stats(struct selabel_handle __attribute__((unused)) *rec)
{
selinux_log(SELINUX_WARNING, "'stats' functionality not implemented.\n");
}
int selabel_property_init(struct selabel_handle *rec, struct selinux_opt *opts,
int selabel_property_init(struct selabel_handle *rec,
const struct selinux_opt *opts,
unsigned nopts)
{
struct saved_data *data;

View File

@ -234,7 +234,8 @@ db_stats(struct selabel_handle *rec)
* selabel_open() handler
*/
static catalog_t *
db_init(struct selinux_opt *opts, unsigned nopts, struct selabel_handle *rec)
db_init(const struct selinux_opt *opts, unsigned nopts,
struct selabel_handle *rec)
{
catalog_t *catalog;
FILE *filp;
@ -243,6 +244,7 @@ db_init(struct selinux_opt *opts, unsigned nopts, struct selabel_handle *rec)
size_t line_len = 0;
unsigned int line_num = 0;
unsigned int i;
struct stat sb;
/*
* Initialize catalog data structure
@ -279,6 +281,12 @@ db_init(struct selinux_opt *opts, unsigned nopts, struct selabel_handle *rec)
free(catalog);
return NULL;
}
if (fstat(fileno(filp), &sb) < 0)
return NULL;
if (!S_ISREG(sb.st_mode)) {
errno = EINVAL;
return NULL;
}
rec->spec_file = strdup(path);
/*
@ -311,6 +319,11 @@ db_init(struct selinux_opt *opts, unsigned nopts, struct selabel_handle *rec)
}
free(line_buf);
if (digest_add_specfile(rec->digest, filp, NULL, sb.st_size, path) < 0)
goto out_error;
digest_gen_hash(rec->digest);
fclose(filp);
return catalog;
@ -332,7 +345,7 @@ out_error:
* Initialize selabel_handle and load the entries of specfile
*/
int selabel_db_init(struct selabel_handle *rec,
struct selinux_opt *opts, unsigned nopts)
const struct selinux_opt *opts, unsigned nopts)
{
rec->func_close = &db_close;
rec->func_lookup = &db_lookup;

View File

@ -5,6 +5,7 @@
* Author : Stephen Smalley <sds@tycho.nsa.gov>
*/
#include <assert.h>
#include <fcntl.h>
#include <stdarg.h>
#include <string.h>
@ -15,13 +16,11 @@
#include <limits.h>
#include <stdint.h>
#include <pcre.h>
#include <linux/limits.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "callbacks.h"
#include "label_internal.h"
#include "label_file.h"
@ -72,12 +71,14 @@ static int nodups_specs(struct saved_data *data, const char *path)
for (ii = 0; ii < data->nspec; ii++) {
curr_spec = &spec_arr[ii];
for (jj = ii + 1; jj < data->nspec; jj++) {
if ((!strcmp(spec_arr[jj].regex_str, curr_spec->regex_str))
if ((!strcmp(spec_arr[jj].regex_str,
curr_spec->regex_str))
&& (!spec_arr[jj].mode || !curr_spec->mode
|| spec_arr[jj].mode == curr_spec->mode)) {
rc = -1;
errno = EINVAL;
if (strcmp(spec_arr[jj].lr.ctx_raw, curr_spec->lr.ctx_raw)) {
if (strcmp(spec_arr[jj].lr.ctx_raw,
curr_spec->lr.ctx_raw)) {
COMPAT_LOG
(SELINUX_ERROR,
"%s: Multiple different specifications for %s (%s and %s).\n",
@ -96,136 +97,9 @@ static int nodups_specs(struct saved_data *data, const char *path)
return rc;
}
static int compile_regex(struct saved_data *data, struct spec *spec, const char **errbuf)
{
const char *tmperrbuf;
char *reg_buf, *anchored_regex, *cp;
struct stem *stem_arr = data->stem_arr;
size_t len;
int erroff;
if (spec->regcomp)
return 0; /* already done */
/* Skip the fixed stem. */
reg_buf = spec->regex_str;
if (spec->stem_id >= 0)
reg_buf += stem_arr[spec->stem_id].len;
/* Anchor the regular expression. */
len = strlen(reg_buf);
cp = anchored_regex = malloc(len + 3);
if (!anchored_regex)
return -1;
/* Create ^...$ regexp. */
*cp++ = '^';
cp = mempcpy(cp, reg_buf, len);
*cp++ = '$';
*cp = '\0';
/* Compile the regular expression. */
spec->regex = pcre_compile(anchored_regex, PCRE_DOTALL, &tmperrbuf, &erroff, NULL);
free(anchored_regex);
if (!spec->regex) {
if (errbuf)
*errbuf=tmperrbuf;
return -1;
}
spec->sd = pcre_study(spec->regex, 0, &tmperrbuf);
if (!spec->sd && tmperrbuf) {
if (errbuf)
*errbuf=tmperrbuf;
return -1;
}
/* Done. */
spec->regcomp = 1;
return 0;
}
static int process_line(struct selabel_handle *rec,
const char *path, const char *prefix,
char *line_buf, unsigned lineno)
{
int items, len, rc;
char *regex = NULL, *type = NULL, *context = NULL;
struct saved_data *data = (struct saved_data *)rec->data;
struct spec *spec_arr;
unsigned int nspec = data->nspec;
const char *errbuf = NULL;
items = read_spec_entries(line_buf, 3, &regex, &type, &context);
if (items <= 0)
return items;
if (items < 2) {
COMPAT_LOG(SELINUX_WARNING,
"%s: line %u is missing fields, skipping\n", path,
lineno);
if (items == 1)
free(regex);
return 0;
} else if (items == 2) {
/* The type field is optional. */
free(context);
context = type;
type = 0;
}
len = get_stem_from_spec(regex);
if (len && prefix && strncmp(prefix, regex, len)) {
/* Stem of regex does not match requested prefix, discard. */
free(regex);
free(type);
free(context);
return 0;
}
rc = grow_specs(data);
if (rc)
return rc;
spec_arr = data->spec_arr;
/* process and store the specification in spec. */
spec_arr[nspec].stem_id = find_stem_from_spec(data, regex);
spec_arr[nspec].regex_str = regex;
if (rec->validating && compile_regex(data, &spec_arr[nspec], &errbuf)) {
COMPAT_LOG(SELINUX_WARNING, "%s: line %u has invalid regex %s: %s\n",
path, lineno, regex, (errbuf ? errbuf : "out of memory"));
}
/* Convert the type string to a mode format */
spec_arr[nspec].type_str = type;
spec_arr[nspec].mode = 0;
if (type) {
mode_t mode = string_to_mode(type);
if (mode == (mode_t)-1) {
COMPAT_LOG(SELINUX_WARNING, "%s: line %u has invalid file type %s\n",
path, lineno, type);
mode = 0;
}
spec_arr[nspec].mode = mode;
}
spec_arr[nspec].lr.ctx_raw = context;
/* Determine if specification has
* any meta characters in the RE */
spec_hasMetaChars(&spec_arr[nspec]);
if (strcmp(context, "<<none>>") && rec->validating)
compat_validate(rec, &spec_arr[nspec].lr, path, lineno);
data->nspec = ++nspec;
return 0;
}
static int load_mmap(struct selabel_handle *rec, const char *path, struct stat *sb)
static int load_mmap(struct selabel_handle *rec, const char *path,
struct stat *sb, bool isbinary,
struct selabel_digest *digest)
{
struct saved_data *data = (struct saved_data *)rec->data;
char mmap_path[PATH_MAX + 1];
@ -239,9 +113,16 @@ static int load_mmap(struct selabel_handle *rec, const char *path, struct stat *
uint32_t i, magic, version;
uint32_t entry_len, stem_map_len, regex_array_len;
rc = snprintf(mmap_path, sizeof(mmap_path), "%s.bin", path);
if (rc >= (int)sizeof(mmap_path))
return -1;
if (isbinary) {
len = strlen(path);
if (len >= sizeof(mmap_path))
return -1;
strcpy(mmap_path, path);
} else {
rc = snprintf(mmap_path, sizeof(mmap_path), "%s.bin", path);
if (rc >= (int)sizeof(mmap_path))
return -1;
}
mmapfd = open(mmap_path, O_RDONLY | O_CLOEXEC);
if (mmapfd < 0)
@ -259,12 +140,6 @@ static int load_mmap(struct selabel_handle *rec, const char *path, struct stat *
return -1;
}
if (mmap_stat.st_mtime == sb->st_mtime &&
mmap_stat.st_mtim.tv_nsec < sb->st_mtim.tv_nsec) {
close(mmapfd);
return -1;
}
/* ok, read it in... */
len = mmap_stat.st_size;
len += (sysconf(_SC_PAGE_SIZE) - 1);
@ -285,8 +160,8 @@ static int load_mmap(struct selabel_handle *rec, const char *path, struct stat *
}
/* save where we mmap'd the file to cleanup on close() */
mmap_area->addr = addr;
mmap_area->len = len;
mmap_area->addr = mmap_area->next_addr = addr;
mmap_area->len = mmap_area->next_len = len;
mmap_area->next = data->mmap_areas;
data->mmap_areas = mmap_area;
@ -357,7 +232,7 @@ static int load_mmap(struct selabel_handle *rec, const char *path, struct stat *
/* Check for stem_len wrap around. */
if (stem_len < UINT32_MAX) {
buf = (char *)mmap_area->addr;
buf = (char *)mmap_area->next_addr;
/* Check if over-run before null check. */
rc = next_entry(NULL, mmap_area, (stem_len + 1));
if (rc < 0)
@ -395,7 +270,7 @@ static int load_mmap(struct selabel_handle *rec, const char *path, struct stat *
for (i = 0; i < regex_array_len; i++) {
struct spec *spec;
int32_t stem_id, meta_chars;
uint32_t mode = 0;
uint32_t mode = 0, prefix_len = 0;
rc = grow_specs(data);
if (rc < 0)
@ -428,6 +303,14 @@ static int load_mmap(struct selabel_handle *rec, const char *path, struct stat *
}
spec->lr.ctx_raw = str_buf;
if (strcmp(spec->lr.ctx_raw, "<<none>>") && rec->validating) {
if (selabel_validate(rec, &spec->lr) < 0) {
selinux_log(SELINUX_ERROR,
"%s: context %s is invalid\n", mmap_path, spec->lr.ctx_raw);
goto err;
}
}
/* Process regex string */
rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t));
if (rc < 0 || !entry_len) {
@ -435,7 +318,7 @@ static int load_mmap(struct selabel_handle *rec, const char *path, struct stat *
goto err;
}
spec->regex_str = (char *)mmap_area->addr;
spec->regex_str = (char *)mmap_area->next_addr;
rc = next_entry(NULL, mmap_area, entry_len);
if (rc < 0)
goto err;
@ -460,7 +343,7 @@ static int load_mmap(struct selabel_handle *rec, const char *path, struct stat *
if (rc < 0)
goto err;
if (stem_id < 0 || stem_id >= stem_map_len)
if (stem_id < 0 || stem_id >= (int32_t)stem_map_len)
spec->stem_id = -1;
else
spec->stem_id = stem_map[stem_id];
@ -471,6 +354,15 @@ static int load_mmap(struct selabel_handle *rec, const char *path, struct stat *
goto err;
spec->hasMetaChars = meta_chars;
/* and prefix length for use by selabel_lookup_best_match */
if (version >= SELINUX_COMPILED_FCONTEXT_PREFIX_LEN) {
rc = next_entry(&prefix_len, mmap_area,
sizeof(uint32_t));
if (rc < 0)
goto err;
spec->prefix_len = prefix_len;
}
/* Process regex and study_data entries */
rc = next_entry(&entry_len, mmap_area, sizeof(uint32_t));
@ -478,7 +370,7 @@ static int load_mmap(struct selabel_handle *rec, const char *path, struct stat *
rc = -1;
goto err;
}
spec->regex = (pcre *)mmap_area->addr;
spec->regex = (pcre *)mmap_area->next_addr;
rc = next_entry(NULL, mmap_area, entry_len);
if (rc < 0)
goto err;
@ -496,7 +388,7 @@ static int load_mmap(struct selabel_handle *rec, const char *path, struct stat *
rc = -1;
goto err;
}
spec->lsd.study_data = (void *)mmap_area->addr;
spec->lsd.study_data = (void *)mmap_area->next_addr;
spec->lsd.flags |= PCRE_EXTRA_STUDY_DATA;
rc = next_entry(NULL, mmap_area, entry_len);
if (rc < 0)
@ -512,27 +404,36 @@ static int load_mmap(struct selabel_handle *rec, const char *path, struct stat *
data->nspec++;
}
/* win */
rc = 0;
rc = digest_add_specfile(digest, NULL, addr, mmap_stat.st_size,
mmap_path);
if (rc)
goto err;
err:
free(stem_map);
return rc;
}
static int process_file(const char *path, const char *suffix, struct selabel_handle *rec, const char *prefix)
static int process_file(const char *path, const char *suffix,
struct selabel_handle *rec,
const char *prefix, struct selabel_digest *digest)
{
FILE *fp;
struct stat sb;
unsigned int lineno;
size_t line_len;
size_t line_len = 0;
char *line_buf = NULL;
int rc;
char stack_path[PATH_MAX + 1];
bool isbinary = false;
uint32_t magic;
/* append the path suffix if we have one */
if (suffix) {
rc = snprintf(stack_path, sizeof(stack_path), "%s.%s", path, suffix);
rc = snprintf(stack_path, sizeof(stack_path),
"%s.%s", path, suffix);
if (rc >= (int)sizeof(stack_path)) {
errno = ENAMETOOLONG;
return -1;
@ -541,38 +442,74 @@ static int process_file(const char *path, const char *suffix, struct selabel_han
}
/* Open the specification file. */
if ((fp = fopen(path, "r")) == NULL)
return -1;
__fsetlocking(fp, FSETLOCKING_BYCALLER);
fp = fopen(path, "r");
if (fp) {
__fsetlocking(fp, FSETLOCKING_BYCALLER);
if (fstat(fileno(fp), &sb) < 0)
return -1;
if (!S_ISREG(sb.st_mode)) {
errno = EINVAL;
return -1;
if (fstat(fileno(fp), &sb) < 0)
return -1;
if (!S_ISREG(sb.st_mode)) {
errno = EINVAL;
return -1;
}
magic = 0;
if (fread(&magic, sizeof magic, 1, fp) != 1) {
if (ferror(fp)) {
errno = EINVAL;
fclose(fp);
return -1;
}
clearerr(fp);
}
if (magic == SELINUX_MAGIC_COMPILED_FCONTEXT) {
/* file_contexts.bin format */
fclose(fp);
fp = NULL;
isbinary = true;
} else {
rewind(fp);
}
} else {
/*
* Text file does not exist, so clear the timestamp
* so that we will always pass the timestamp comparison
* with the bin file in load_mmap().
*/
sb.st_mtime = 0;
}
rc = load_mmap(rec, path, &sb);
rc = load_mmap(rec, path, &sb, isbinary, digest);
if (rc == 0)
goto out;
if (!fp)
return -1; /* no text or bin file */
/*
* The do detailed validation of the input and fill the spec array
* Then do detailed validation of the input and fill the spec array
*/
lineno = 0;
rc = 0;
while (getline(&line_buf, &line_len, fp) > 0) {
rc = process_line(rec, path, prefix, line_buf, ++lineno);
if (rc)
return rc;
goto out;
}
rc = digest_add_specfile(digest, fp, NULL, sb.st_size, path);
out:
free(line_buf);
fclose(fp);
return 0;
if (fp)
fclose(fp);
return rc;
}
static int init(struct selabel_handle *rec, struct selinux_opt *opts,
static void closef(struct selabel_handle *rec);
static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
unsigned n)
{
struct saved_data *data = (struct saved_data *)rec->data;
@ -597,22 +534,27 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
/* Process local and distribution substitution files */
if (!path) {
rec->dist_subs = selabel_subs_init(selinux_file_context_subs_dist_path(), rec->dist_subs);
rec->subs = selabel_subs_init(selinux_file_context_subs_path(), rec->subs);
rec->dist_subs =
selabel_subs_init(selinux_file_context_subs_dist_path(),
rec->dist_subs, rec->digest);
rec->subs = selabel_subs_init(selinux_file_context_subs_path(),
rec->subs, rec->digest);
path = selinux_file_context_path();
} else {
snprintf(subs_file, sizeof(subs_file), "%s.subs_dist", path);
rec->dist_subs = selabel_subs_init(subs_file, rec->dist_subs);
rec->dist_subs = selabel_subs_init(subs_file, rec->dist_subs,
rec->digest);
snprintf(subs_file, sizeof(subs_file), "%s.subs", path);
rec->subs = selabel_subs_init(subs_file, rec->subs);
rec->subs = selabel_subs_init(subs_file, rec->subs,
rec->digest);
}
rec->spec_file = strdup(path);
/*
/*
* The do detailed validation of the input and fill the spec array
*/
status = process_file(path, NULL, rec, prefix);
status = process_file(path, NULL, rec, prefix, rec->digest);
if (status)
goto finish;
@ -623,21 +565,25 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
}
if (!baseonly) {
status = process_file(path, "homedirs", rec, prefix);
status = process_file(path, "homedirs", rec, prefix,
rec->digest);
if (status && errno != ENOENT)
goto finish;
status = process_file(path, "local", rec, prefix);
status = process_file(path, "local", rec, prefix,
rec->digest);
if (status && errno != ENOENT)
goto finish;
}
digest_gen_hash(rec->digest);
status = sort_specs(data);
status = 0;
finish:
if (status)
free(data->spec_arr);
closef(rec);
return status;
}
@ -731,7 +677,7 @@ static struct spec *lookup_common(struct selabel_handle *rec,
if (partial)
pcre_options |= PCRE_PARTIAL_SOFT;
/*
/*
* Check for matching specifications in reverse order, so that
* the last matching specification is used.
*/
@ -857,6 +803,96 @@ out:
return lr;
}
static enum selabel_cmp_result incomp(struct spec *spec1, struct spec *spec2, const char *reason, int i, int j)
{
selinux_log(SELINUX_INFO,
"selabel_cmp: mismatched %s on entry %d: (%s, %x, %s) vs entry %d: (%s, %x, %s)\n",
reason,
i, spec1->regex_str, spec1->mode, spec1->lr.ctx_raw,
j, spec2->regex_str, spec2->mode, spec2->lr.ctx_raw);
return SELABEL_INCOMPARABLE;
}
static enum selabel_cmp_result cmp(struct selabel_handle *h1,
struct selabel_handle *h2)
{
struct saved_data *data1 = (struct saved_data *)h1->data;
struct saved_data *data2 = (struct saved_data *)h2->data;
unsigned int i, nspec1 = data1->nspec, j, nspec2 = data2->nspec;
struct spec *spec_arr1 = data1->spec_arr, *spec_arr2 = data2->spec_arr;
struct stem *stem_arr1 = data1->stem_arr, *stem_arr2 = data2->stem_arr;
bool skipped1 = false, skipped2 = false;
i = 0;
j = 0;
while (i < nspec1 && j < nspec2) {
struct spec *spec1 = &spec_arr1[i];
struct spec *spec2 = &spec_arr2[j];
/*
* Because sort_specs() moves exact pathnames to the
* end, we might need to skip over additional regex
* entries that only exist in one of the configurations.
*/
if (!spec1->hasMetaChars && spec2->hasMetaChars) {
j++;
skipped2 = true;
continue;
}
if (spec1->hasMetaChars && !spec2->hasMetaChars) {
i++;
skipped1 = true;
continue;
}
if (spec1->regcomp && spec2->regcomp) {
size_t len1, len2;
int rc;
rc = pcre_fullinfo(spec1->regex, NULL, PCRE_INFO_SIZE, &len1);
assert(rc == 0);
rc = pcre_fullinfo(spec2->regex, NULL, PCRE_INFO_SIZE, &len2);
assert(rc == 0);
if (len1 != len2 ||
memcmp(spec1->regex, spec2->regex, len1))
return incomp(spec1, spec2, "regex", i, j);
} else {
if (strcmp(spec1->regex_str, spec2->regex_str))
return incomp(spec1, spec2, "regex_str", i, j);
}
if (spec1->mode != spec2->mode)
return incomp(spec1, spec2, "mode", i, j);
if (spec1->stem_id == -1 && spec2->stem_id != -1)
return incomp(spec1, spec2, "stem_id", i, j);
if (spec2->stem_id == -1 && spec1->stem_id != -1)
return incomp(spec1, spec2, "stem_id", i, j);
if (spec1->stem_id != -1 && spec2->stem_id != -1) {
struct stem *stem1 = &stem_arr1[spec1->stem_id];
struct stem *stem2 = &stem_arr2[spec2->stem_id];
if (stem1->len != stem2->len ||
strncmp(stem1->buf, stem2->buf, stem1->len))
return incomp(spec1, spec2, "stem", i, j);
}
if (strcmp(spec1->lr.ctx_raw, spec2->lr.ctx_raw))
return incomp(spec1, spec2, "ctx_raw", i, j);
i++;
j++;
}
if ((skipped1 || i < nspec1) && !skipped2)
return SELABEL_SUPERSET;
if ((skipped2 || j < nspec2) && !skipped1)
return SELABEL_SUBSET;
if (skipped1 && skipped2)
return SELABEL_INCOMPARABLE;
return SELABEL_EQUAL;
}
static void stats(struct selabel_handle *rec)
{
@ -882,8 +918,9 @@ static void stats(struct selabel_handle *rec)
}
}
int selabel_file_init(struct selabel_handle *rec, struct selinux_opt *opts,
unsigned nopts)
int selabel_file_init(struct selabel_handle *rec,
const struct selinux_opt *opts,
unsigned nopts)
{
struct saved_data *data;
@ -898,6 +935,7 @@ int selabel_file_init(struct selabel_handle *rec, struct selinux_opt *opts,
rec->func_lookup = &lookup;
rec->func_partial_match = &partial_match;
rec->func_lookup_best_match = &lookup_best_match;
rec->func_cmp = &cmp;
return init(rec, opts, nopts);
}

View File

@ -3,6 +3,7 @@
#include <sys/stat.h>
#include "callbacks.h"
#include "label_internal.h"
#define SELINUX_MAGIC_COMPILED_FCONTEXT 0xf97cff8a
@ -11,10 +12,11 @@
#define SELINUX_COMPILED_FCONTEXT_NOPCRE_VERS 1
#define SELINUX_COMPILED_FCONTEXT_PCRE_VERS 2
#define SELINUX_COMPILED_FCONTEXT_MODE 3
#define SELINUX_COMPILED_FCONTEXT_PREFIX_LEN 4
#define SELINUX_COMPILED_FCONTEXT_MAX_VERS SELINUX_COMPILED_FCONTEXT_MODE
#define SELINUX_COMPILED_FCONTEXT_MAX_VERS SELINUX_COMPILED_FCONTEXT_PREFIX_LEN
/* Prior to verison 8.20, libpcre did not have pcre_free_study() */
/* Prior to version 8.20, libpcre did not have pcre_free_study() */
#if (PCRE_MAJOR < 8 || (PCRE_MAJOR == 8 && PCRE_MINOR < 20))
#define pcre_free_study pcre_free
#endif
@ -47,8 +49,10 @@ struct stem {
/* Where we map the file in during selabel_open() */
struct mmap_area {
void *addr; /* Start of area - gets incremented by next_entry() */
size_t len; /* Length - gets decremented by next_entry() */
void *addr; /* Start addr + len used to release memory at close */
size_t len;
void *next_addr; /* Incremented by next_entry() */
size_t next_len; /* Decremented by next_entry() */
struct mmap_area *next;
};
@ -147,6 +151,7 @@ static inline void spec_hasMetaChars(struct spec *spec)
end = c + len;
spec->hasMetaChars = 0;
spec->prefix_len = len;
/* Look at each character in the RE specification string for a
* meta character. Return when any meta character reached. */
@ -163,6 +168,7 @@ static inline void spec_hasMetaChars(struct spec *spec)
case '(':
case '{':
spec->hasMetaChars = 1;
spec->prefix_len = c - spec->regex_str;
return;
case '\\': /* skip the next character */
c++;
@ -173,7 +179,6 @@ static inline void spec_hasMetaChars(struct spec *spec)
}
c++;
}
return;
}
/* Move exact pathname specifications to the end. */
@ -200,9 +205,9 @@ static inline int sort_specs(struct saved_data *data)
}
/*
* now the exact pathnames are at the end, but they are in the reverse order.
* since 'front' is now the first of the 'exact' we can run that part of the
* array switching the front and back element.
* now the exact pathnames are at the end, but they are in the reverse
* order. Since 'front' is now the first of the 'exact' we can run
* that part of the array switching the front and back element.
*/
back = data->nspec - 1;
while (front < back) {
@ -242,7 +247,8 @@ static inline int get_stem_from_spec(const char *const buf)
/*
* return the stemid given a string and a length
*/
static inline int find_stem(struct saved_data *data, const char *buf, int stem_len)
static inline int find_stem(struct saved_data *data, const char *buf,
int stem_len)
{
int i;
@ -272,6 +278,7 @@ static inline int store_stem(struct saved_data *data, char *buf, int stem_len)
}
data->stem_arr[num].len = stem_len;
data->stem_arr[num].buf = buf;
data->stem_arr[num].from_mmap = 0;
data->num_stems++;
return num;
@ -306,14 +313,161 @@ static inline int find_stem_from_spec(struct saved_data *data, const char *buf)
* current buffer). */
static inline int next_entry(void *buf, struct mmap_area *fp, size_t bytes)
{
if (bytes > fp->len)
if (bytes > fp->next_len)
return -1;
if (buf)
memcpy(buf, fp->addr, bytes);
memcpy(buf, fp->next_addr, bytes);
fp->next_addr = (char *)fp->next_addr + bytes;
fp->next_len -= bytes;
return 0;
}
static inline int compile_regex(struct saved_data *data, struct spec *spec,
const char **errbuf)
{
const char *tmperrbuf;
char *reg_buf, *anchored_regex, *cp;
struct stem *stem_arr = data->stem_arr;
size_t len;
int erroff;
if (spec->regcomp)
return 0; /* already done */
/* Skip the fixed stem. */
reg_buf = spec->regex_str;
if (spec->stem_id >= 0)
reg_buf += stem_arr[spec->stem_id].len;
/* Anchor the regular expression. */
len = strlen(reg_buf);
cp = anchored_regex = malloc(len + 3);
if (!anchored_regex)
return -1;
/* Create ^...$ regexp. */
*cp++ = '^';
memcpy(cp, reg_buf, len);
cp += len;
*cp++ = '$';
*cp = '\0';
/* Compile the regular expression. */
spec->regex = pcre_compile(anchored_regex, PCRE_DOTALL, &tmperrbuf,
&erroff, NULL);
free(anchored_regex);
if (!spec->regex) {
if (errbuf)
*errbuf = tmperrbuf;
return -1;
}
spec->sd = pcre_study(spec->regex, 0, &tmperrbuf);
if (!spec->sd && tmperrbuf) {
if (errbuf)
*errbuf = tmperrbuf;
return -1;
}
/* Done. */
spec->regcomp = 1;
return 0;
}
/* This service is used by label_file.c process_file() and
* utils/sefcontext_compile.c */
static inline int process_line(struct selabel_handle *rec,
const char *path, const char *prefix,
char *line_buf, unsigned lineno)
{
int items, len, rc;
char *regex = NULL, *type = NULL, *context = NULL;
struct saved_data *data = (struct saved_data *)rec->data;
struct spec *spec_arr;
unsigned int nspec = data->nspec;
const char *errbuf = NULL;
items = read_spec_entries(line_buf, 3, &regex, &type, &context);
if (items <= 0)
return items;
if (items < 2) {
COMPAT_LOG(SELINUX_ERROR,
"%s: line %u is missing fields\n", path,
lineno);
if (items == 1)
free(regex);
errno = EINVAL;
return -1;
} else if (items == 2) {
/* The type field is optional. */
context = type;
type = 0;
}
len = get_stem_from_spec(regex);
if (len && prefix && strncmp(prefix, regex, len)) {
/* Stem of regex does not match requested prefix, discard. */
free(regex);
free(type);
free(context);
return 0;
}
rc = grow_specs(data);
if (rc)
return rc;
spec_arr = data->spec_arr;
/* process and store the specification in spec. */
spec_arr[nspec].stem_id = find_stem_from_spec(data, regex);
spec_arr[nspec].regex_str = regex;
spec_arr[nspec].type_str = type;
spec_arr[nspec].mode = 0;
spec_arr[nspec].lr.ctx_raw = context;
/*
* bump data->nspecs to cause closef() to cover it in its free
* but do not bump nspec since it's used below.
*/
data->nspec++;
if (rec->validating &&
compile_regex(data, &spec_arr[nspec], &errbuf)) {
COMPAT_LOG(SELINUX_ERROR,
"%s: line %u has invalid regex %s: %s\n",
path, lineno, regex,
(errbuf ? errbuf : "out of memory"));
errno = EINVAL;
return -1;
}
if (type) {
mode_t mode = string_to_mode(type);
if (mode == (mode_t)-1) {
COMPAT_LOG(SELINUX_ERROR,
"%s: line %u has invalid file type %s\n",
path, lineno, type);
errno = EINVAL;
return -1;
}
spec_arr[nspec].mode = mode;
}
/* Determine if specification has
* any meta characters in the RE */
spec_hasMetaChars(&spec_arr[nspec]);
if (strcmp(context, "<<none>>") && rec->validating)
compat_validate(rec, &spec_arr[nspec].lr, path, lineno);
fp->addr = (char *)fp->addr + bytes;
fp->len -= bytes;
return 0;
}

View File

@ -10,23 +10,30 @@
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <selinux/selinux.h>
#include <selinux/label.h>
#include "dso.h"
#include "sha1.h"
/*
* Installed backends
*/
int selabel_file_init(struct selabel_handle *rec, struct selinux_opt *opts,
unsigned nopts) hidden;
int selabel_media_init(struct selabel_handle *rec, struct selinux_opt *opts,
unsigned nopts) hidden;
int selabel_x_init(struct selabel_handle *rec, struct selinux_opt *opts,
unsigned nopts) hidden;
int selabel_file_init(struct selabel_handle *rec,
const struct selinux_opt *opts,
unsigned nopts) hidden;
int selabel_media_init(struct selabel_handle *rec,
const struct selinux_opt *opts,
unsigned nopts) hidden;
int selabel_x_init(struct selabel_handle *rec,
const struct selinux_opt *opts,
unsigned nopts) hidden;
int selabel_db_init(struct selabel_handle *rec,
struct selinux_opt *opts, unsigned nopts) hidden;
const struct selinux_opt *opts,
unsigned nopts) hidden;
int selabel_property_init(struct selabel_handle *rec,
struct selinux_opt *opts, unsigned nopts) hidden;
const struct selinux_opt *opts,
unsigned nopts) hidden;
/*
* Labeling internal structures
@ -38,8 +45,31 @@ struct selabel_sub {
struct selabel_sub *next;
};
/*
* Calculate an SHA1 hash of all the files used to build the specs.
* The hash value is held in rec->digest if SELABEL_OPT_DIGEST set. To
* calculate the hash the hashbuf will hold a concatenation of all the files
* used. This is released once the value has been calculated.
*/
#define DIGEST_SPECFILE_SIZE SHA1_HASH_SIZE
#define DIGEST_FILES_MAX 8
struct selabel_digest {
unsigned char *digest; /* SHA1 digest of specfiles */
unsigned char *hashbuf; /* buffer to hold specfiles */
size_t hashbuf_size; /* buffer size */
size_t specfile_cnt; /* how many specfiles processed */
char **specfile_list; /* and their names */
};
extern int digest_add_specfile(struct selabel_digest *digest, FILE *fp,
char *from_addr,
size_t buf_len,
const char *path);
extern void digest_gen_hash(struct selabel_digest *digest);
extern struct selabel_sub *selabel_subs_init(const char *path,
struct selabel_sub *list);
struct selabel_sub *list,
struct selabel_digest *digest);
struct selabel_lookup_rec {
char * ctx_raw;
@ -63,6 +93,8 @@ struct selabel_handle {
const char *key,
const char **aliases,
int type);
enum selabel_cmp_result (*func_cmp)(struct selabel_handle *h1,
struct selabel_handle *h2);
/* supports backend-specific state information */
void *data;
@ -76,6 +108,8 @@ struct selabel_handle {
/* substitution support */
struct selabel_sub *dist_subs;
struct selabel_sub *subs;
/* ptr to SHA1 hash information if SELABEL_OPT_DIGEST set */
struct selabel_digest *digest;
};
/*
@ -90,7 +124,7 @@ selabel_validate(struct selabel_handle *rec,
*/
extern int myprintf_compat;
extern void __attribute__ ((format(printf, 1, 2)))
(*myprintf) (const char *fmt,...);
(*myprintf) (const char *fmt, ...);
#define COMPAT_LOG(type, fmt...) if (myprintf_compat) \
myprintf(fmt); \

View File

@ -67,7 +67,7 @@ static int process_line(const char *path, char *line_buf, int pass,
return 0;
}
static int init(struct selabel_handle *rec, struct selinux_opt *opts,
static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
unsigned n)
{
FILE *fp;
@ -136,7 +136,12 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
}
free(line_buf);
status = 0;
status = digest_add_specfile(rec->digest, fp, NULL, sb.st_size, path);
if (status)
goto finish;
digest_gen_hash(rec->digest);
finish:
fclose(fp);
return status;
@ -161,7 +166,7 @@ static void close(struct selabel_handle *rec)
if (spec_arr)
free(spec_arr);
memset(data, 0, sizeof(*data));
free(data);
}
static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
@ -201,8 +206,9 @@ static void stats(struct selabel_handle *rec)
data->nspec, total);
}
int selabel_media_init(struct selabel_handle *rec, struct selinux_opt *opts,
unsigned nopts)
int selabel_media_init(struct selabel_handle *rec,
const struct selinux_opt *opts,
unsigned nopts)
{
struct saved_data *data;

View File

@ -8,6 +8,8 @@
#include <stdarg.h>
#include <ctype.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include "label_internal.h"
/*
@ -15,11 +17,8 @@
* replace sscanf to read entries from spec files. The file and
* property services now use these.
*/
/* Read an entry from a spec file (e.g. file_contexts) */
static inline int read_spec_entry(char **entry, char **ptr)
static inline int read_spec_entry(char **entry, char **ptr, int *len)
{
int entry_len = 0;
*entry = NULL;
char *tmp_buf = NULL;
@ -27,15 +26,18 @@ static inline int read_spec_entry(char **entry, char **ptr)
(*ptr)++;
tmp_buf = *ptr;
*len = 0;
while (!isspace(**ptr) && **ptr != '\0') {
(*ptr)++;
entry_len++;
(*len)++;
}
*entry = strndup(tmp_buf, entry_len);
if (!*entry)
return -1;
if (*len) {
*entry = strndup(tmp_buf, *len);
if (!*entry)
return -1;
}
return 0;
}
@ -48,15 +50,20 @@ static inline int read_spec_entry(char **entry, char **ptr)
*
* This function calls read_spec_entry() to do the actual string processing.
*/
int read_spec_entries(char *line_buf, int num_args, ...)
int hidden read_spec_entries(char *line_buf, int num_args, ...)
{
char **spec_entry, *buf_p;
int len, rc, items;
int len, rc, items, entry_len = 0;
va_list ap;
len = strlen(line_buf);
if (line_buf[len - 1] == '\n')
line_buf[len - 1] = '\0';
else
/* Handle case if line not \n terminated by bumping
* the len for the check below (as the line is NUL
* terminated by getline(3)) */
len++;
buf_p = line_buf;
while (isspace(*buf_p))
@ -69,7 +76,8 @@ int read_spec_entries(char *line_buf, int num_args, ...)
/* Process the spec file entries */
va_start(ap, num_args);
for (items = 0; items < num_args; items++) {
items = 0;
while (items < num_args) {
spec_entry = va_arg(ap, char **);
if (len - 1 == buf_p - line_buf) {
@ -77,12 +85,93 @@ int read_spec_entries(char *line_buf, int num_args, ...)
return items;
}
rc = read_spec_entry(spec_entry, &buf_p);
rc = read_spec_entry(spec_entry, &buf_p, &entry_len);
if (rc < 0) {
va_end(ap);
return rc;
}
if (entry_len)
items++;
}
va_end(ap);
return items;
}
/* Once all the specfiles are in the hash_buf, generate the hash. */
void hidden digest_gen_hash(struct selabel_digest *digest)
{
Sha1Context context;
/* If SELABEL_OPT_DIGEST not set then just return */
if (!digest)
return;
Sha1Initialise(&context);
Sha1Update(&context, digest->hashbuf, digest->hashbuf_size);
Sha1Finalise(&context, (SHA1_HASH *)digest->digest);
free(digest->hashbuf);
digest->hashbuf = NULL;
return;
}
/**
* digest_add_specfile - Add a specfile to the hashbuf and if gen_hash true
* then generate the hash.
* @digest: pointer to the selabel_digest struct
* @fp: file pointer for fread(3) or NULL if not.
* @from_addr: pointer at start of buffer for memcpy or NULL if not (used for
* mmap(3) files).
* @buf_len: length of buffer to copy.
* @path: pointer to the specfile.
*
* Return %0 on success, -%1 with @errno set on failure.
*/
int hidden digest_add_specfile(struct selabel_digest *digest, FILE *fp,
char *from_addr, size_t buf_len,
const char *path)
{
unsigned char *tmp_buf;
/* If SELABEL_OPT_DIGEST not set then just return */
if (!digest)
return 0;
if (digest->hashbuf_size + buf_len < digest->hashbuf_size) {
errno = EOVERFLOW;
return -1;
}
digest->hashbuf_size += buf_len;
tmp_buf = realloc(digest->hashbuf, digest->hashbuf_size);
if (!tmp_buf)
return -1;
digest->hashbuf = tmp_buf;
if (fp) {
rewind(fp);
if (fread(digest->hashbuf + (digest->hashbuf_size - buf_len),
1, buf_len, fp) != buf_len)
return -1;
rewind(fp);
} else if (from_addr) {
tmp_buf = memcpy(digest->hashbuf +
(digest->hashbuf_size - buf_len),
from_addr, buf_len);
if (!tmp_buf)
return -1;
}
/* Now add path to list */
digest->specfile_list[digest->specfile_cnt] = strdup(path);
if (!digest->specfile_list[digest->specfile_cnt])
return -1;
digest->specfile_cnt++;
if (digest->specfile_cnt > DIGEST_FILES_MAX) {
errno = EOVERFLOW;
return -1;
}
return 0;
}

View File

@ -94,7 +94,7 @@ static int process_line(const char *path, char *line_buf, int pass,
return 0;
}
static int init(struct selabel_handle *rec, struct selinux_opt *opts,
static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
unsigned n)
{
FILE *fp;
@ -163,7 +163,12 @@ static int init(struct selabel_handle *rec, struct selinux_opt *opts,
}
free(line_buf);
status = 0;
status = digest_add_specfile(rec->digest, fp, NULL, sb.st_size, path);
if (status)
goto finish;
digest_gen_hash(rec->digest);
finish:
fclose(fp);
return status;
@ -188,7 +193,7 @@ static void close(struct selabel_handle *rec)
if (spec_arr)
free(spec_arr);
memset(data, 0, sizeof(*data));
free(data);
}
static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
@ -227,7 +232,7 @@ static void stats(struct selabel_handle *rec)
data->nspec, total);
}
int selabel_x_init(struct selabel_handle *rec, struct selinux_opt *opts,
int selabel_x_init(struct selabel_handle *rec, const struct selinux_opt *opts,
unsigned nopts)
{
struct saved_data *data;

View File

@ -11,8 +11,6 @@
#define UNSET (char *) -1
static __thread pid_t cpid;
static __thread pid_t tid;
static __thread char *prev_current = UNSET;
static __thread char * prev_exec = UNSET;
static __thread char * prev_fscreate = UNSET;
@ -24,15 +22,6 @@ static pthread_key_t destructor_key;
static int destructor_key_initialized = 0;
static __thread char destructor_initialized;
extern void *__dso_handle __attribute__ ((__weak__, __visibility__ ("hidden")));
extern int __register_atfork (void (*) (void), void (*) (void), void (*) (void), void *);
static int __selinux_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void))
{
return __register_atfork (prepare, parent, child,
&__dso_handle == NULL ? NULL : __dso_handle);
}
static pid_t gettid(void)
{
return syscall(__NR_gettid);
@ -52,14 +41,6 @@ static void procattr_thread_destructor(void __attribute__((unused)) *unused)
free(prev_sockcreate);
}
static void free_procattr(void)
{
procattr_thread_destructor(NULL);
tid = 0;
cpid = getpid();
prev_current = prev_exec = prev_fscreate = prev_keycreate = prev_sockcreate = UNSET;
}
void __attribute__((destructor)) procattr_destructor(void);
void hidden __attribute__((destructor)) procattr_destructor(void)
@ -79,7 +60,6 @@ static inline void init_thread_destructor(void)
static void init_procattr(void)
{
if (__selinux_key_create(&destructor_key, procattr_thread_destructor) == 0) {
__selinux_atfork(NULL, NULL, free_procattr);
destructor_key_initialized = 1;
}
}
@ -88,21 +68,26 @@ static int openattr(pid_t pid, const char *attr, int flags)
{
int fd, rc;
char *path;
if (cpid != getpid())
free_procattr();
pid_t tid;
if (pid > 0)
rc = asprintf(&path, "/proc/%d/attr/%s", pid, attr);
else {
if (!tid)
tid = gettid();
rc = asprintf(&path, "/proc/thread-self/attr/%s", attr);
if (rc < 0)
return -1;
fd = open(path, flags | O_CLOEXEC);
if (fd >= 0 || errno != ENOENT)
goto out;
free(path);
tid = gettid();
rc = asprintf(&path, "/proc/self/task/%d/attr/%s", tid, attr);
}
if (rc < 0)
return -1;
fd = open(path, flags | O_CLOEXEC);
out:
free(path);
return fd;
}
@ -120,9 +105,6 @@ static int getprocattrcon_raw(char ** context,
__selinux_once(once, init_procattr);
init_thread_destructor();
if (cpid != getpid())
free_procattr();
switch (attr[0]) {
case 'c':
prev_context = prev_current;
@ -220,9 +202,6 @@ static int setprocattrcon_raw(const char * context,
__selinux_once(once, init_procattr);
init_thread_destructor();
if (cpid != getpid())
free_procattr();
switch (attr[0]) {
case 'c':
prev_context = &prev_current;

View File

@ -102,6 +102,8 @@ hidden_proto(security_get_initial_context);
hidden_proto(security_get_initial_context_raw);
hidden_proto(selinux_reset_config);
hidden void flush_class_cache(void);
extern int load_setlocaldefs hidden;
extern int require_seusers hidden;
extern int selinux_page_size hidden;

View File

@ -8,7 +8,7 @@
%pythoncode %{
import shutil, os, stat
import shutil, os, errno, stat
DISABLED = -1
PERMISSIVE = 0
@ -26,7 +26,12 @@ def restorecon(path, recursive=False):
status, context = matchpathcon(path, mode)
if status == 0:
status, oldcontext = lgetfilecon(path)
try:
status, oldcontext = lgetfilecon(path)
except OSError as e:
if e.errno != errno.ENODATA:
raise
oldcontext = None
if context != oldcontext:
lsetfilecon(path, context)

214
libselinux/src/sha1.c Normal file
View File

@ -0,0 +1,214 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// LibSha1
//
// Implementation of SHA1 hash function.
// Original author: Steve Reid <sreid@sea-to-sky.net>
// Contributions by: James H. Brown <jbrown@burgoyne.com>, Saul Kravitz <Saul.Kravitz@celera.com>,
// and Ralph Giles <giles@ghostscript.com>
// Modified by WaterJuice retaining Public Domain license.
//
// This is free and unencumbered software released into the public domain - June 2013 waterjuice.org
// Modified to stop symbols being exported for libselinux shared library - October 2015
// Richard Haines <richard_c_haines@btinternet.com>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IMPORTS
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include "sha1.h"
#include "dso.h"
#include <memory.h>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// TYPES
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef union
{
uint8_t c [64];
uint32_t l [16];
} CHAR64LONG16;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// INTERNAL FUNCTIONS
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
// blk0() and blk() perform the initial expand.
#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
|(rol(block->l[i],8)&0x00FF00FF))
#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
^block->l[(i+2)&15]^block->l[i&15],1))
// (R0+R1), R2, R3, R4 are the different operations used in SHA1
#define R0(v,w,x,y,z,i) z += ((w&(x^y))^y) + blk0(i)+ 0x5A827999 + rol(v,5); w=rol(w,30);
#define R1(v,w,x,y,z,i) z += ((w&(x^y))^y) + blk(i) + 0x5A827999 + rol(v,5); w=rol(w,30);
#define R2(v,w,x,y,z,i) z += (w^x^y) + blk(i) + 0x6ED9EBA1 + rol(v,5); w=rol(w,30);
#define R3(v,w,x,y,z,i) z += (((w|x)&y)|(w&x)) + blk(i) + 0x8F1BBCDC + rol(v,5); w=rol(w,30);
#define R4(v,w,x,y,z,i) z += (w^x^y) + blk(i) + 0xCA62C1D6 + rol(v,5); w=rol(w,30);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// TransformFunction
//
// Hash a single 512-bit block. This is the core of the algorithm
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static
void
TransformFunction
(
uint32_t state[5],
const uint8_t buffer[64]
)
{
uint32_t a;
uint32_t b;
uint32_t c;
uint32_t d;
uint32_t e;
uint8_t workspace[64];
CHAR64LONG16* block = (CHAR64LONG16*) workspace;
memcpy( block, buffer, 64 );
// Copy context->state[] to working vars
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
// 4 rounds of 20 operations each. Loop unrolled.
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
// Add the working vars back into context.state[]
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PUBLIC FUNCTIONS
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Sha1Initialise
//
// Initialises an SHA1 Context. Use this to initialise/reset a context.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void hidden
Sha1Initialise
(
Sha1Context* Context
)
{
// SHA1 initialization constants
Context->State[0] = 0x67452301;
Context->State[1] = 0xEFCDAB89;
Context->State[2] = 0x98BADCFE;
Context->State[3] = 0x10325476;
Context->State[4] = 0xC3D2E1F0;
Context->Count[0] = 0;
Context->Count[1] = 0;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Sha1Update
//
// Adds data to the SHA1 context. This will process the data and update the internal state of the context. Keep on
// calling this function until all the data has been added. Then call Sha1Finalise to calculate the hash.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void hidden
Sha1Update
(
Sha1Context* Context,
void* Buffer,
uint32_t BufferSize
)
{
uint32_t i;
uint32_t j;
j = (Context->Count[0] >> 3) & 63;
if( (Context->Count[0] += BufferSize << 3) < (BufferSize << 3) )
{
Context->Count[1]++;
}
Context->Count[1] += (BufferSize >> 29);
if( (j + BufferSize) > 63 )
{
i = 64 - j;
memcpy( &Context->Buffer[j], Buffer, i );
TransformFunction(Context->State, Context->Buffer);
for( ; i + 63 < BufferSize; i += 64 )
{
TransformFunction(Context->State, (uint8_t*)Buffer + i);
}
j = 0;
}
else
{
i = 0;
}
memcpy( &Context->Buffer[j], &((uint8_t*)Buffer)[i], BufferSize - i );
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Sha1Finalise
//
// Performs the final calculation of the hash and returns the digest (20 byte buffer containing 160bit hash). After
// calling this, Sha1Initialised must be used to reuse the context.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void hidden
Sha1Finalise
(
Sha1Context* Context,
SHA1_HASH* Digest
)
{
uint32_t i;
uint8_t finalcount[8];
for( i=0; i<8; i++ )
{
finalcount[i] = (unsigned char)((Context->Count[(i >= 4 ? 0 : 1)]
>> ((3-(i & 3)) * 8) ) & 255); // Endian independent
}
Sha1Update( Context, (uint8_t*)"\x80", 1 );
while( (Context->Count[0] & 504) != 448 )
{
Sha1Update( Context, (uint8_t*)"\0", 1 );
}
Sha1Update( Context, finalcount, 8 ); // Should cause a Sha1TransformFunction()
for( i=0; i<SHA1_HASH_SIZE; i++ )
{
Digest->bytes[i] = (uint8_t)((Context->State[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
}
}

85
libselinux/src/sha1.h Normal file
View File

@ -0,0 +1,85 @@
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// LibSha1
//
// Implementation of SHA1 hash function.
// Original author: Steve Reid <sreid@sea-to-sky.net>
// Contributions by: James H. Brown <jbrown@burgoyne.com>, Saul Kravitz <Saul.Kravitz@celera.com>,
// and Ralph Giles <giles@ghostscript.com>
// Modified by WaterJuice retaining Public Domain license.
//
// This is free and unencumbered software released into the public domain - June 2013 waterjuice.org
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef _sha1_h_
#define _sha1_h_
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// IMPORTS
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#include <stdint.h>
#include <stdio.h>
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// TYPES
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Sha1Context - This must be initialised using Sha1Initialised. Do not modify the contents of this structure directly.
typedef struct
{
uint32_t State[5];
uint32_t Count[2];
uint8_t Buffer[64];
} Sha1Context;
#define SHA1_HASH_SIZE ( 160 / 8 )
typedef struct
{
uint8_t bytes [SHA1_HASH_SIZE];
} SHA1_HASH;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PUBLIC FUNCTIONS
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Sha1Initialise
//
// Initialises an SHA1 Context. Use this to initialise/reset a context.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
Sha1Initialise
(
Sha1Context* Context
);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Sha1Update
//
// Adds data to the SHA1 context. This will process the data and update the internal state of the context. Keep on
// calling this function until all the data has been added. Then call Sha1Finalise to calculate the hash.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
Sha1Update
(
Sha1Context* Context,
void* Buffer,
uint32_t BufferSize
);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Sha1Finalise
//
// Performs the final calculation of the hash and returns the digest (20 byte buffer containing 160bit hash). After
// calling this, Sha1Initialised must be used to reuse the context.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
Sha1Finalise
(
Sha1Context* Context,
SHA1_HASH* Digest
);
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif //_sha1_h_

View File

@ -158,6 +158,28 @@ err1:
return NULL;
}
hidden void flush_class_cache(void)
{
struct discover_class_node *cur = discover_class_cache, *prev = NULL;
size_t i;
while (cur != NULL) {
free(cur->name);
for (i = 0; i < MAXVECTORS; i++)
free(cur->perms[i]);
free(cur->perms);
prev = cur;
cur = cur->next;
free(prev);
}
discover_class_cache = NULL;
}
security_class_t string_to_security_class(const char *s)
{
struct discover_class_node *node;

View File

@ -28,7 +28,7 @@ LDLIBS += -L../src -lselinux -L$(LIBDIR)
TARGETS=$(patsubst %.c,%,$(wildcard *.c))
sefcontext_compile: LDLIBS += -lpcre
sefcontext_compile: LDLIBS += -lpcre ../src/libselinux.a -lsepol
ifeq ($(DISABLE_AVC),y)
UNUSED_TARGETS+=compute_av compute_create compute_member compute_relabel

View File

@ -7,117 +7,62 @@
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/limits.h>
#include <getopt.h>
#include <limits.h>
#include <selinux/selinux.h>
#include <sepol/sepol.h>
#include "../src/label_file.h"
static int process_file(struct saved_data *data, const char *filename)
const char *policy_file;
static int ctx_err;
static int validate_context(char **ctxp)
{
char *ctx = *ctxp;
if (policy_file && sepol_check_context(ctx) < 0) {
ctx_err = -1;
return ctx_err;
}
return 0;
}
static int process_file(struct selabel_handle *rec, const char *filename)
{
struct spec *spec;
unsigned int line_num;
int rc;
char *line_buf = NULL;
size_t line_len;
ssize_t len;
size_t line_len = 0;
FILE *context_file;
const char *prefix = NULL;
context_file = fopen(filename, "r");
if (!context_file) {
fprintf(stderr, "Error opening %s: %s\n", filename, strerror(errno));
fprintf(stderr, "Error opening %s: %s\n",
filename, strerror(errno));
return -1;
}
line_num = 0;
while ((len = getline(&line_buf, &line_len, context_file)) != -1) {
char *context = NULL;
char *mode = NULL;
char *regex = NULL;
char *cp, *anchored_regex;
pcre *re;
pcre_extra *sd;
const char *err;
int items, erroff, rc;
size_t regex_len;
int32_t stem_id;
line_num++;
items = read_spec_entries(line_buf, 3, &regex, &mode, &context);
if (items < 0)
return -1;
if (items == 0)
continue;
else if (items == 1) {
fprintf(stderr,
"line: %u has invalid entry - skipping: %s\n",
line_num, line_buf);
continue;
} else if (items == 2) {
context = mode;
mode = NULL;
rc = 0;
while (getline(&line_buf, &line_len, context_file) > 0) {
rc = process_line(rec, filename, prefix, line_buf, ++line_num);
if (rc || ctx_err) {
/* With -p option need to check and fail if ctx err as
* process_line() context validation on Linux does not
* return an error, but does print the error line to
* stderr. Android will set both to error and print
* the error line. */
rc = -1;
goto out;
}
rc = grow_specs(data);
if (rc) {
fprintf(stderr, "grow_specs failed: %s\n", strerror(errno));
return rc;
}
spec = &data->spec_arr[data->nspec];
spec->lr.ctx_raw = context;
spec->mode = string_to_mode(mode);
if (spec->mode == (mode_t)-1) {
fprintf(stderr, "%s: line %u has invalid file type %s\n",
regex, line_num + 1, mode);
spec->mode = 0;
}
free(mode);
spec->regex_str = regex;
stem_id = find_stem_from_spec(data, regex);
spec->stem_id = stem_id;
/* skip past the fixed stem part */
if (stem_id != -1)
regex += data->stem_arr[stem_id].len;
regex_len = strlen(regex);
cp = anchored_regex = malloc(regex_len + 3);
if (!cp) {
fprintf(stderr, "Malloc Failed: %s\n", strerror(errno));
return -1;
}
*cp++ = '^';
memcpy(cp, regex, regex_len);
cp += regex_len;
*cp++ = '$';
*cp = '\0';
spec_hasMetaChars(spec);
re = pcre_compile(anchored_regex, PCRE_DOTALL, &err, &erroff, NULL);
if (!re) {
fprintf(stderr, "PCRE compilation failed for %s at offset %d: %s\n", anchored_regex, erroff, err);
return -1;
}
spec->regex = re;
sd = pcre_study(re, 0, &err);
if (!sd) {
fprintf(stderr, "PCRE study failed for %s: %s\n", anchored_regex, err);
return -1;
}
free(anchored_regex);
spec->sd = sd;
data->nspec++;
}
out:
free(line_buf);
fclose(context_file);
return 0;
return rc;
}
/*
@ -129,18 +74,19 @@ static int process_file(struct saved_data *data, const char *filename)
* char - pcre version string EXCLUDING nul
* u32 - number of stems
* ** Stems
* u32 - length of stem EXCLUDING nul
* char - stem char array INCLUDING nul
* u32 - length of stem EXCLUDING nul
* char - stem char array INCLUDING nul
* u32 - number of regexs
* ** Regexes
* u32 - length of upcoming context INCLUDING nul
* char - char array of the raw context
* u32 - length of upcoming context INCLUDING nul
* char - char array of the raw context
* u32 - length of the upcoming regex_str
* char - char array of the original regex string including the stem.
* u32 - mode bits for >= SELINUX_COMPILED_FCONTEXT_MODE
* mode_t for <= SELINUX_COMPILED_FCONTEXT_PCRE_VERS
* s32 - stemid associated with the regex
* u32 - spec has meta characters
* u32 - The specs prefix_len if >= SELINUX_COMPILED_FCONTEXT_PREFIX_LEN
* u32 - data length of the pcre regex
* char - a bufer holding the raw pcre regex info
* u32 - data length of the pcre regex study daya
@ -214,6 +160,7 @@ static int write_binary_file(struct saved_data *data, int fd)
char *context = specs[i].lr.ctx_raw;
char *regex_str = specs[i].regex_str;
mode_t mode = specs[i].mode;
size_t prefix_len = specs[i].prefix_len;
int32_t stem_id = specs[i].stem_id;
pcre *re = specs[i].regex;
pcre_extra *sd = get_pcre_extra(&specs[i]);
@ -259,6 +206,12 @@ static int write_binary_file(struct saved_data *data, int fd)
if (len != 1)
goto err;
/* For SELINUX_COMPILED_FCONTEXT_PREFIX_LEN */
to_write = prefix_len;
len = fwrite(&to_write, sizeof(to_write), 1, bin_file);
if (len != 1)
goto err;
/* determine the size of the pcre data in bytes */
rc = pcre_fullinfo(re, NULL, PCRE_INFO_SIZE, &size);
if (rc < 0)
@ -301,7 +254,7 @@ err:
goto out;
}
static int free_specs(struct saved_data *data)
static void free_specs(struct saved_data *data)
{
struct spec *specs = data->spec_arr;
unsigned int num_entries = data->nspec;
@ -311,59 +264,144 @@ static int free_specs(struct saved_data *data)
free(specs[i].lr.ctx_raw);
free(specs[i].lr.ctx_trans);
free(specs[i].regex_str);
free(specs[i].type_str);
pcre_free(specs[i].regex);
pcre_free_study(specs[i].sd);
}
free(specs);
num_entries = data->num_stems;
for (i = 0; i < num_entries; i++) {
for (i = 0; i < num_entries; i++)
free(data->stem_arr[i].buf);
}
free(data->stem_arr);
memset(data, 0, sizeof(*data));
return 0;
}
static void usage(const char *progname)
{
fprintf(stderr,
"usage: %s [-o out_file] [-p policy_file] fc_file\n"
"Where:\n\t"
"-o Optional file name of the PCRE formatted binary\n\t"
" file to be output. If not specified the default\n\t"
" will be fc_file with the .bin suffix appended.\n\t"
"-p Optional binary policy file that will be used to\n\t"
" validate contexts defined in the fc_file.\n\t"
"fc_file The text based file contexts file to be processed.\n",
progname);
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[])
{
struct saved_data data;
const char *path;
const char *path = NULL;
const char *out_file = NULL;
char stack_path[PATH_MAX + 1];
int rc;
char *tmp= NULL;
int fd;
char *tmp = NULL;
int fd, rc, opt;
FILE *policy_fp = NULL;
struct stat buf;
struct selabel_handle *rec = NULL;
struct saved_data *data = NULL;
if (argc != 2) {
fprintf(stderr, "usage: %s input_file\n", argv[0]);
exit(EXIT_FAILURE);
if (argc < 2)
usage(argv[0]);
while ((opt = getopt(argc, argv, "o:p:")) > 0) {
switch (opt) {
case 'o':
out_file = optarg;
break;
case 'p':
policy_file = optarg;
break;
default:
usage(argv[0]);
}
}
memset(&data, 0, sizeof(data));
path = argv[1];
if (optind >= argc)
usage(argv[0]);
path = argv[optind];
if (stat(path, &buf) < 0) {
fprintf(stderr, "Can not stat: %s: %m\n", path);
exit(EXIT_FAILURE);
}
rc = process_file(&data, path);
/* Open binary policy if supplied. */
if (policy_file) {
policy_fp = fopen(policy_file, "r");
if (!policy_fp) {
fprintf(stderr, "Failed to open policy: %s\n",
policy_file);
exit(EXIT_FAILURE);
}
if (sepol_set_policydb_from_file(policy_fp) < 0) {
fprintf(stderr, "Failed to load policy: %s\n",
policy_file);
fclose(policy_fp);
exit(EXIT_FAILURE);
}
}
/* Generate dummy handle for process_line() function */
rec = (struct selabel_handle *)calloc(1, sizeof(*rec));
if (!rec) {
fprintf(stderr, "Failed to calloc handle\n");
if (policy_fp)
fclose(policy_fp);
exit(EXIT_FAILURE);
}
rec->backend = SELABEL_CTX_FILE;
/* Need to set validation on to get the bin file generated by the
* process_line function, however as the bin file being generated
* may not be related to the currently loaded policy (that it
* would be validated against), then set callback to ignore any
* validation - unless the -p option is used in which case if an
* error is detected, the process will be aborted. */
rec->validating = 1;
selinux_set_callback(SELINUX_CB_VALIDATE,
(union selinux_callback)&validate_context);
data = (struct saved_data *)calloc(1, sizeof(*data));
if (!data) {
fprintf(stderr, "Failed to calloc saved_data\n");
free(rec);
if (policy_fp)
fclose(policy_fp);
exit(EXIT_FAILURE);
}
rec->data = data;
rc = process_file(rec, path);
if (rc < 0)
return rc;
goto err;
rc = sort_specs(&data);
rc = sort_specs(data);
if (rc)
return rc;
goto err;
if (out_file)
rc = snprintf(stack_path, sizeof(stack_path), "%s", out_file);
else
rc = snprintf(stack_path, sizeof(stack_path), "%s.bin", path);
rc = snprintf(stack_path, sizeof(stack_path), "%s.bin", path);
if (rc < 0 || rc >= (int)sizeof(stack_path))
return rc;
goto err;
if (asprintf(&tmp, "%sXXXXXX", stack_path) < 0)
return -1;
tmp = malloc(strlen(stack_path) + 7);
if (!tmp)
goto err;
rc = sprintf(tmp, "%sXXXXXX", stack_path);
if (rc < 0)
goto err;
fd = mkstemp(tmp);
if (fd < 0)
@ -372,23 +410,30 @@ int main(int argc, char *argv[])
rc = fchmod(fd, buf.st_mode);
if (rc < 0) {
perror("fchmod failed to set permission on compiled regexs");
goto err;
goto err_unlink;
}
rc = write_binary_file(&data, fd);
rc = write_binary_file(data, fd);
if (rc < 0)
goto err;
goto err_unlink;
rename(tmp, stack_path);
rc = free_specs(&data);
rc = rename(tmp, stack_path);
if (rc < 0)
goto err;
goto err_unlink;
rc = 0;
out:
if (policy_fp)
fclose(policy_fp);
free_specs(data);
free(rec);
free(data);
free(tmp);
return rc;
err_unlink:
unlink(tmp);
err:
rc = -1;
goto out;

View File

@ -0,0 +1,188 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <errno.h>
#include <selinux/selinux.h>
#include <selinux/label.h>
static size_t digest_len;
static void usage(const char *progname)
{
fprintf(stderr,
"usage: %s -b backend [-d] [-v] [-B] [-i] [-f file]\n\n"
"Where:\n\t"
"-b The backend - \"file\", \"media\", \"x\", \"db\" or "
"\"prop\"\n\t"
"-v Run \"cat <specfile_list> | openssl dgst -sha1 -hex\"\n\t"
" on the list of specfiles to compare the SHA1 digests.\n\t"
"-B Use base specfiles only (valid for \"-b file\" only).\n\t"
"-i Do not request a digest.\n\t"
"-f Optional file containing the specs (defaults to\n\t"
" those used by loaded policy).\n\n",
progname);
exit(1);
}
static int run_check_digest(char *cmd, char *selabel_digest)
{
FILE *fp;
char files_digest[128];
char *files_ptr;
int rc = 0;
fp = popen(cmd, "r");
if (!fp) {
printf("Failed to run command line\n");
return -1;
}
/* Only expect one line "(stdin)= x.." so read and find first space */
while (fgets(files_digest, sizeof(files_digest) - 1, fp) != NULL)
;
files_ptr = strstr(files_digest, " ");
rc = strncmp(selabel_digest, files_ptr + 1, digest_len * 2);
if (rc) {
printf("Failed validation:\n\tselabel_digest: %s\n\t"
"files_digest: %s\n",
selabel_digest, files_ptr + 1);
} else {
printf("Passed validation - digest: %s\n", selabel_digest);
}
pclose(fp);
return rc;
}
int main(int argc, char **argv)
{
int backend = 0, rc, opt, i, validate = 0;
char *baseonly = NULL, *file = NULL, *digest = (char *)1;
char **specfiles = NULL;
unsigned char *sha1_digest = NULL;
size_t num_specfiles;
char cmd_buf[4096];
char *cmd_ptr;
char *sha1_buf;
struct selabel_handle *hnd;
struct selinux_opt selabel_option[] = {
{ SELABEL_OPT_PATH, file },
{ SELABEL_OPT_BASEONLY, baseonly },
{ SELABEL_OPT_DIGEST, digest }
};
if (argc < 3)
usage(argv[0]);
while ((opt = getopt(argc, argv, "ib:Bvf:")) > 0) {
switch (opt) {
case 'b':
if (!strcasecmp(optarg, "file")) {
backend = SELABEL_CTX_FILE;
} else if (!strcmp(optarg, "media")) {
backend = SELABEL_CTX_MEDIA;
} else if (!strcmp(optarg, "x")) {
backend = SELABEL_CTX_X;
} else if (!strcmp(optarg, "db")) {
backend = SELABEL_CTX_DB;
} else if (!strcmp(optarg, "prop")) {
backend = SELABEL_CTX_ANDROID_PROP;
} else {
fprintf(stderr, "Unknown backend: %s\n",
optarg);
usage(argv[0]);
}
break;
case 'B':
baseonly = (char *)1;
break;
case 'v':
validate = 1;
break;
case 'i':
digest = NULL;
break;
case 'f':
file = optarg;
break;
default:
usage(argv[0]);
}
}
memset(cmd_buf, 0, sizeof(cmd_buf));
selabel_option[0].value = file;
selabel_option[1].value = baseonly;
selabel_option[2].value = digest;
hnd = selabel_open(backend, selabel_option, 3);
if (!hnd) {
switch (errno) {
case EOVERFLOW:
fprintf(stderr, "ERROR Number of specfiles or specfile"
" buffer caused an overflow.\n");
break;
default:
fprintf(stderr, "ERROR: selabel_open: %s\n",
strerror(errno));
}
return -1;
}
rc = selabel_digest(hnd, &sha1_digest, &digest_len, &specfiles,
&num_specfiles);
if (rc) {
switch (errno) {
case EINVAL:
fprintf(stderr, "No digest available.\n");
break;
default:
fprintf(stderr, "selabel_digest ERROR: %s\n",
strerror(errno));
}
goto err;
}
sha1_buf = malloc(digest_len * 2 + 1);
if (!sha1_buf) {
fprintf(stderr, "Could not malloc buffer ERROR: %s\n",
strerror(errno));
rc = -1;
goto err;
}
printf("SHA1 digest: ");
for (i = 0; i < digest_len; i++)
sprintf(&(sha1_buf[i * 2]), "%02x", sha1_digest[i]);
printf("%s\n", sha1_buf);
printf("calculated using the following specfile(s):\n");
if (specfiles) {
cmd_ptr = &cmd_buf[0];
sprintf(cmd_ptr, "/usr/bin/cat ");
cmd_ptr = &cmd_buf[0] + strlen(cmd_buf);
for (i = 0; i < num_specfiles; i++) {
sprintf(cmd_ptr, "%s ", specfiles[i]);
cmd_ptr += strlen(specfiles[i]) + 1;
printf("%s\n", specfiles[i]);
}
sprintf(cmd_ptr, "| /usr/bin/openssl dgst -sha1 -hex");
if (validate)
rc = run_check_digest(cmd_buf, sha1_buf);
}
free(sha1_buf);
err:
selabel_close(hnd);
return rc;
}

View File

@ -1,3 +1,12 @@
* semanage_migrate_store: Load libsepol.so.1 instead of libsepol.so, from Laurent Bigonville.
* Store homedir_template and users_extra in policy store, from Steve Lawrence
* Fix null pointer dereference in semanage_module_key_destroy, from Yuli Khodorkovskiy.
* Add semanage_module_extract() to extract a module as CIL or HLL, from Yuli Khodorkovskiy.
* semanage_migrate_store: add -r <root> option for migrating inside chroots, from Petr Lautrbach.
* Add file_contexts and seusers to the store, from Yuli Khodorkovskiy.
* Add policy binary and file_contexts.local to the store, from Yuli Khodorkovskiy.
* Allow to install compressed modules without a compression extension,
from Petr Lautrbach.
* Do not copy contexts in semanage_migrate_store, from Jason Zaman.
* Fix logic in bunzip for uncompressed pp files, from Thomas Hurd.
* Fix fname[] initialization in test_utilities.c, from Petr Lautrbach.

View File

@ -24,6 +24,7 @@
#include <stddef.h>
#include <stdint.h>
#include <semanage/handle.h>
#include <sys/types.h>
typedef struct semanage_module_key semanage_module_key_t;
@ -41,6 +42,22 @@ int semanage_module_remove(semanage_handle_t *, char *module_name);
modules, only name at this time */
typedef struct semanage_module_info semanage_module_info_t;
/* Look up a module using @modkey. The module's raw data is returned as a
* @mapped_data blob and size of the mapped_data is returned as @data_len.
* @modinfo contains additional information which can be used by the caller such
* as the high level language extension of @mapped_data.
*
* On success, the caller is responsible for unmapping @mapped_data with munmap(),
* destroying @modinfo with semanage_module_info_destroy(), and freeing @modinfo.
*
* Returns 0 on success and -1 on error.
*/
int semanage_module_extract(semanage_handle_t *sh,
semanage_module_key_t *modkey,
int extract_cil,
void **mapped_data,
size_t *data_len,
semanage_module_info_t **modinfo);
int semanage_module_list(semanage_handle_t *,
semanage_module_info_t **, int *num_modules);
void semanage_module_info_datum_destroy(semanage_module_info_t *);

View File

@ -55,10 +55,8 @@ int bool_policydb_dbase_init(semanage_handle_t * handle,
{
if (dbase_policydb_init(handle,
semanage_final_path(SEMANAGE_FINAL_SELINUX,
SEMANAGE_KERNEL),
semanage_final_path(SEMANAGE_FINAL_TMP,
SEMANAGE_KERNEL),
semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_KERNEL),
semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL),
&SEMANAGE_BOOL_RTABLE,
&SEMANAGE_BOOL_POLICYDB_RTABLE,
&dconfig->dbase) < 0)

View File

@ -66,6 +66,12 @@ static int semanage_direct_commit(semanage_handle_t * sh);
static int semanage_direct_install(semanage_handle_t * sh, char *data,
size_t data_len, const char *module_name, const char *lang_ext);
static int semanage_direct_install_file(semanage_handle_t * sh, const char *module_name);
static int semanage_direct_extract(semanage_handle_t * sh,
semanage_module_key_t *modkey,
int extract_cil,
void **mapped_data,
size_t *data_len,
semanage_module_info_t **modinfo);
static int semanage_direct_remove(semanage_handle_t * sh, char *module_name);
static int semanage_direct_list(semanage_handle_t * sh,
semanage_module_info_t ** modinfo,
@ -100,6 +106,7 @@ static struct semanage_policy_table direct_funcs = {
.begin_trans = semanage_direct_begintrans,
.commit = semanage_direct_commit,
.install = semanage_direct_install,
.extract = semanage_direct_extract,
.install_file = semanage_direct_install_file,
.remove = semanage_direct_remove,
.list = semanage_direct_list,
@ -196,10 +203,8 @@ int semanage_direct_connect(semanage_handle_t * sh)
goto err;
if (fcontext_file_dbase_init(sh,
semanage_final_path(SEMANAGE_FINAL_SELINUX,
SEMANAGE_FC_LOCAL),
semanage_final_path(SEMANAGE_FINAL_TMP,
SEMANAGE_FC_LOCAL),
semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_FC_LOCAL),
semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC_LOCAL),
semanage_fcontext_dbase_local(sh)) < 0)
goto err;
@ -250,18 +255,14 @@ int semanage_direct_connect(semanage_handle_t * sh)
goto err;
if (fcontext_file_dbase_init(sh,
semanage_final_path(SEMANAGE_FINAL_SELINUX,
SEMANAGE_FC),
semanage_final_path(SEMANAGE_FINAL_TMP,
SEMANAGE_FC),
semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_FC),
semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC),
semanage_fcontext_dbase_policy(sh)) < 0)
goto err;
if (seuser_file_dbase_init(sh,
semanage_final_path(SEMANAGE_FINAL_SELINUX,
SEMANAGE_SEUSERS),
semanage_final_path(SEMANAGE_FINAL_TMP,
SEMANAGE_SEUSERS),
semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_SEUSERS),
semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_SEUSERS),
semanage_seuser_dbase_policy(sh)) < 0)
goto err;
@ -502,15 +503,32 @@ exit:
* the file into '*data'.
* Returns the total number of bytes in memory .
* Returns -1 if file could not be opened or mapped. */
static ssize_t map_file(semanage_handle_t *sh, int fd, char **data,
static ssize_t map_file(semanage_handle_t *sh, const char *path, char **data,
int *compressed)
{
ssize_t size = -1;
char *uncompress;
if ((size = bunzip(sh, fdopen(fd, "r"), &uncompress)) > 0) {
int fd = -1;
FILE *file = NULL;
fd = open(path, O_RDONLY);
if (fd == -1) {
ERR(sh, "Unable to open %s\n", path);
return -1;
}
file = fdopen(fd, "r");
if (file == NULL) {
ERR(sh, "Unable to open %s\n", path);
close(fd);
return -1;
}
if ((size = bunzip(sh, file, &uncompress)) > 0) {
*data = mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
if (*data == MAP_FAILED) {
free(uncompress);
fclose(file);
return -1;
} else {
memcpy(*data, uncompress, size);
@ -529,6 +547,8 @@ static ssize_t map_file(semanage_handle_t *sh, int fd, char **data,
*compressed = 0;
}
fclose(file);
return size;
}
@ -604,7 +624,7 @@ static int semanage_direct_update_seuser(semanage_handle_t * sh, cil_db_t *cildb
}
if (size > 0) {
ofilename = semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_SEUSERS);
ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_SEUSERS);
if (ofilename == NULL) {
return -1;
}
@ -892,9 +912,8 @@ cleanup:
return ret;
}
static int semanage_compile_hll(semanage_handle_t *sh,
semanage_module_info_t *modinfos,
int num_modinfos)
static int semanage_compile_module(semanage_handle_t *sh,
semanage_module_info_t *modinfo)
{
char cil_path[PATH_MAX];
char hll_path[PATH_MAX];
@ -907,19 +926,108 @@ static int semanage_compile_hll(semanage_handle_t *sh,
ssize_t hll_data_len = 0;
ssize_t bzip_status;
int status = 0;
int i, compressed;
int in_fd = -1;
int compressed;
size_t cil_data_len;
size_t err_data_len;
if (!strcasecmp(modinfo->lang_ext, "cil")) {
goto cleanup;
}
status = semanage_get_hll_compiler_path(sh, modinfo->lang_ext, &compiler_path);
if (status != 0) {
goto cleanup;
}
status = semanage_module_get_path(
sh,
modinfo,
SEMANAGE_MODULE_PATH_CIL,
cil_path,
sizeof(cil_path));
if (status != 0) {
goto cleanup;
}
status = semanage_module_get_path(
sh,
modinfo,
SEMANAGE_MODULE_PATH_HLL,
hll_path,
sizeof(hll_path));
if (status != 0) {
goto cleanup;
}
if ((hll_data_len = map_file(sh, hll_path, &hll_data, &compressed)) <= 0) {
ERR(sh, "Unable to read file %s\n", hll_path);
status = -1;
goto cleanup;
}
status = semanage_pipe_data(sh, compiler_path, hll_data, (size_t)hll_data_len, &cil_data, &cil_data_len, &err_data, &err_data_len);
if (err_data_len > 0) {
for (start = end = err_data; end < err_data + err_data_len; end++) {
if (*end == '\n') {
fprintf(stderr, "%s: ", modinfo->name);
fwrite(start, 1, end - start + 1, stderr);
start = end + 1;
}
}
if (end != start) {
fprintf(stderr, "%s: ", modinfo->name);
fwrite(start, 1, end - start, stderr);
fprintf(stderr, "\n");
}
}
if (status != 0) {
goto cleanup;
}
bzip_status = bzip(sh, cil_path, cil_data, cil_data_len);
if (bzip_status == -1) {
ERR(sh, "Failed to bzip %s\n", cil_path);
status = -1;
goto cleanup;
}
if (sh->conf->remove_hll == 1) {
status = unlink(hll_path);
if (status != 0) {
ERR(sh, "Error while removing HLL file %s: %s", hll_path, strerror(errno));
goto cleanup;
}
status = semanage_direct_write_langext(sh, "cil", modinfo);
if (status != 0) {
goto cleanup;
}
}
cleanup:
if (hll_data_len > 0) {
munmap(hll_data, hll_data_len);
}
free(cil_data);
free(err_data);
free(compiler_path);
return status;
}
static int semanage_compile_hll_modules(semanage_handle_t *sh,
semanage_module_info_t *modinfos,
int num_modinfos)
{
int status = 0;
int i;
char cil_path[PATH_MAX];
assert(sh);
assert(modinfos);
for (i = 0; i < num_modinfos; i++) {
if (!strcasecmp(modinfos[i].lang_ext, "cil")) {
continue;
}
status = semanage_module_get_path(
sh,
&modinfos[i],
@ -931,101 +1039,19 @@ static int semanage_compile_hll(semanage_handle_t *sh,
}
if (semanage_get_ignore_module_cache(sh) == 0 &&
access(cil_path, F_OK) == 0) {
access(cil_path, F_OK) == 0) {
continue;
}
status = semanage_get_hll_compiler_path(sh, modinfos[i].lang_ext, &compiler_path);
if (status != 0) {
status = semanage_compile_module(sh, &modinfos[i]);
if (status < 0) {
goto cleanup;
}
status = semanage_module_get_path(
sh,
&modinfos[i],
SEMANAGE_MODULE_PATH_HLL,
hll_path,
sizeof(hll_path));
if (status != 0) {
goto cleanup;
}
if ((in_fd = open(hll_path, O_RDONLY)) == -1) {
ERR(sh, "Unable to open %s\n", hll_path);
status = -1;
goto cleanup;
}
if ((hll_data_len = map_file(sh, in_fd, &hll_data, &compressed)) <= 0) {
ERR(sh, "Unable to read file %s\n", hll_path);
status = -1;
goto cleanup;
}
if (in_fd >= 0) close(in_fd);
in_fd = -1;
status = semanage_pipe_data(sh, compiler_path, hll_data, (size_t)hll_data_len, &cil_data, &cil_data_len, &err_data, &err_data_len);
if (err_data_len > 0) {
for (start = end = err_data; end < err_data + err_data_len; end++) {
if (*end == '\n') {
fprintf(stderr, "%s: ", modinfos[i].name);
fwrite(start, 1, end - start + 1, stderr);
start = end + 1;
}
}
if (end != start) {
fprintf(stderr, "%s: ", modinfos[i].name);
fwrite(start, 1, end - start, stderr);
fprintf(stderr, "\n");
}
}
if (status != 0) {
goto cleanup;
}
if (sh->conf->remove_hll == 1) {
status = unlink(hll_path);
if (status != 0) {
ERR(sh, "Error while removing HLL file %s: %s", hll_path, strerror(errno));
goto cleanup;
}
status = semanage_direct_write_langext(sh, "cil", &modinfos[i]);
if (status != 0) {
goto cleanup;
}
}
bzip_status = bzip(sh, cil_path, cil_data, cil_data_len);
if (bzip_status == -1) {
ERR(sh, "Failed to bzip %s\n", cil_path);
status = -1;
goto cleanup;
}
if (hll_data_len > 0) munmap(hll_data, hll_data_len);
hll_data_len = 0;
free(cil_data);
free(err_data);
free(compiler_path);
cil_data = NULL;
err_data = NULL;
compiler_path = NULL;
cil_data_len = 0;
err_data_len = 0;
}
status = 0;
cleanup:
if (hll_data_len > 0) munmap(hll_data, hll_data_len);
if (in_fd >= 0) close(in_fd);
free(cil_data);
free(err_data);
free(compiler_path);
return status;
}
@ -1041,7 +1067,8 @@ static int semanage_direct_commit(semanage_handle_t * sh)
size_t fc_buffer_len = 0;
const char *ofilename = NULL;
const char *path;
int retval = -1, num_modinfos = 0, i;
int retval = -1, num_modinfos = 0, i, missing_policy_kern = 0,
missing_seusers = 0, missing_fc = 0, missing = 0;
sepol_policydb_t *out = NULL;
struct cil_db *cildb = NULL;
semanage_module_info_t *modinfos = NULL;
@ -1143,8 +1170,36 @@ static int semanage_direct_commit(semanage_handle_t * sh)
modified |= dontaudit_modified;
modified |= preserve_tunables_modified;
/* This is for systems that have already migrated with an older version
* of semanage_migrate_store. The older version did not copy policy.kern so
* the policy binary must be rebuilt here.
*/
if (!sh->do_rebuild && !modified) {
path = semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL);
if (access(path, F_OK) != 0) {
missing_policy_kern = 1;
}
path = semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC);
if (access(path, F_OK) != 0) {
missing_fc = 1;
}
path = semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_SEUSERS);
if (access(path, F_OK) != 0) {
missing_seusers = 1;
}
}
missing |= missing_policy_kern;
missing |= missing_fc;
missing |= missing_seusers;
/* If there were policy changes, or explicitly requested, rebuild the policy */
if (sh->do_rebuild || modified) {
if (sh->do_rebuild || modified || missing) {
/* =================== Module expansion =============== */
retval = semanage_get_active_modules(sh, &modinfos, &num_modinfos);
@ -1156,7 +1211,7 @@ static int semanage_direct_commit(semanage_handle_t * sh)
goto cleanup;
}
retval = semanage_compile_hll(sh, modinfos, num_modinfos);
retval = semanage_compile_hll_modules(sh, modinfos, num_modinfos);
if (retval < 0) {
ERR(sh, "Failed to compile hll files into cil files.\n");
goto cleanup;
@ -1217,6 +1272,9 @@ static int semanage_direct_commit(semanage_handle_t * sh)
if (retval < 0)
goto cleanup;
/* remove FC_TMPL now that it is now longer needed */
unlink(semanage_path(SEMANAGE_TMP, SEMANAGE_FC_TMPL));
pfcontexts->dtable->drop_cache(pfcontexts->dbase);
/* SEUsers */
@ -1302,6 +1360,43 @@ static int semanage_direct_commit(semanage_handle_t * sh)
if (retval < 0)
goto cleanup;
retval = semanage_copy_file(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL),
semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_KERNEL),
sh->conf->file_mode);
if (retval < 0) {
goto cleanup;
}
path = semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC_LOCAL);
if (access(path, F_OK) == 0) {
retval = semanage_copy_file(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC_LOCAL),
semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC_LOCAL),
sh->conf->file_mode);
if (retval < 0) {
goto cleanup;
}
}
path = semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC);
if (access(path, F_OK) == 0) {
retval = semanage_copy_file(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC),
semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC),
sh->conf->file_mode);
if (retval < 0) {
goto cleanup;
}
}
path = semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_SEUSERS);
if (access(path, F_OK) == 0) {
retval = semanage_copy_file(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_SEUSERS),
semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_SEUSERS),
sh->conf->file_mode);
if (retval < 0) {
goto cleanup;
}
}
/* run genhomedircon if its enabled, this should be the last operation
* which requires the out policydb */
if (!sh->conf->disable_genhomedircon) {
@ -1321,11 +1416,6 @@ static int semanage_direct_commit(semanage_handle_t * sh)
sepol_policydb_free(out);
out = NULL;
/* remove files that are automatically generated and no longer needed */
unlink(semanage_path(SEMANAGE_TMP, SEMANAGE_FC_TMPL));
unlink(semanage_path(SEMANAGE_TMP, SEMANAGE_HOMEDIR_TMPL));
unlink(semanage_path(SEMANAGE_TMP, SEMANAGE_USERS_EXTRA));
if (sh->do_rebuild || modified || bools_modified || fcontexts_modified) {
retval = semanage_install_sandbox(sh);
}
@ -1432,19 +1522,12 @@ static int semanage_direct_install_file(semanage_handle_t * sh,
char *data = NULL;
ssize_t data_len = 0;
int compressed = 0;
int in_fd = -1;
char *path = NULL;
char *filename;
char *lang_ext;
char *lang_ext = NULL;
char *separator;
if ((in_fd = open(install_filename, O_RDONLY)) == -1) {
ERR(sh, "Unable to open %s: %s\n", install_filename, strerror(errno));
retval = -1;
goto cleanup;
}
if ((data_len = map_file(sh, in_fd, &data, &compressed)) <= 0) {
if ((data_len = map_file(sh, install_filename, &data, &compressed)) <= 0) {
ERR(sh, "Unable to read file %s\n", install_filename);
retval = -1;
goto cleanup;
@ -1467,30 +1550,114 @@ static int semanage_direct_install_file(semanage_handle_t * sh,
goto cleanup;
}
*separator = '\0';
lang_ext = separator + 1;
}
separator = strrchr(filename, '.');
if (separator == NULL) {
ERR(sh, "Module does not have a valid extension.");
retval = -1;
goto cleanup;
if (lang_ext == NULL) {
ERR(sh, "Module does not have a valid extension.");
retval = -1;
goto cleanup;
}
} else {
*separator = '\0';
lang_ext = separator + 1;
}
*separator = '\0';
lang_ext = separator + 1;
retval = semanage_direct_install(sh, data, data_len, filename, lang_ext);
cleanup:
if (in_fd != -1) {
close(in_fd);
}
if (data_len > 0) munmap(data, data_len);
free(path);
return retval;
}
static int semanage_direct_extract(semanage_handle_t * sh,
semanage_module_key_t *modkey,
int extract_cil,
void **mapped_data,
size_t *data_len,
semanage_module_info_t **modinfo)
{
char module_path[PATH_MAX];
char input_file[PATH_MAX];
enum semanage_module_path_type file_type;
int rc = -1;
semanage_module_info_t *_modinfo = NULL;
ssize_t _data_len;
char *_data;
int compressed;
/* get path of module */
rc = semanage_module_get_path(
sh,
(const semanage_module_info_t *)modkey,
SEMANAGE_MODULE_PATH_NAME,
module_path,
sizeof(module_path));
if (rc != 0) {
goto cleanup;
}
if (access(module_path, F_OK) != 0) {
ERR(sh, "Module does not exist: %s", module_path);
rc = -1;
goto cleanup;
}
rc = semanage_module_get_module_info(sh,
modkey,
&_modinfo);
if (rc != 0) {
goto cleanup;
}
if (extract_cil || strcmp(_modinfo->lang_ext, "cil") == 0) {
file_type = SEMANAGE_MODULE_PATH_CIL;
} else {
file_type = SEMANAGE_MODULE_PATH_HLL;
}
/* get path of what to extract */
rc = semanage_module_get_path(
sh,
_modinfo,
file_type,
input_file,
sizeof(input_file));
if (rc != 0) {
goto cleanup;
}
if (extract_cil == 1 && strcmp(_modinfo->lang_ext, "cil") && access(input_file, F_OK) != 0) {
rc = semanage_compile_module(sh, _modinfo);
if (rc < 0) {
goto cleanup;
}
}
_data_len = map_file(sh, input_file, &_data, &compressed);
if (_data_len <= 0) {
ERR(sh, "Error mapping file: %s", input_file);
rc = -1;
goto cleanup;
}
*modinfo = _modinfo;
*data_len = (size_t)_data_len;
*mapped_data = _data;
cleanup:
if (rc != 0) {
semanage_module_info_destroy(sh, _modinfo);
free(_modinfo);
}
return rc;
}
/* Removes a module from the sandbox. Returns 0 on success, -1 if out
* of memory, -2 if module not found or could not be removed. */
static int semanage_direct_remove(semanage_handle_t * sh, char *module_name)

View File

@ -51,10 +51,8 @@ int iface_policydb_dbase_init(semanage_handle_t * handle,
{
if (dbase_policydb_init(handle,
semanage_final_path(SEMANAGE_FINAL_SELINUX,
SEMANAGE_KERNEL),
semanage_final_path(SEMANAGE_FINAL_TMP,
SEMANAGE_KERNEL),
semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_KERNEL),
semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL),
&SEMANAGE_IFACE_RTABLE,
&SEMANAGE_IFACE_POLICYDB_RTABLE,
&dconfig->dbase) < 0)

View File

@ -30,6 +30,7 @@ LIBSEMANAGE_1.0 {
LIBSEMANAGE_1.1 {
global:
semanage_module_install;
semanage_module_extract;
semanage_get_hll_compiler_path;
semanage_get_ignore_module_cache;
semanage_set_ignore_module_cache;

View File

@ -142,6 +142,23 @@ int semanage_module_install_file(semanage_handle_t * sh,
return sh->funcs->install_file(sh, module_name);
}
int semanage_module_extract(semanage_handle_t * sh,
semanage_module_key_t *modkey,
int extract_cil,
void **mapped_data,
size_t *data_len,
semanage_module_info_t **modinfo) {
if (sh->funcs->extract == NULL) {
ERR(sh,
"No get function defined for this connection type.");
return -1;
} else if (!sh->is_connected) {
ERR(sh, "Not connected.");
return -1;
}
return sh->funcs->extract(sh, modkey, extract_cil, mapped_data, data_len, modinfo);
}
/* Legacy function that remains to preserve ABI
* compatibility. Please use semanage_module_install instead.
*/
@ -673,10 +690,12 @@ int semanage_module_key_destroy(semanage_handle_t *sh,
{
assert(sh);
if (modkey) {
free(modkey->name);
if (!modkey) {
return 0;
}
free(modkey->name);
return semanage_module_key_init(sh, modkey);
}

View File

@ -50,10 +50,8 @@ int node_policydb_dbase_init(semanage_handle_t * handle,
{
if (dbase_policydb_init(handle,
semanage_final_path(SEMANAGE_FINAL_SELINUX,
SEMANAGE_KERNEL),
semanage_final_path(SEMANAGE_FINAL_TMP,
SEMANAGE_KERNEL),
semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_KERNEL),
semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL),
&SEMANAGE_NODE_RTABLE,
&SEMANAGE_NODE_POLICYDB_RTABLE,
&dconfig->dbase) < 0)

View File

@ -52,6 +52,14 @@ struct semanage_policy_table {
/* Install a policy module */
int (*install_file) (struct semanage_handle *, const char *);
/* Extract a policy module */
int (*extract) (struct semanage_handle *,
semanage_module_key_t *,
int extract_cil,
void **,
size_t *,
semanage_module_info_t **);
/* Remove a policy module */
int (*remove) (struct semanage_handle *, char *);

View File

@ -50,10 +50,8 @@ int port_policydb_dbase_init(semanage_handle_t * handle,
{
if (dbase_policydb_init(handle,
semanage_final_path(SEMANAGE_FINAL_SELINUX,
SEMANAGE_KERNEL),
semanage_final_path(SEMANAGE_FINAL_TMP,
SEMANAGE_KERNEL),
semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_KERNEL),
semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL),
&SEMANAGE_PORT_RTABLE,
&SEMANAGE_PORT_POLICYDB_RTABLE,
&dconfig->dbase) < 0)

View File

@ -110,10 +110,14 @@ static const char *semanage_sandbox_paths[SEMANAGE_STORE_NUM_PATHS] = {
"/disable_dontaudit",
"/preserve_tunables",
"/modules/disabled",
"/policy.kern",
"/file_contexts.local",
"/file_contexts",
"/seusers"
};
static char const * const semanage_final_prefix[SEMANAGE_FINAL_NUM] = {
"/tmp",
"/final",
"",
};
@ -664,7 +668,7 @@ static int semanage_filename_select(const struct dirent *d)
/* Copies a file from src to dst. If dst already exists then
* overwrite it. Returns 0 on success, -1 on error. */
static int semanage_copy_file(const char *src, const char *dst, mode_t mode)
int semanage_copy_file(const char *src, const char *dst, mode_t mode)
{
int in, out, retval = 0, amount_read, n, errsv = errno;
char tmp[PATH_MAX];
@ -943,9 +947,7 @@ int semanage_make_final(semanage_handle_t *sh)
goto cleanup;
}
/* Copy in exported databases.
* i = 1 to avoid copying the top level directory.
*/
// Build final directory structure
int i;
for (i = 1; i < SEMANAGE_FINAL_PATH_NUM; i++) {
if (strlen(semanage_final_path(SEMANAGE_FINAL_TMP, i)) >= sizeof(fn)) {
@ -959,12 +961,6 @@ int semanage_make_final(semanage_handle_t *sh)
status = -1;
goto cleanup;
}
semanage_copy_file(
semanage_final_path(SEMANAGE_FINAL_SELINUX, i),
semanage_final_path(SEMANAGE_FINAL_TMP, i),
sh->conf->file_mode);
/* ignore errors, these files may not exist */
}
cleanup:
@ -1431,11 +1427,11 @@ int semanage_split_fc(semanage_handle_t * sh)
goto cleanup;
}
fc = open(semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC),
fc = open(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC),
O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (fc < 0) {
ERR(sh, "Could not open %s for writing.",
semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC));
semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC));
goto cleanup;
}
hd = open(semanage_path(SEMANAGE_TMP, SEMANAGE_HOMEDIR_TMPL),
@ -1460,8 +1456,7 @@ int semanage_split_fc(semanage_handle_t * sh)
} else {
if (write(fc, buf, strlen(buf)) < 0) {
ERR(sh, "Write to %s failed.",
semanage_final_path(SEMANAGE_FINAL_TMP,
SEMANAGE_FC));
semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC));
goto cleanup;
}
}
@ -2019,8 +2014,7 @@ int semanage_read_policydb(semanage_handle_t * sh, sepol_policydb_t * in)
FILE *infile = NULL;
if ((kernel_filename =
semanage_final_path(SEMANAGE_FINAL_SELINUX,
SEMANAGE_KERNEL)) == NULL) {
semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_KERNEL)) == NULL) {
goto cleanup;
}
if ((infile = fopen(kernel_filename, "r")) == NULL) {
@ -2061,7 +2055,7 @@ int semanage_write_policydb(semanage_handle_t * sh, sepol_policydb_t * out)
FILE *outfile = NULL;
if ((kernel_filename =
semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_KERNEL)) == NULL) {
semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL)) == NULL) {
goto cleanup;
}
if ((outfile = fopen(kernel_filename, "wb")) == NULL) {

View File

@ -55,6 +55,10 @@ enum semanage_sandbox_defs {
SEMANAGE_DISABLE_DONTAUDIT,
SEMANAGE_PRESERVE_TUNABLES,
SEMANAGE_MODULES_DISABLED,
SEMANAGE_STORE_KERNEL,
SEMANAGE_STORE_FC_LOCAL,
SEMANAGE_STORE_FC,
SEMANAGE_STORE_SEUSERS,
SEMANAGE_STORE_NUM_PATHS
};
@ -148,4 +152,6 @@ int semanage_nc_sort(semanage_handle_t * sh,
size_t buf_len,
char **sorted_buf, size_t * sorted_buf_len);
int semanage_copy_file(const char *src, const char *dst, mode_t mode);
#endif

View File

@ -23,6 +23,7 @@
%header %{
#include <stdlib.h>
#include <semanage/semanage.h>
#include <sys/mman.h>
#define STATUS_SUCCESS 0
#define STATUS_ERR -1
@ -103,6 +104,10 @@
%apply int *OUTPUT { unsigned int * };
%apply int *OUTPUT { uint16_t * };
%include <cstring.i>
/* This is needed to properly mmaped binary data in SWIG */
%cstring_output_allocate_size(void **mapped_data, size_t *data_len, munmap(*$1, *$2));
%typemap(in, numinputs=0) char **(char *temp=NULL) {
$1 = &temp;
}

View File

@ -50,10 +50,8 @@ int user_base_policydb_dbase_init(semanage_handle_t * handle,
{
if (dbase_policydb_init(handle,
semanage_final_path(SEMANAGE_FINAL_SELINUX,
SEMANAGE_KERNEL),
semanage_final_path(SEMANAGE_FINAL_TMP,
SEMANAGE_KERNEL),
semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_KERNEL),
semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL),
&SEMANAGE_USER_BASE_RTABLE,
&SEMANAGE_USER_BASE_POLICYDB_RTABLE,
&dconfig->dbase) < 0)

View File

@ -10,7 +10,7 @@ from optparse import OptionParser
import ctypes
sepol = ctypes.cdll.LoadLibrary('libsepol.so')
sepol = ctypes.cdll.LoadLibrary('libsepol.so.1')
try:
import selinux
@ -180,7 +180,7 @@ def rebuild_policy():
def oldroot_path():
return "/etc/selinux"
return "%s/etc/selinux" % ROOT
def oldstore_path(store):
return "%s/%s/modules/active" % (oldroot_path(), store)
@ -192,7 +192,7 @@ def disabledmodules_path(store):
return "%s/disabled" % newmodules_path(store)
def newroot_path():
return PATH
return "%s%s" % (ROOT, PATH)
def newstore_path(store):
return "%s/%s/active" % (newroot_path(), store)
@ -219,6 +219,8 @@ if __name__ == "__main__":
help="Disable rebuilding policy after migration (default: no)")
parser.add_option("-P", "--path", dest="path",
help="Set path for the policy store (default: /var/lib/selinux)")
parser.add_option("-r", "--root", dest="root",
help="Set an alternative root for the migration (default: /)")
(options, args) = parser.parse_args()
@ -231,6 +233,10 @@ if __name__ == "__main__":
if PATH is None:
PATH = "/var/lib/selinux"
ROOT = options.root
if ROOT is None:
ROOT = ""
# List of paths that go in the active 'root'
TOPPATHS = [
"commit_num",
@ -241,9 +247,13 @@ if __name__ == "__main__":
"file_contexts.local",
"seusers",
"users.local",
"users_extra",
"users_extra.local",
"disable_dontaudit",
"preserve_tunables" ]
"preserve_tunables",
"policy.kern",
"file_contexts",
"homedir_template"]
create_dir(newroot_path(), 0o755)

View File

@ -46,6 +46,7 @@ cil_src_files := \
cil/src/cil_build_ast.c \
cil/src/cil.c \
cil/src/cil_copy_ast.c \
cil/src/cil_find.c \
cil/src/cil_fqn.c \
cil/src/cil_lexer.l \
cil/src/cil_list.c \

View File

@ -1,8 +1,25 @@
* Add neverallow support for ioctl extended permissions, from Jeff Vander Stoep.
* Improve CIL block and macro call recursion detection, from Steve Lawrence
* Fix CIL uninitialized false positive in cil_binary, from Yuli Khodorkovskiy
* Provide error in CIL if classperms are empty, from Yuli Khodorkovskiy
* Add userattribute{set} functionality to CIL, from Yuli Khodorkovskiy
* fix CIL blockinherit copying segfault and add macro restrictions, from Steve Lawrence
* fix CIL NULL pointer dereference when copying classpermission/set, from Steve Lawrence
* Add CIL support for ioctl whitelists, from Steve Lawrence
* Fix memory leak when destroying avtab, from Steve Lawrence
* Replace sscanf in module_to_cil, from Yuli Khodorkovskiy.
* Improve CIL resolution error messages, from Steve Lawrence
* Fix policydb_read for policy versions < 24, from Stephen Smalley.
* Added CIL bounds checking and refactored CIL Neverallow checking, from James Carter
* Refactored libsepol Neverallow and bounds (hierarchy) checking, from James Carter
* Treat types like an attribute in the attr_type_map, from James Carter
* Add new ebitmap function named ebitmap_match_any(), from James Carter
* switch operations to extended perms, from Jeff Vander Stoep.
* Write auditadm_r and secadm_r roles to base module when writing CIL, from Steve Lawrence
* Fix module to CIL to only associate declared roleattributes with in-scope types, from Steve Lawrence
* Don't allow categories/sensitivities inside blocks in CIL, from Yuli Khodorkovskiy.
* Replace fmemopen() with internal function in libsepol, from James Carter.
* Verify users prior to evaluating users in cil, from Yuli Khodorkovskiy.
* Verify users prior to evaluating users in cil, from Yuli Khodorkovskiy.
* Binary modules do not support ioctl rules, from Stephen Smalley.
* Add support for ioctl command whitelisting, from Jeff Vander Stoep.
* Don't use symbol versioning for static object files, from Yuli Khodorkovskiy.

View File

@ -70,11 +70,11 @@ asm(".symver cil_filecons_to_string_nopdb, cil_filecons_to_string@@LIBSEPOL_1.1"
#endif
int cil_sym_sizes[CIL_SYM_ARRAY_NUM][CIL_SYM_NUM] = {
{64, 64, 64, 1 << 13, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64},
{64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
{64, 64, 64, 1 << 13, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64},
{64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}
};
static void cil_init_keys(void)
@ -122,6 +122,8 @@ static void cil_init_keys(void)
CIL_KEY_TYPE = cil_strpool_add("type");
CIL_KEY_ROLE = cil_strpool_add("role");
CIL_KEY_USER = cil_strpool_add("user");
CIL_KEY_USERATTRIBUTE = cil_strpool_add("userattribute");
CIL_KEY_USERATTRIBUTESET = cil_strpool_add("userattributeset");
CIL_KEY_SENSITIVITY = cil_strpool_add("sensitivity");
CIL_KEY_CATEGORY = cil_strpool_add("category");
CIL_KEY_CATSET = cil_strpool_add("categoryset");
@ -223,6 +225,11 @@ static void cil_init_keys(void)
CIL_KEY_ROOT = cil_strpool_add("<root>");
CIL_KEY_NODE = cil_strpool_add("<node>");
CIL_KEY_PERM = cil_strpool_add("perm");
CIL_KEY_ALLOWX = cil_strpool_add("allowx");
CIL_KEY_AUDITALLOWX = cil_strpool_add("auditallowx");
CIL_KEY_DONTAUDITX = cil_strpool_add("dontauditx");
CIL_KEY_PERMISSIONX = cil_strpool_add("permissionx");
CIL_KEY_IOCTL = cil_strpool_add("ioctl");
}
void cil_db_init(struct cil_db **db)
@ -257,12 +264,15 @@ void cil_db_init(struct cil_db **db)
cil_type_init(&(*db)->selftype);
(*db)->selftype->datum.name = CIL_KEY_SELF;
(*db)->selftype->datum.fqn = CIL_KEY_SELF;
(*db)->num_types_and_attrs = 0;
(*db)->num_classes = 0;
(*db)->num_types = 0;
(*db)->num_roles = 0;
(*db)->num_users = 0;
(*db)->num_cats = 0;
(*db)->val_to_type = NULL;
(*db)->val_to_role = NULL;
(*db)->val_to_user = NULL;
(*db)->disable_dontaudit = CIL_FALSE;
(*db)->disable_neverallow = CIL_FALSE;
@ -305,6 +315,7 @@ void cil_db_destroy(struct cil_db **db)
cil_strpool_destroy();
free((*db)->val_to_type);
free((*db)->val_to_role);
free((*db)->val_to_user);
free(*db);
*db = NULL;
@ -340,7 +351,7 @@ int cil_add_file(cil_db_t *db, char *name, char *data, size_t size)
rc = cil_parser(name, buffer, size + 2, &db->parse);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to parse %s\n", name);
cil_log(CIL_INFO, "Failed to parse %s\n", name);
goto exit;
}
@ -370,7 +381,7 @@ int cil_compile_nopdb(struct cil_db *db)
cil_log(CIL_INFO, "Building AST from Parse Tree\n");
rc = cil_build_ast(db, db->parse->root, db->ast->root);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to build ast\n");
cil_log(CIL_INFO, "Failed to build ast\n");
goto exit;
}
@ -380,21 +391,21 @@ int cil_compile_nopdb(struct cil_db *db)
cil_log(CIL_INFO, "Resolving AST\n");
rc = cil_resolve_ast(db, db->ast->root);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to resolve ast\n");
cil_log(CIL_INFO, "Failed to resolve ast\n");
goto exit;
}
cil_log(CIL_INFO, "Qualifying Names\n");
rc = cil_fqn_qualify(db->ast->root);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to qualify names\n");
cil_log(CIL_INFO, "Failed to qualify names\n");
goto exit;
}
cil_log(CIL_INFO, "Compile post process\n");
rc = cil_post_process(db);
if (rc != SEPOL_OK ) {
cil_log(CIL_ERR, "Post process failed\n");
cil_log(CIL_INFO, "Post process failed\n");
goto exit;
}
@ -546,6 +557,12 @@ void cil_destroy_data(void **data, enum cil_flavor flavor)
case CIL_USER:
cil_destroy_user(*data);
break;
case CIL_USERATTRIBUTE:
cil_destroy_userattribute(*data);
break;
case CIL_USERATTRIBUTESET:
cil_destroy_userattributeset(*data);
break;
case CIL_USERPREFIX:
cil_destroy_userprefix(*data);
break;
@ -652,6 +669,12 @@ void cil_destroy_data(void **data, enum cil_flavor flavor)
case CIL_AVRULE:
cil_destroy_avrule(*data);
break;
case CIL_AVRULEX:
cil_destroy_avrulex(*data);
break;
case CIL_PERMISSIONX:
cil_destroy_permissionx(*data);
break;
case CIL_ROLETRANSITION:
cil_destroy_roletransition(*data);
break;
@ -782,6 +805,7 @@ int cil_flavor_to_symtab_index(enum cil_flavor flavor, enum cil_sym_index *sym_i
*sym_index = CIL_SYM_CLASSPERMSETS;
break;
case CIL_USER:
case CIL_USERATTRIBUTE:
*sym_index = CIL_SYM_USERS;
break;
case CIL_ROLE:
@ -823,6 +847,9 @@ int cil_flavor_to_symtab_index(enum cil_flavor flavor, enum cil_sym_index *sym_i
case CIL_POLICYCAP:
*sym_index = CIL_SYM_POLICYCAPS;
break;
case CIL_PERMISSIONX:
*sym_index = CIL_SYM_PERMX;
break;
default:
*sym_index = CIL_SYM_UNKNOWN;
cil_log(CIL_INFO, "Failed to find flavor: %d\n", flavor);
@ -909,6 +936,10 @@ const char * cil_node_to_string(struct cil_tree_node *node)
return CIL_KEY_CLASSPERMISSIONSET;
case CIL_USER:
return CIL_KEY_USER;
case CIL_USERATTRIBUTE:
return CIL_KEY_USERATTRIBUTE;
case CIL_USERATTRIBUTESET:
return CIL_KEY_USERATTRIBUTESET;
case CIL_USERPREFIX:
return CIL_KEY_USERPREFIX;
case CIL_USERROLE:
@ -993,6 +1024,20 @@ const char * cil_node_to_string(struct cil_tree_node *node)
break;
}
break;
case CIL_AVRULEX:
switch (((struct cil_avrulex *)node->data)->rule_kind) {
case CIL_AVRULE_ALLOWED:
return CIL_KEY_ALLOWX;
case CIL_AVRULE_AUDITALLOW:
return CIL_KEY_AUDITALLOWX;
case CIL_AVRULE_DONTAUDIT:
return CIL_KEY_DONTAUDITX;
default:
break;
}
break;
case CIL_PERMISSIONX:
return CIL_KEY_PERMISSIONX;
case CIL_ROLETRANSITION:
return CIL_KEY_ROLETRANSITION;
case CIL_TYPE_RULE:
@ -2078,6 +2123,31 @@ void cil_avrule_init(struct cil_avrule **avrule)
(*avrule)->classperms = NULL;
}
void cil_permissionx_init(struct cil_permissionx **permx)
{
*permx = cil_malloc(sizeof(**permx));
cil_symtab_datum_init(&(*permx)->datum);
(*permx)->kind = CIL_NONE;
(*permx)->obj_str = NULL;
(*permx)->obj = NULL;
(*permx)->expr_str = NULL;
(*permx)->perms = NULL;
}
void cil_avrulex_init(struct cil_avrulex **avrule)
{
*avrule = cil_malloc(sizeof(**avrule));
(*avrule)->rule_kind = CIL_NONE;
(*avrule)->src_str = NULL;
(*avrule)->src = NULL;
(*avrule)->tgt_str = NULL;
(*avrule)->tgt = NULL;
(*avrule)->permx_str = NULL;
(*avrule)->permx = NULL;
}
void cil_type_rule_init(struct cil_type_rule **type_rule)
{
*type_rule = cil_malloc(sizeof(**type_rule));
@ -2325,6 +2395,26 @@ void cil_user_init(struct cil_user **user)
(*user)->roles = NULL;
(*user)->dftlevel = NULL;
(*user)->range = NULL;
(*user)->value = 0;
}
void cil_userattribute_init(struct cil_userattribute **attr)
{
*attr = cil_malloc(sizeof(**attr));
cil_symtab_datum_init(&(*attr)->datum);
(*attr)->expr_list = NULL;
(*attr)->users = NULL;
}
void cil_userattributeset_init(struct cil_userattributeset **attrset)
{
*attrset = cil_malloc(sizeof(**attrset));
(*attrset)->attr_str = NULL;
(*attrset)->str_expr = NULL;
(*attrset)->datum_expr = NULL;
}
void cil_userlevel_init(struct cil_userlevel **usrlvl)

File diff suppressed because it is too large Load Diff

View File

@ -112,7 +112,7 @@ int cil_roletype_to_policydb(policydb_t *pdb, const struct cil_db *db, struct ci
*
* @return SEPOL_OK upon success or an error otherwise.
*/
int cil_type_to_policydb(policydb_t *pdb, struct cil_type *cil_type);
int cil_type_to_policydb(policydb_t *pdb, struct cil_type *cil_type, void *type_value_to_cil[]);
/**
* Insert cil typealias structure into sepol policydb.
@ -144,7 +144,7 @@ int cil_typepermissive_to_policydb(policydb_t *pdb, struct cil_typepermissive *c
*
* @return SEPOL_OK upon success or an error otherwise.
*/
int cil_typeattribute_to_policydb(policydb_t *pdb, struct cil_typeattribute *cil_attr);
int cil_typeattribute_to_policydb(policydb_t *pdb, struct cil_typeattribute *cil_attr, void *type_value_to_cil[]);
/**
* Insert cil attribute structure into sepol type->attribute bitmap.
@ -184,12 +184,13 @@ int cil_user_to_policydb(policydb_t *pdb, struct cil_user *cil_user);
/**
* Insert cil userrole structure into sepol policydb.
*
* @param[in] pdb THe policy database to insert the userrole into.
* @param[in] datum The cil_userrole datum.
* @param[in] pdb The policy database to insert the userrole into.
* @param[in] db The cil database
* @param[in] datum The cil_user
*
* @return SEPOL_OK upon success or SEPOL_ERR otherwise.
*/
int cil_userrole_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_userrole *userrole);
int cil_userrole_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_user *user);
/**
* Insert cil bool structure into sepol policydb.
@ -250,7 +251,7 @@ int cil_type_rule_to_policydb(policydb_t *pdb, const struct cil_db *db, struct c
*
* @return SEPOL_OK upon success or an error otherwise.
*/
int cil_avrule_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_avrule *cil_avrule, struct cil_list *neverallows);
int cil_avrule_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_avrule *cil_avrule);
/**
* Insert cil booleanif structure into sepol policydb. This populates the
@ -262,7 +263,7 @@ int cil_avrule_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_
*
* @return SEPOL_OK upon success or an error otherwise.
*/
int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_tree_node *node, struct cil_list *neverallows, hashtab_t filename_trans_table);
int cil_booleanif_to_policydb(policydb_t *pdb, const struct cil_db *db, struct cil_tree_node *node, hashtab_t filename_trans_table);
/**
* Insert cil role transition structure into sepol policydb.

View File

@ -1196,10 +1196,132 @@ void cil_destroy_user(struct cil_user *user)
}
cil_symtab_datum_destroy(&user->datum);
cil_list_destroy(&user->roles, CIL_FALSE);
ebitmap_destroy(user->roles);
free(user->roles);
free(user);
}
int cil_gen_userattribute(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
{
enum cil_syntax syntax[] = {
CIL_SYN_STRING,
CIL_SYN_STRING,
CIL_SYN_END
};
int syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_userattribute *attr = NULL;
int rc = SEPOL_ERR;
if (parse_current == NULL || ast_node == NULL) {
goto exit;
}
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
goto exit;
}
cil_userattribute_init(&attr);
key = parse_current->next->data;
rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_USERS, CIL_USERATTRIBUTE);
if (rc != SEPOL_OK) {
goto exit;
}
return SEPOL_OK;
exit:
cil_log(CIL_ERR, "Bad userattribute declaration at line %d of %s\n",
parse_current->line, parse_current->path);
cil_destroy_userattribute(attr);
cil_clear_node(ast_node);
return rc;
}
void cil_destroy_userattribute(struct cil_userattribute *attr)
{
struct cil_list_item *expr = NULL;
struct cil_list_item *next = NULL;
if (attr == NULL) {
return;
}
if (attr->expr_list != NULL) {
/* we don't want to destroy the expression stacks (cil_list) inside
* this list cil_list_destroy destroys sublists, so we need to do it
* manually */
expr = attr->expr_list->head;
while (expr != NULL) {
next = expr->next;
cil_list_item_destroy(&expr, CIL_FALSE);
expr = next;
}
free(attr->expr_list);
attr->expr_list = NULL;
}
cil_symtab_datum_destroy(&attr->datum);
ebitmap_destroy(attr->users);
free(attr->users);
free(attr);
}
int cil_gen_userattributeset(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
{
enum cil_syntax syntax[] = {
CIL_SYN_STRING,
CIL_SYN_STRING,
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
int syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_userattributeset *attrset = NULL;
int rc = SEPOL_ERR;
if (db == NULL || parse_current == NULL || ast_node == NULL) {
goto exit;
}
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
goto exit;
}
cil_userattributeset_init(&attrset);
attrset->attr_str = parse_current->next->data;
rc = cil_gen_expr(parse_current->next->next, CIL_USER, &attrset->str_expr);
if (rc != SEPOL_OK) {
goto exit;
}
ast_node->data = attrset;
ast_node->flavor = CIL_USERATTRIBUTESET;
return SEPOL_OK;
exit:
cil_log(CIL_ERR, "Bad userattributeset declaration at line %d of %s\n",
parse_current->line, parse_current->path);
cil_destroy_userattributeset(attrset);
return rc;
}
void cil_destroy_userattributeset(struct cil_userattributeset *attrset)
{
if (attrset == NULL) {
return;
}
cil_list_destroy(&attrset->str_expr, CIL_TRUE);
cil_list_destroy(&attrset->datum_expr, CIL_FALSE);
free(attrset);
}
int cil_gen_userlevel(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
{
enum cil_syntax syntax[] = {
@ -1903,6 +2025,169 @@ void cil_destroy_avrule(struct cil_avrule *rule)
free(rule);
}
int cil_fill_permissionx(struct cil_tree_node *parse_current, struct cil_permissionx *permx)
{
enum cil_syntax syntax[] = {
CIL_SYN_STRING,
CIL_SYN_STRING,
CIL_SYN_LIST,
CIL_SYN_END
};
int syntax_len = sizeof(syntax)/sizeof(*syntax);
int rc = SEPOL_ERR;
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
goto exit;
}
if (parse_current->data == CIL_KEY_IOCTL) {
permx->kind = CIL_PERMX_KIND_IOCTL;
} else {
cil_log(CIL_ERR, "Unknown permissionx kind, %s. Must be \"ioctl\"\n", (char *)parse_current->data);
rc = SEPOL_ERR;
goto exit;
}
permx->obj_str = parse_current->next->data;
rc = cil_gen_expr(parse_current->next->next, CIL_PERMISSIONX, &permx->expr_str);
if (rc != SEPOL_OK) {
goto exit;
}
return SEPOL_OK;
exit:
cil_log(CIL_ERR, "Bad permissionx content at line %d of %s\n",
parse_current->line, parse_current->path);
return rc;
}
int cil_gen_permissionx(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
{
enum cil_syntax syntax[] = {
CIL_SYN_STRING,
CIL_SYN_STRING,
CIL_SYN_LIST,
CIL_SYN_END
};
int syntax_len = sizeof(syntax)/sizeof(*syntax);
char *key = NULL;
struct cil_permissionx *permx = NULL;
int rc = SEPOL_ERR;
if (parse_current == NULL || ast_node == NULL) {
goto exit;
}
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
goto exit;
}
cil_permissionx_init(&permx);
key = parse_current->next->data;
rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)permx, (hashtab_key_t)key, CIL_SYM_PERMX, CIL_PERMISSIONX);
if (rc != SEPOL_OK) {
goto exit;
}
rc = cil_fill_permissionx(parse_current->next->next->cl_head, permx);
if (rc != SEPOL_OK) {
goto exit;
}
return SEPOL_OK;
exit:
cil_log(CIL_ERR, "Bad permissionx statement at line %d of %s\n",
parse_current->line, parse_current->path);
cil_destroy_permissionx(permx);
cil_clear_node(ast_node);
return rc;
}
void cil_destroy_permissionx(struct cil_permissionx *permx)
{
if (permx == NULL) {
return;
}
cil_symtab_datum_destroy(&permx->datum);
cil_list_destroy(&permx->expr_str, CIL_TRUE);
ebitmap_destroy(permx->perms);
free(permx->perms);
free(permx);
}
int cil_gen_avrulex(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind)
{
enum cil_syntax syntax[] = {
CIL_SYN_STRING,
CIL_SYN_STRING,
CIL_SYN_STRING,
CIL_SYN_STRING | CIL_SYN_LIST,
CIL_SYN_END
};
int syntax_len = sizeof(syntax)/sizeof(*syntax);
struct cil_avrulex *rule = NULL;
int rc = SEPOL_ERR;
if (parse_current == NULL || ast_node == NULL) {
goto exit;
}
rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
if (rc != SEPOL_OK) {
goto exit;
}
cil_avrulex_init(&rule);
rule->rule_kind = rule_kind;
rule->src_str = parse_current->next->data;
rule->tgt_str = parse_current->next->next->data;
if (parse_current->next->next->next->cl_head == NULL) {
rule->permx_str = parse_current->next->next->next->data;
} else {
cil_permissionx_init(&rule->permx);
rc = cil_fill_permissionx(parse_current->next->next->next->cl_head, rule->permx);
if (rc != SEPOL_OK) {
goto exit;
}
}
ast_node->data = rule;
ast_node->flavor = CIL_AVRULEX;
return SEPOL_OK;
exit:
cil_log(CIL_ERR, "Bad allowx rule at line %d of %s\n",
parse_current->line, parse_current->path);
cil_destroy_avrulex(rule);
return rc;
}
void cil_destroy_avrulex(struct cil_avrulex *rule)
{
if (rule == NULL) {
return;
}
if (rule->permx_str == NULL && rule->permx != NULL) {
cil_destroy_permissionx(rule->permx);
}
free(rule);
}
int cil_gen_type_rule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind)
{
enum cil_syntax syntax[] = {
@ -2217,8 +2502,8 @@ static enum cil_flavor __cil_get_expr_operator_flavor(const char *op)
else if (op == CIL_KEY_EQ) return CIL_EQ; /* Only conditional */
else if (op == CIL_KEY_NEQ) return CIL_NEQ; /* Only conditional */
else if (op == CIL_KEY_XOR) return CIL_XOR;
else if (op == CIL_KEY_ALL) return CIL_ALL; /* Only set */
else if (op == CIL_KEY_RANGE) return CIL_RANGE; /* Only catset */
else if (op == CIL_KEY_ALL) return CIL_ALL; /* Only set and permissionx */
else if (op == CIL_KEY_RANGE) return CIL_RANGE; /* Only catset and permissionx */
else return CIL_NONE;
}
@ -5587,27 +5872,14 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
}
if (macro != NULL) {
if (parse_current->data == CIL_KEY_MACRO) {
if (parse_current->data == CIL_KEY_MACRO ||
parse_current->data == CIL_KEY_TUNABLE ||
parse_current->data == CIL_KEY_IN ||
parse_current->data == CIL_KEY_BLOCK ||
parse_current->data == CIL_KEY_BLOCKINHERIT ||
parse_current->data == CIL_KEY_BLOCKABSTRACT) {
rc = SEPOL_ERR;
cil_log(CIL_ERR, "Found macro at line %d of %s\n",
parse_current->line, parse_current->path);
cil_log(CIL_ERR, "Macros cannot be defined within macro statement\n");
goto exit;
}
if (parse_current->data == CIL_KEY_TUNABLE) {
rc = SEPOL_ERR;
cil_log(CIL_ERR, "Found tunable at line %d of %s\n",
parse_current->line, parse_current->path);
cil_log(CIL_ERR, "Tunables cannot be defined within macro statement\n");
goto exit;
}
if (parse_current->data == CIL_KEY_IN) {
rc = SEPOL_ERR;
cil_log(CIL_ERR, "Found in at line %d of %s\n",
parse_current->line, parse_current->path);
cil_log(CIL_ERR, "in-statements cannot be defined within macro statement\n");
cil_log(CIL_ERR, "%s is not allowed in macros (%s:%d)\n", (char *)parse_current->data, parse_current->path, parse_current->line);
goto exit;
}
}
@ -5705,6 +5977,11 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
*finished = CIL_TREE_SKIP_NEXT;
} else if (parse_current->data == CIL_KEY_USER) {
rc = cil_gen_user(db, parse_current, ast_node);
} else if (parse_current->data == CIL_KEY_USERATTRIBUTE) {
rc = cil_gen_userattribute(db, parse_current, ast_node);
} else if (parse_current->data == CIL_KEY_USERATTRIBUTESET) {
rc = cil_gen_userattributeset(db, parse_current, ast_node);
*finished = CIL_TREE_SKIP_NEXT;
} else if (parse_current->data == CIL_KEY_USERLEVEL) {
rc = cil_gen_userlevel(db, parse_current, ast_node);
*finished = CIL_TREE_SKIP_NEXT;
@ -5789,6 +6066,18 @@ int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *f
} else if (parse_current->data == CIL_KEY_NEVERALLOW) {
rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_NEVERALLOW);
*finished = CIL_TREE_SKIP_NEXT;
} else if (parse_current->data == CIL_KEY_ALLOWX) {
rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_ALLOWED);
*finished = CIL_TREE_SKIP_NEXT;
} else if (parse_current->data == CIL_KEY_AUDITALLOWX) {
rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_AUDITALLOW);
*finished = CIL_TREE_SKIP_NEXT;
} else if (parse_current->data == CIL_KEY_DONTAUDITX) {
rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_DONTAUDIT);
*finished = CIL_TREE_SKIP_NEXT;
} else if (parse_current->data == CIL_KEY_PERMISSIONX) {
rc = cil_gen_permissionx(db, parse_current, ast_node);
*finished = CIL_TREE_SKIP_NEXT;
} else if (parse_current->data == CIL_KEY_TYPETRANSITION) {
rc = cil_gen_typetransition(db, parse_current, ast_node);
} else if (parse_current->data == CIL_KEY_TYPECHANGE) {

View File

@ -80,6 +80,10 @@ int cil_gen_sidorder(struct cil_db *db, struct cil_tree_node *parse_current, str
void cil_destroy_sidorder(struct cil_sidorder *sidorder);
int cil_gen_user(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
void cil_destroy_user(struct cil_user *user);
int cil_gen_userattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
void cil_destroy_userattribute(struct cil_userattribute *attr);
int cil_gen_userattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
void cil_destroy_userattributeset(struct cil_userattributeset *attrset);
int cil_gen_userlevel(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
void cil_destroy_userlevel(struct cil_userlevel *usrlvl);
int cil_gen_userrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
@ -107,6 +111,10 @@ void cil_destroy_roleattributeset(struct cil_roleattributeset *attrset);
int cil_gen_rolebounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
int cil_gen_avrule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind);
void cil_destroy_avrule(struct cil_avrule *rule);
int cil_gen_avrulex(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind);
void cil_destroy_avrulex(struct cil_avrulex *rule);
int cil_gen_permissionx(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);
void cil_destroy_permissionx(struct cil_permissionx *permx);
int cil_gen_type_rule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind);
void cil_destroy_type_rule(struct cil_type_rule *rule);
int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node);

View File

@ -282,6 +282,8 @@ int cil_copy_classpermission(__attribute__((unused)) struct cil_db *db, void *da
}
}
cil_classpermission_init(&new);
cil_copy_classperms_list(orig->classperms, &new->classperms);
*copy = new;
@ -294,6 +296,8 @@ int cil_copy_classpermissionset(__attribute__((unused)) struct cil_db *db, void
struct cil_classpermissionset *orig = data;
struct cil_classpermissionset *new = NULL;
cil_classpermissionset_init(&new);
new->set_str = orig->set_str;
cil_copy_classperms_list(orig->classperms, &new->classperms);
@ -388,6 +392,41 @@ int cil_copy_user(__attribute__((unused)) struct cil_db *db, void *data, void **
return SEPOL_OK;
}
int cil_copy_userattribute(__attribute__((unused)) struct cil_db *db, void *data, void **copy, symtab_t *symtab)
{
struct cil_userattribute *orig = data;
struct cil_userattribute *new = NULL;
char *key = orig->datum.name;
struct cil_symtab_datum *datum = NULL;
cil_symtab_get_datum(symtab, key, &datum);
if (datum == NULL) {
cil_userattribute_init(&new);
*copy = new;
} else {
*copy = datum;
}
return SEPOL_OK;
}
int cil_copy_userattributeset(struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
{
struct cil_userattributeset *orig = data;
struct cil_userattributeset *new = NULL;
cil_userattributeset_init(&new);
new->attr_str = orig->attr_str;
cil_copy_expr(db, orig->str_expr, &new->str_expr);
cil_copy_expr(db, orig->datum_expr, &new->datum_expr);
*copy = new;
return SEPOL_OK;
}
int cil_copy_userrole(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
{
struct cil_userrole *orig = data;
@ -760,6 +799,59 @@ int cil_copy_avrule(__attribute__((unused)) struct cil_db *db, void *data, void
return SEPOL_OK;
}
void cil_copy_fill_permissionx(struct cil_db *db, struct cil_permissionx *orig, struct cil_permissionx *new)
{
new->kind = orig->kind;
new->obj_str = orig->obj_str;
cil_copy_expr(db, orig->expr_str, &new->expr_str);
}
int cil_copy_permissionx(struct cil_db *db, void *data, void **copy, symtab_t *symtab)
{
struct cil_permissionx *orig = data;
struct cil_permissionx *new = NULL;
char *key = orig->datum.name;
struct cil_symtab_datum *datum = NULL;
cil_symtab_get_datum(symtab, key, &datum);
if (datum != NULL) {
cil_log(CIL_INFO, "cil_copy_permissionx: permissionx cannot be redefined\n");
return SEPOL_ERR;
}
cil_permissionx_init(&new);
cil_copy_fill_permissionx(db, orig, new);
*copy = new;
return SEPOL_OK;
}
int cil_copy_avrulex(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
{
struct cil_avrulex *orig = data;
struct cil_avrulex *new = NULL;
cil_avrulex_init(&new);
new->rule_kind = orig->rule_kind;
new->src_str = orig->src_str;
new->tgt_str = orig->tgt_str;
if (new->permx_str != NULL) {
new->permx_str = orig->permx_str;
} else {
cil_permissionx_init(&new->permx);
cil_copy_fill_permissionx(db, orig->permx, new->permx);
}
*copy = new;
return SEPOL_OK;
}
int cil_copy_type_rule(__attribute__((unused)) struct cil_db *db, void *data, void **copy, __attribute__((unused)) symtab_t *symtab)
{
struct cil_type_rule *orig = data;
@ -1660,6 +1752,12 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
case CIL_USER:
copy_func = &cil_copy_user;
break;
case CIL_USERATTRIBUTE:
copy_func = &cil_copy_userattribute;
break;
case CIL_USERATTRIBUTESET:
copy_func = &cil_copy_userattributeset;
break;
case CIL_USERROLE:
copy_func = &cil_copy_userrole;
break;
@ -1732,6 +1830,12 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
case CIL_AVRULE:
copy_func = &cil_copy_avrule;
break;
case CIL_AVRULEX:
copy_func = &cil_copy_avrulex;
break;
case CIL_PERMISSIONX:
copy_func = &cil_copy_permissionx;
break;
case CIL_TYPE_RULE:
copy_func = &cil_copy_type_rule;
break;
@ -1909,7 +2013,14 @@ int __cil_copy_node_helper(struct cil_tree_node *orig, __attribute__((unused)) u
if (new->flavor == CIL_BLOCKINHERIT) {
blockinherit = new->data;
cil_list_append(blockinherit->block->bi_nodes, CIL_NODE, new);
// if a blockinherit statement is copied before blockinherit are
// resolved (like in an in-statement), the block will not have been
// resolved yet, so there's nothing to append yet. This is fine,
// the copied blockinherit statement will be handled later, as if
// it wasn't in an in-statement
if (blockinherit->block != NULL) {
cil_list_append(blockinherit->block->bi_nodes, CIL_NODE, new);
}
}
if (parent->cl_head == NULL) {

View File

@ -57,6 +57,8 @@ int cil_copy_sid(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
int cil_copy_sidcontext(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
int cil_copy_sidorder(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
int cil_copy_user(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
int cil_copy_userattribute(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
int cil_copy_userattributeset(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
int cil_copy_userrole(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
int cil_copy_userlevel(struct cil_db *db, void *data, void **copy, symtab_t *symtab);
int cil_copy_userrange(struct cil_db *db, void *data, void **copy, symtab_t *symtab);

305
libsepol/cil/src/cil_find.c Normal file
View File

@ -0,0 +1,305 @@
/*
* Copyright 2011 Tresys Technology, LLC. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those
* of the authors and should not be interpreted as representing official policies,
* either expressed or implied, of Tresys Technology, LLC.
*/
#include <sepol/policydb/ebitmap.h>
#include "cil_internal.h"
#include "cil_flavor.h"
#include "cil_list.h"
#include "cil_log.h"
#include "cil_symtab.h"
struct cil_args_find {
enum cil_flavor flavor;
void *target;
struct cil_list *matching;
int match_self;
};
static int cil_type_match_any(struct cil_symtab_datum *d1, struct cil_symtab_datum *d2)
{
enum cil_flavor f1 = ((struct cil_tree_node*)d1->nodes->head->data)->flavor;
enum cil_flavor f2 = ((struct cil_tree_node*)d2->nodes->head->data)->flavor;
if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
struct cil_type *t1 = (struct cil_type *)d1;
struct cil_type *t2 = (struct cil_type *)d2;
if (t1->value == t2->value) {
return CIL_TRUE;
}
} else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
struct cil_typeattribute *a = (struct cil_typeattribute *)d1;
struct cil_type *t = (struct cil_type *)d2;
if (ebitmap_get_bit(a->types, t->value)) {
return CIL_TRUE;
}
} else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) {
struct cil_type *t = (struct cil_type *)d1;
struct cil_typeattribute *a = (struct cil_typeattribute *)d2;
if (ebitmap_get_bit(a->types, t->value)) {
return CIL_TRUE;
}
} else {
/* Both are attributes */
struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1;
struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2;
return ebitmap_match_any(a1->types, a2->types);
}
return CIL_FALSE;
}
static int cil_type_matches(ebitmap_t *matches, struct cil_symtab_datum *d1, struct cil_symtab_datum *d2)
{
int rc = SEPOL_OK;
enum cil_flavor f1 = ((struct cil_tree_node*)d1->nodes->head->data)->flavor;
enum cil_flavor f2 = ((struct cil_tree_node*)d2->nodes->head->data)->flavor;
if (f1 != CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
struct cil_type *t1 = (struct cil_type *)d1;
struct cil_type *t2 = (struct cil_type *)d2;
if (t1->value == t2->value) {
ebitmap_set_bit(matches, t1->value, 1);
}
} else if (f1 == CIL_TYPEATTRIBUTE && f2 != CIL_TYPEATTRIBUTE) {
struct cil_typeattribute *a = (struct cil_typeattribute *)d1;
struct cil_type *t = (struct cil_type *)d2;
if (ebitmap_get_bit(a->types, t->value)) {
ebitmap_set_bit(matches, t->value, 1);
}
} else if (f1 != CIL_TYPEATTRIBUTE && f2 == CIL_TYPEATTRIBUTE) {
struct cil_type *t = (struct cil_type *)d1;
struct cil_typeattribute *a = (struct cil_typeattribute *)d2;
if (ebitmap_get_bit(a->types, t->value)) {
ebitmap_set_bit(matches, t->value, 1);
}
} else {
/* Both are attributes */
struct cil_typeattribute *a1 = (struct cil_typeattribute *)d1;
struct cil_typeattribute *a2 = (struct cil_typeattribute *)d2;
rc = ebitmap_and(matches, a1->types, a2->types);
}
return rc;
}
/* s1 is the src type that is matched with a self
* s2, and t2 are the source and type of the other rule
*/
static int cil_self_match_any(struct cil_symtab_datum *s1, struct cil_symtab_datum *s2, struct cil_symtab_datum *t2)
{
int rc;
struct cil_tree_node *n1 = s1->nodes->head->data;
if (n1->flavor != CIL_TYPEATTRIBUTE) {
rc = cil_type_match_any(s1, t2);
} else {
struct cil_typeattribute *a = (struct cil_typeattribute *)s1;
ebitmap_t map;
ebitmap_init(&map);
rc = cil_type_matches(&map, s2, t2);
if (rc < 0) {
ebitmap_destroy(&map);
goto exit;
}
if (map.node == NULL) {
rc = CIL_FALSE;
goto exit;
}
rc = ebitmap_match_any(&map, a->types);
ebitmap_destroy(&map);
}
exit:
return rc;
}
static int cil_classperms_match_any(struct cil_classperms *cp1, struct cil_classperms *cp2)
{
struct cil_class *c1 = cp1->class;
struct cil_class *c2 = cp2->class;
struct cil_list_item *i1, *i2;
if (&c1->datum != &c2->datum) return CIL_FALSE;
cil_list_for_each(i1, cp1->perms) {
struct cil_perm *p1 = i1->data;
cil_list_for_each(i2, cp2->perms) {
struct cil_perm *p2 = i2->data;
if (&p1->datum == &p2->datum) return CIL_TRUE;
}
}
return CIL_FALSE;
}
static int __cil_classperms_list_match_any(struct cil_classperms *cp1, struct cil_list *cpl2)
{
int rc;
struct cil_list_item *curr;
cil_list_for_each(curr, cpl2) {
if (curr->flavor == CIL_CLASSPERMS) {
struct cil_classperms *cp = curr->data;
if (FLAVOR(cp->class) == CIL_CLASS) {
rc = cil_classperms_match_any(cp1, cp);
if (rc == CIL_TRUE) return CIL_TRUE;
} else { /* MAP */
struct cil_list_item *i = NULL;
cil_list_for_each(i, cp->perms) {
struct cil_perm *cmp = i->data;
rc = __cil_classperms_list_match_any(cp1, cmp->classperms);
if (rc == CIL_TRUE) return CIL_TRUE;
}
}
} else { /* SET */
struct cil_classperms_set *cp_set = curr->data;
struct cil_classpermission *cp = cp_set->set;
rc = __cil_classperms_list_match_any(cp1, cp->classperms);
if (rc == CIL_TRUE) return CIL_TRUE;
}
}
return CIL_FALSE;
}
static int cil_classperms_list_match_any(struct cil_list *cpl1, struct cil_list *cpl2)
{
int rc;
struct cil_list_item *curr;
cil_list_for_each(curr, cpl1) {
if (curr->flavor == CIL_CLASSPERMS) {
struct cil_classperms *cp = curr->data;
if (FLAVOR(cp->class) == CIL_CLASS) {
rc = __cil_classperms_list_match_any(cp, cpl2);
if (rc == CIL_TRUE) return CIL_TRUE;
} else { /* MAP */
struct cil_list_item *i = NULL;
cil_list_for_each(i, cp->perms) {
struct cil_perm *cmp = i->data;
rc = cil_classperms_list_match_any(cmp->classperms, cpl2);
if (rc == CIL_TRUE) return CIL_TRUE;
}
}
} else { /* SET */
struct cil_classperms_set *cp_set = curr->data;
struct cil_classpermission *cp = cp_set->set;
rc = cil_classperms_list_match_any(cp->classperms, cpl2);
if (rc == CIL_TRUE) return CIL_TRUE;
}
}
return CIL_FALSE;
}
int cil_find_matching_avrule(struct cil_tree_node *node, struct cil_avrule *avrule, struct cil_avrule *target, struct cil_list *matching, int match_self)
{
int rc = SEPOL_OK;
struct cil_symtab_datum *s1 = avrule->src;
struct cil_symtab_datum *t1 = avrule->tgt;
struct cil_list *cp1 = avrule->classperms;
struct cil_symtab_datum *s2 = target->src;
struct cil_symtab_datum *t2 = target->tgt;
struct cil_list *cp2 = target->classperms;
if (match_self != CIL_TRUE && avrule == target) goto exit;
if (avrule->rule_kind != target->rule_kind) goto exit;
if (!cil_type_match_any(s1, s2)) goto exit;
if (t1->fqn != CIL_KEY_SELF && t2->fqn != CIL_KEY_SELF) {
if (!cil_type_match_any(t1, t2)) goto exit;
} else {
if (t1->fqn == CIL_KEY_SELF && t2->fqn == CIL_KEY_SELF) {
/* The earlier check whether s1 and s2 matches is all that is needed */
} else if (t1->fqn == CIL_KEY_SELF) {
rc = cil_self_match_any(s1, s2, t2);
if (rc < 0) {
goto exit;
} else if (rc == CIL_FALSE) {
rc = SEPOL_OK;
goto exit;
}
} else if (t2->fqn == CIL_KEY_SELF) {
rc = cil_self_match_any(s2, s1, t1);
if (rc < 0) {
goto exit;
} else if (rc == CIL_FALSE) {
rc = SEPOL_OK;
goto exit;
}
}
}
if (cil_classperms_list_match_any(cp1, cp2)) {
cil_list_append(matching, CIL_NODE, node);
}
rc = SEPOL_OK;
exit:
return rc;
}
static int __cil_find_matching_avrule_in_ast(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
{
int rc = SEPOL_OK;
struct cil_args_find *args = extra_args;
if (node->flavor == CIL_BLOCK) {
struct cil_block *blk = node->data;
if (blk->is_abstract == CIL_TRUE) {
*finished = CIL_TREE_SKIP_HEAD;
goto exit;
}
} else if (node->flavor == CIL_MACRO) {
*finished = CIL_TREE_SKIP_HEAD;
goto exit;
} else if (node->flavor == CIL_AVRULE) {
rc = cil_find_matching_avrule(node, node->data, args->target, args->matching, args->match_self);
}
exit:
return rc;
}
int cil_find_matching_avrule_in_ast(struct cil_tree_node *current, enum cil_flavor flavor, void *target, struct cil_list *matching, int match_self)
{
int rc;
struct cil_args_find args;
args.flavor = flavor;
args.target = target;
args.matching = matching;
args.match_self = match_self;
rc = cil_tree_walk(current, __cil_find_matching_avrule_in_ast, NULL, NULL, &args);
if (rc) {
cil_log(CIL_ERR, "An error occured while searching for avrule in AST\n");
}
return rc;
}

View File

@ -0,0 +1,39 @@
/*
* Copyright 2011 Tresys Technology, LLC. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
* EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those
* of the authors and should not be interpreted as representing official policies,
* either expressed or implied, of Tresys Technology, LLC.
*/
#include "cil_flavor.h"
#include "cil_tree.h"
#include "cil_list.h"
#ifndef CIL_FIND_H_
#define CIL_FIND_H_
int cil_find_matching_avrule_in_ast(struct cil_tree_node *current, enum cil_flavor flavor, void *target, struct cil_list *matching, int match_self);
#endif

View File

@ -63,6 +63,7 @@ enum cil_flavor {
CIL_CLASSPERMISSIONSET,
CIL_USERPREFIX,
CIL_USERROLE,
CIL_USERATTRIBUTESET,
CIL_USERLEVEL,
CIL_USERRANGE,
CIL_USERBOUNDS,
@ -83,6 +84,7 @@ enum cil_flavor {
CIL_SIDORDER,
CIL_ROLEALLOW,
CIL_AVRULE,
CIL_AVRULEX,
CIL_ROLETRANSITION,
CIL_TYPE_RULE,
CIL_NAMETYPETRANSITION,
@ -163,6 +165,7 @@ enum cil_flavor {
CIL_MAP_CLASS,
CIL_CLASSPERMISSION,
CIL_USER,
CIL_USERATTRIBUTE,
CIL_ROLE,
CIL_ROLEATTRIBUTE,
CIL_TYPE,
@ -180,6 +183,7 @@ enum cil_flavor {
CIL_CONTEXT,
CIL_IPADDR,
CIL_POLICYCAP,
CIL_PERMISSIONX
};

View File

@ -102,6 +102,7 @@ static int __cil_fqn_qualify_blocks(__attribute__((unused)) hashtab_key_t k, has
case CIL_SYM_LEVELRANGES:
case CIL_SYM_IPADDRS:
case CIL_SYM_NAMES:
case CIL_SYM_PERMX:
/* These do not show up in the kernal policy */
break;
case CIL_SYM_POLICYCAPS:

View File

@ -127,6 +127,8 @@ char *CIL_KEY_TRANS;
char *CIL_KEY_TYPE;
char *CIL_KEY_ROLE;
char *CIL_KEY_USER;
char *CIL_KEY_USERATTRIBUTE;
char *CIL_KEY_USERATTRIBUTESET;
char *CIL_KEY_SENSITIVITY;
char *CIL_KEY_CATEGORY;
char *CIL_KEY_CATSET;
@ -216,6 +218,11 @@ char *CIL_KEY_DEFAULTTYPE;
char *CIL_KEY_ROOT;
char *CIL_KEY_NODE;
char *CIL_KEY_PERM;
char *CIL_KEY_ALLOWX;
char *CIL_KEY_AUDITALLOWX;
char *CIL_KEY_DONTAUDITX;
char *CIL_KEY_PERMISSIONX;
char *CIL_KEY_IOCTL;
/*
Symbol Table Array Indices
@ -239,6 +246,7 @@ enum cil_sym_index {
CIL_SYM_POLICYCAPS,
CIL_SYM_IPADDRS,
CIL_SYM_NAMES,
CIL_SYM_PERMX,
CIL_SYM_NUM,
CIL_SYM_UNKNOWN,
CIL_SYM_PERMS // Special case for permissions. This symtab is not included in arrays
@ -279,11 +287,15 @@ struct cil_db {
struct cil_list *userprefixes;
struct cil_list *selinuxusers;
struct cil_list *names;
int num_types_and_attrs;
int num_classes;
int num_cats;
int num_types;
int num_roles;
int num_users;
struct cil_type **val_to_type;
struct cil_role **val_to_role;
struct cil_user **val_to_user;
int disable_dontaudit;
int disable_neverallow;
int preserve_tunables;
@ -410,14 +422,27 @@ struct cil_sidorder {
struct cil_user {
struct cil_symtab_datum datum;
struct cil_user *bounds;
struct cil_list *roles;
ebitmap_t *roles;
struct cil_level *dftlevel;
struct cil_levelrange *range;
int value;
};
struct cil_userattribute {
struct cil_symtab_datum datum;
struct cil_list *expr_list;
ebitmap_t *users;
};
struct cil_userattributeset {
char *attr_str;
struct cil_list *str_expr;
struct cil_list *datum_expr;
};
struct cil_userrole {
char *user_str;
struct cil_user *user;
void *user;
char *role_str;
void *role;
};
@ -552,6 +577,26 @@ struct cil_avrule {
struct cil_list *classperms;
};
#define CIL_PERMX_KIND_IOCTL 1
struct cil_permissionx {
struct cil_symtab_datum datum;
uint32_t kind;
char *obj_str;
void *obj;
struct cil_list *expr_str;
ebitmap_t *perms;
};
struct cil_avrulex {
uint32_t rule_kind;
char *src_str;
void *src; /* type, alias, or attribute */
char *tgt_str;
void *tgt; /* type, alias, or attribute */
char *permx_str;
struct cil_permissionx *permx;
};
#define CIL_TYPE_TRANSITION 16
#define CIL_TYPE_MEMBER 32
#define CIL_TYPE_CHANGE 64
@ -928,6 +973,8 @@ void cil_condblock_init(struct cil_condblock **cb);
void cil_tunable_init(struct cil_tunable **ciltun);
void cil_tunif_init(struct cil_tunableif **tif);
void cil_avrule_init(struct cil_avrule **avrule);
void cil_avrulex_init(struct cil_avrulex **avrulex);
void cil_permissionx_init(struct cil_permissionx **permx);
void cil_type_rule_init(struct cil_type_rule **type_rule);
void cil_roletransition_init(struct cil_roletransition **roletrans);
void cil_roleallow_init(struct cil_roleallow **role_allow);
@ -972,5 +1019,7 @@ void cil_default_init(struct cil_default **def);
void cil_defaultrange_init(struct cil_defaultrange **def);
void cil_handleunknown_init(struct cil_handleunknown **unk);
void cil_mls_init(struct cil_mls **mls);
void cil_userattribute_init(struct cil_userattribute **attribute);
void cil_userattributeset_init(struct cil_userattributeset **attrset);
#endif

View File

@ -1155,11 +1155,6 @@ int __cil_gen_policy_node_helper(struct cil_tree_node *node, uint32_t *finished,
case CIL_USER:
cil_multimap_insert(users, node->data, NULL, CIL_USERROLE, CIL_NONE);
break;
case CIL_USERROLE: {
struct cil_userrole *userrole = node->data;
cil_multimap_insert(users, &userrole->user->datum, (struct cil_symtab_datum *)userrole->role, CIL_USERROLE, CIL_ROLE);
}
break;
case CIL_CATALIAS: {
struct cil_alias *alias = node->data;
struct cil_symtab_datum *datum = alias->actual;

View File

@ -339,28 +339,53 @@ static int __cil_post_db_count_helper(struct cil_tree_node *node, uint32_t *fini
case CIL_MACRO:
*finished = CIL_TREE_SKIP_HEAD;
break;
case CIL_TYPE: {
struct cil_type *type = node->data;
if (type->datum.nodes->head->data == node) {
// multiple AST nodes can point to the same cil_type data (like if
// copied from a macro). This check ensures we only count the
// duplicates once
type->value = db->num_types;
db->num_types++;
case CIL_CLASS: {
struct cil_class *class = node->data;
if (class->datum.nodes->head->data == node) {
// Multiple nodes can point to the same datum. Only count once.
db->num_classes++;
}
break;
}
case CIL_TYPE: {
struct cil_type *type = node->data;
if (type->datum.nodes->head->data == node) {
// Multiple nodes can point to the same datum. Only count once.
type->value = db->num_types;
db->num_types++;
db->num_types_and_attrs++;
}
break;
}
case CIL_TYPEATTRIBUTE: {
struct cil_typeattribute *attr = node->data;
if (attr->datum.nodes->head->data == node) {
// Multiple nodes can point to the same datum. Only count once.
db->num_types_and_attrs++;
}
break;
}
case CIL_ROLE: {
struct cil_role *role = node->data;
if (role->datum.nodes->head->data == node) {
// multiple AST nodes can point to the same cil_role data (like if
// copied from a macro). This check ensures we only count the
// duplicates once
// Multiple nodes can point to the same datum. Only count once.
role->value = db->num_roles;
db->num_roles++;
}
break;
}
case CIL_USER: {
struct cil_user *user = node->data;
if (user->datum.nodes->head->data == node) {
// multiple AST nodes can point to the same cil_user data (like if
// copied from a macro). This check ensures we only count the
// duplicates once
user->value = db->num_users;
db->num_users++;
}
break;
}
case CIL_NETIFCON:
db->netifcon->count++;
break;
@ -432,6 +457,14 @@ static int __cil_post_db_array_helper(struct cil_tree_node *node, __attribute__(
db->val_to_role[role->value] = role;
break;
}
case CIL_USER: {
struct cil_user *user= node->data;
if (db->val_to_user == NULL) {
db->val_to_user = cil_malloc(sizeof(*db->val_to_user) * db->num_users);
}
db->val_to_user[user->value] = user;
break;
}
case CIL_USERPREFIX: {
cil_list_append(db->userprefixes, CIL_USERPREFIX, node->data);
break;
@ -624,6 +657,54 @@ exit:
return rc;
}
static int __evaluate_user_expression(struct cil_userattribute *attr, struct cil_db *db)
{
int rc;
attr->users = cil_malloc(sizeof(*attr->users));
rc = __cil_expr_list_to_bitmap(attr->expr_list, attr->users, db->num_users, db);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to expand user attribute to bitmap\n");
ebitmap_destroy(attr->users);
free(attr->users);
attr->users = NULL;
}
return rc;
}
static int __cil_user_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, struct cil_db *db)
{
int rc = SEPOL_ERR;
struct cil_tree_node *node = datum->nodes->head->data;
struct cil_userattribute *attr = NULL;
struct cil_user *user = NULL;
ebitmap_init(bitmap);
if (node->flavor == CIL_USERATTRIBUTE) {
attr = (struct cil_userattribute *)datum;
if (attr->users == NULL) {
rc = __evaluate_user_expression(attr, db);
if (rc != SEPOL_OK) {
goto exit;
}
}
ebitmap_union(bitmap, attr->users);
} else {
user = (struct cil_user *)datum;
if (ebitmap_set_bit(bitmap, user->value, 1)) {
cil_log(CIL_ERR, "Failed to set user bit\n");
ebitmap_destroy(bitmap);
goto exit;
}
}
return SEPOL_OK;
exit:
return rc;
}
static int __evaluate_role_expression(struct cil_roleattribute *attr, struct cil_db *db)
{
int rc;
@ -668,6 +749,70 @@ exit:
return rc;
}
static int __evaluate_permissionx_expression(struct cil_permissionx *permx, struct cil_db *db)
{
int rc;
permx->perms = cil_malloc(sizeof(*permx->perms));
ebitmap_init(permx->perms);
rc = __cil_expr_to_bitmap(permx->expr_str, permx->perms, 0x10000, db); // max is one more than 0xFFFF
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to expand permissionx expression\n");
ebitmap_destroy(permx->perms);
free(permx->perms);
permx->perms = NULL;
}
return rc;
}
static int __cil_permx_str_to_int(char *permx_str, uint16_t *val)
{
char *endptr = NULL;
long lval = strtol(permx_str, &endptr, 0);
if (*endptr != '\0') {
cil_log(CIL_ERR, "permissionx value %s not valid number\n", permx_str);
goto exit;
}
if (lval < 0x0000 || lval > 0xFFFF) {
cil_log(CIL_ERR, "permissionx value %s must be between 0x0000 and 0xFFFF\n", permx_str);
goto exit;
}
*val = (uint16_t)lval;
return SEPOL_OK;
exit:
return SEPOL_ERR;
}
static int __cil_permx_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, __attribute__((unused)) struct cil_db *db)
{
int rc = SEPOL_ERR;
uint16_t val;
ebitmap_init(bitmap);
rc = __cil_permx_str_to_int((char*)datum, &val);
if (rc != SEPOL_OK) {
goto exit;
}
if (ebitmap_set_bit(bitmap, (unsigned int)val, 1)) {
cil_log(CIL_ERR, "Failed to set permissionx bit\n");
ebitmap_destroy(bitmap);
goto exit;
}
return SEPOL_OK;
exit:
return rc;
}
static int __cil_perm_to_bitmap(struct cil_symtab_datum *datum, ebitmap_t *bitmap, __attribute__((unused)) struct cil_db *db)
{
struct cil_perm *perm = (struct cil_perm *)datum;
@ -778,7 +923,7 @@ exit:
return rc;
}
static int __cil_expr_range_to_bitmap_helper(struct cil_list_item *i1, struct cil_list_item *i2, ebitmap_t *bitmap)
static int __cil_cat_expr_range_to_bitmap_helper(struct cil_list_item *i1, struct cil_list_item *i2, ebitmap_t *bitmap)
{
int rc = SEPOL_ERR;
struct cil_symtab_datum *d1 = i1->data;
@ -818,6 +963,39 @@ exit:
return rc;
}
static int __cil_permissionx_expr_range_to_bitmap_helper(struct cil_list_item *i1, struct cil_list_item *i2, ebitmap_t *bitmap)
{
int rc = SEPOL_ERR;
char *p1 = i1->data;
char *p2 = i2->data;
uint16_t v1;
uint16_t v2;
uint32_t i;
rc = __cil_permx_str_to_int(p1, &v1);
if (rc != SEPOL_OK) {
goto exit;
}
rc = __cil_permx_str_to_int(p2, &v2);
if (rc != SEPOL_OK) {
goto exit;
}
for (i = v1; i <= v2; i++) {
if (ebitmap_set_bit(bitmap, i, 1)) {
cil_log(CIL_ERR, "Failed to set permissionx bit\n");
ebitmap_destroy(bitmap);
goto exit;
}
}
return SEPOL_OK;
exit:
return rc;
}
static int __cil_expr_to_bitmap_helper(struct cil_list_item *curr, enum cil_flavor flavor, ebitmap_t *bitmap, int max, struct cil_db *db)
{
int rc = SEPOL_ERR;
@ -830,6 +1008,9 @@ static int __cil_expr_to_bitmap_helper(struct cil_list_item *curr, enum cil_flav
case CIL_ROLE:
rc = __cil_role_to_bitmap(curr->data, bitmap, db);
break;
case CIL_USER:
rc = __cil_user_to_bitmap(curr->data, bitmap, db);
break;
case CIL_PERM:
rc = __cil_perm_to_bitmap(curr->data, bitmap, db);
break;
@ -846,6 +1027,10 @@ static int __cil_expr_to_bitmap_helper(struct cil_list_item *curr, enum cil_flav
if (rc != SEPOL_OK) {
ebitmap_destroy(bitmap);
}
} else if (flavor == CIL_PERMISSIONX) {
// permissionx expressions aren't resolved into anything, so curr->flavor
// is just a CIL_STRING, not a CIL_DATUM, so just check on flavor for those
rc = __cil_permx_to_bitmap(curr->data, bitmap, db);
}
return rc;
@ -878,18 +1063,27 @@ static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max,
goto exit;
}
} else if (op == CIL_RANGE) {
if (flavor != CIL_CAT) {
cil_log(CIL_INFO, "Range operation only supported for categories\n");
if (flavor == CIL_CAT) {
ebitmap_init(&tmp);
rc = __cil_cat_expr_range_to_bitmap_helper(curr->next, curr->next->next, &tmp);
if (rc != SEPOL_OK) {
cil_log(CIL_INFO, "Failed to expand category range\n");
ebitmap_destroy(&tmp);
goto exit;
}
} else if (flavor == CIL_PERMISSIONX) {
ebitmap_init(&tmp);
rc = __cil_permissionx_expr_range_to_bitmap_helper(curr->next, curr->next->next, &tmp);
if (rc != SEPOL_OK) {
cil_log(CIL_INFO, "Failed to expand category range\n");
ebitmap_destroy(&tmp);
goto exit;
}
} else {
cil_log(CIL_INFO, "Range operation only supported for categories permissionx\n");
rc = SEPOL_ERR;
goto exit;
}
ebitmap_init(&tmp);
rc = __cil_expr_range_to_bitmap_helper(curr->next, curr->next->next, &tmp);
if (rc != SEPOL_OK) {
cil_log(CIL_INFO, "Failed to expand category range\n");
ebitmap_destroy(&tmp);
goto exit;
}
} else {
rc = __cil_expr_to_bitmap_helper(curr->next, flavor, &b1, max, db);
if (rc != SEPOL_OK) {
@ -1025,6 +1219,30 @@ static int __cil_post_db_attr_helper(struct cil_tree_node *node, __attribute__((
}
break;
}
case CIL_AVRULEX: {
struct cil_avrulex *rule = node->data;
if (rule->permx_str == NULL) {
rc = __evaluate_permissionx_expression(rule->permx, db);
if (rc != SEPOL_OK) goto exit;
}
break;
}
case CIL_PERMISSIONX: {
struct cil_permissionx *permx = node->data;
rc = __evaluate_permissionx_expression(permx, db);
if (rc != SEPOL_OK) goto exit;
break;
}
case CIL_USERATTRIBUTE: {
struct cil_userattribute *attr = node->data;
if (attr->users == NULL) {
rc = __evaluate_user_expression(attr, db);
if (rc != SEPOL_OK) {
goto exit;
}
}
break;
}
default:
break;
}
@ -1130,6 +1348,102 @@ exit:
return rc;
}
static int __cil_user_assign_roles(struct cil_user *user, struct cil_symtab_datum *datum)
{
struct cil_tree_node *node = datum->nodes->head->data;
struct cil_role *role = NULL;
struct cil_roleattribute *attr = NULL;
if (user->roles == NULL) {
user->roles = cil_malloc(sizeof(*user->roles));
ebitmap_init(user->roles);
}
if (node->flavor == CIL_ROLE) {
role = (struct cil_role *)datum;
if (ebitmap_set_bit(user->roles, role->value, 1)) {
cil_log(CIL_INFO, "Failed to set bit in user roles bitmap\n");
goto exit;
}
} else if (node->flavor == CIL_ROLEATTRIBUTE) {
attr = (struct cil_roleattribute *)datum;
ebitmap_union(user->roles, attr->roles);
}
return SEPOL_OK;
exit:
return SEPOL_ERR;
}
static int __cil_post_db_userrole_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
{
int rc = SEPOL_ERR;
struct cil_db *db = extra_args;
struct cil_block *blk = NULL;
struct cil_userrole *userrole = NULL;
struct cil_symtab_datum *user_datum = NULL;
struct cil_symtab_datum *role_datum = NULL;
struct cil_tree_node *user_node = NULL;
struct cil_userattribute *u_attr = NULL;
unsigned int i;
struct cil_user *user = NULL;
ebitmap_node_t *unode = NULL;
switch (node->flavor) {
case CIL_BLOCK: {
blk = node->data;
if (blk->is_abstract == CIL_TRUE) {
*finished = CIL_TREE_SKIP_HEAD;
}
break;
}
case CIL_MACRO: {
*finished = CIL_TREE_SKIP_HEAD;
break;
}
case CIL_USERROLE: {
userrole = node->data;
user_datum = userrole->user;
role_datum = userrole->role;
user_node = user_datum->nodes->head->data;
if (user_node->flavor == CIL_USERATTRIBUTE) {
u_attr = userrole->user;
ebitmap_for_each_bit(u_attr->users, unode, i) {
if (!ebitmap_get_bit(u_attr->users, i)) {
continue;
}
user = db->val_to_user[i];
rc = __cil_user_assign_roles(user, role_datum);
if (rc != SEPOL_OK) {
goto exit;
}
}
} else {
user = userrole->user;
rc = __cil_user_assign_roles(user, role_datum);
if (rc != SEPOL_OK) {
goto exit;
}
}
break;
}
default:
break;
}
return SEPOL_OK;
exit:
cil_log(CIL_INFO, "cil_post_db_userrole_helper failed\n");
return rc;
}
static int __evaluate_level_expression(struct cil_level *level, struct cil_db *db)
{
if (level->cats != NULL) {
@ -1601,6 +1915,12 @@ static int cil_post_db(struct cil_db *db)
goto exit;
}
rc = cil_tree_walk(db->ast->root, __cil_post_db_userrole_helper, NULL, NULL, db);
if (rc != SEPOL_OK) {
cil_log(CIL_INFO, "Failed during userrole association\n");
goto exit;
}
rc = cil_tree_walk(db->ast->root, __cil_post_db_classperms_helper, NULL, NULL, db);
if (rc != SEPOL_OK) {
cil_log(CIL_INFO, "Failed to evaluate class mapping permissions expressions\n");

View File

@ -99,7 +99,32 @@ static void cil_reset_user(struct cil_user *user)
user->bounds = NULL;
user->dftlevel = NULL;
user->range = NULL;
cil_list_destroy(&user->roles, CIL_FALSE);
}
static void cil_reset_userattr(struct cil_userattribute *attr)
{
struct cil_list_item *expr = NULL;
struct cil_list_item *next = NULL;
/* during a re-resolve, we need to reset the lists of expression stacks associated with this attribute from a userattribute statement */
if (attr->expr_list != NULL) {
/* we don't want to destroy the expression stacks (cil_list) inside
* this list cil_list_destroy destroys sublists, so we need to do it
* manually */
expr = attr->expr_list->head;
while (expr != NULL) {
next = expr->next;
cil_list_item_destroy(&expr, CIL_FALSE);
expr = next;
}
free(attr->expr_list);
attr->expr_list = NULL;
}
}
static void cil_reset_userattributeset(struct cil_userattributeset *uas)
{
cil_list_destroy(&uas->datum_expr, CIL_FALSE);
}
static void cil_reset_selinuxuser(struct cil_selinuxuser *selinuxuser)
@ -403,6 +428,12 @@ int __cil_reset_node(struct cil_tree_node *node, __attribute__((unused)) uint32
case CIL_USER:
cil_reset_user(node->data);
break;
case CIL_USERATTRIBUTE:
cil_reset_userattr(node->data);
break;
case CIL_USERATTRIBUTESET:
cil_reset_userattributeset(node->data);
break;
case CIL_SELINUXUSERDEFAULT:
case CIL_SELINUXUSER:
cil_reset_selinuxuser(node->data);

View File

@ -51,7 +51,7 @@ struct cil_args_resolve {
struct cil_db *db;
enum cil_pass pass;
uint32_t *changed;
struct cil_tree_node *callstack;
char *last_resolved_name;
struct cil_tree_node *optstack;
struct cil_tree_node *boolif;
struct cil_tree_node *macro;
@ -319,6 +319,75 @@ exit:
return rc;
}
int cil_resolve_permissionx(struct cil_tree_node *current, struct cil_permissionx *permx, void *extra_args)
{
struct cil_symtab_datum *obj_datum = NULL;
int rc = SEPOL_ERR;
rc = cil_resolve_name(current, permx->obj_str, CIL_SYM_CLASSES, extra_args, &obj_datum);
if (rc != SEPOL_OK) {
goto exit;
}
permx->obj = (struct cil_class*)obj_datum;
return SEPOL_OK;
exit:
return rc;
}
int cil_resolve_avrulex(struct cil_tree_node *current, void *extra_args)
{
struct cil_args_resolve *args = extra_args;
struct cil_db *db = NULL;
struct cil_avrulex *rule = current->data;
struct cil_symtab_datum *src_datum = NULL;
struct cil_symtab_datum *tgt_datum = NULL;
struct cil_symtab_datum *permx_datum = NULL;
int rc = SEPOL_ERR;
if (args != NULL) {
db = args->db;
}
rc = cil_resolve_name(current, rule->src_str, CIL_SYM_TYPES, args, &src_datum);
if (rc != SEPOL_OK) {
goto exit;
}
rule->src = src_datum;
cil_type_used(src_datum);
if (rule->tgt_str == CIL_KEY_SELF) {
rule->tgt = db->selftype;
} else {
rc = cil_resolve_name(current, rule->tgt_str, CIL_SYM_TYPES, args, &tgt_datum);
if (rc != SEPOL_OK) {
goto exit;
}
rule->tgt = tgt_datum;
cil_type_used(tgt_datum);
}
if (rule->permx_str != NULL) {
rc = cil_resolve_name(current, rule->permx_str, CIL_SYM_PERMX, args, &permx_datum);
if (rc != SEPOL_OK) {
goto exit;
}
rule->permx = (struct cil_permissionx*)permx_datum;
} else {
rc = cil_resolve_permissionx(current, rule->permx, extra_args);
if (rc != SEPOL_OK) {
goto exit;
}
}
return SEPOL_OK;
exit:
return rc;
}
int cil_resolve_type_rule(struct cil_tree_node *current, void *extra_args)
{
struct cil_type_rule *rule = current->data;
@ -750,12 +819,6 @@ int cil_resolve_userrole(struct cil_tree_node *current, void *extra_args)
}
userrole->role = role_datum;
if (userrole->user->roles == NULL) {
cil_list_init(&userrole->user->roles, CIL_LIST_ITEM);
}
cil_list_append(userrole->user->roles, CIL_ROLE, userrole->role);
return SEPOL_OK;
exit:
@ -768,12 +831,22 @@ int cil_resolve_userlevel(struct cil_tree_node *current, void *extra_args)
struct cil_symtab_datum *user_datum = NULL;
struct cil_symtab_datum *lvl_datum = NULL;
struct cil_user *user = NULL;
struct cil_tree_node *user_node = NULL;
int rc = SEPOL_ERR;
rc = cil_resolve_name(current, usrlvl->user_str, CIL_SYM_USERS, extra_args, &user_datum);
if (rc != SEPOL_OK) {
goto exit;
}
user_node = user_datum->nodes->head->data;
if (user_node->flavor != CIL_USER) {
cil_log(CIL_ERR, "Userlevel must be a user\n");
rc = SEPOL_ERR;
goto exit;
}
user = (struct cil_user*)user_datum;
if (usrlvl->level_str != NULL) {
@ -811,12 +884,22 @@ int cil_resolve_userrange(struct cil_tree_node *current, void *extra_args)
struct cil_symtab_datum *user_datum = NULL;
struct cil_symtab_datum *range_datum = NULL;
struct cil_user *user = NULL;
struct cil_tree_node *user_node = NULL;
int rc = SEPOL_ERR;
rc = cil_resolve_name(current, userrange->user_str, CIL_SYM_USERS, extra_args, &user_datum);
if (rc != SEPOL_OK) {
goto exit;
}
user_node = user_datum->nodes->head->data;
if (user_node->flavor != CIL_USER) {
cil_log(CIL_ERR, "Userrange must be a user: %s\n", user_datum->fqn);
rc = SEPOL_ERR;
goto exit;
}
user = (struct cil_user*)user_datum;
if (userrange->range_str != NULL) {
@ -852,12 +935,22 @@ int cil_resolve_userprefix(struct cil_tree_node *current, void *extra_args)
{
struct cil_userprefix *userprefix = current->data;
struct cil_symtab_datum *user_datum = NULL;
struct cil_tree_node *user_node = NULL;
int rc = SEPOL_ERR;
rc = cil_resolve_name(current, userprefix->user_str, CIL_SYM_USERS, extra_args, &user_datum);
if (rc != SEPOL_OK) {
goto exit;
}
user_node = user_datum->nodes->head->data;
if (user_node->flavor != CIL_USER) {
cil_log(CIL_ERR, "Userprefix must be a user: %s\n", user_datum->fqn);
rc = SEPOL_ERR;
goto exit;
}
userprefix->user = (struct cil_user*)user_datum;
exit:
@ -869,18 +962,27 @@ int cil_resolve_selinuxuser(struct cil_tree_node *current, void *extra_args)
struct cil_selinuxuser *selinuxuser = current->data;
struct cil_symtab_datum *user_datum = NULL;
struct cil_symtab_datum *lvlrange_datum = NULL;
struct cil_tree_node *user_node = NULL;
int rc = SEPOL_ERR;
rc = cil_resolve_name(current, selinuxuser->user_str, CIL_SYM_USERS, extra_args, &user_datum);
if (rc != SEPOL_OK) {
goto exit;
}
user_node = user_datum->nodes->head->data;
if (user_node->flavor != CIL_USER) {
cil_log(CIL_ERR, "Selinuxuser must be a user: %s\n", user_datum->fqn);
rc = SEPOL_ERR;
goto exit;
}
selinuxuser->user = (struct cil_user*)user_datum;
if (selinuxuser->range_str != NULL) {
rc = cil_resolve_name(current, selinuxuser->range_str, CIL_SYM_LEVELRANGES, extra_args, &lvlrange_datum);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Unable to resolve name: %s\n", selinuxuser->range_str);
goto exit;
}
selinuxuser->range = (struct cil_levelrange*)lvlrange_datum;
@ -1455,7 +1557,6 @@ int cil_resolve_cats(struct cil_tree_node *current, struct cil_cats *cats, void
rc = cil_resolve_expr(CIL_CATSET, cats->str_expr, &cats->datum_expr, current, extra_args);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR,"Unable to resolve categories\n");
goto exit;
}
@ -1647,34 +1748,48 @@ int cil_resolve_context(struct cil_tree_node *current, struct cil_context *conte
struct cil_symtab_datum *user_datum = NULL;
struct cil_symtab_datum *role_datum = NULL;
struct cil_symtab_datum *type_datum = NULL;
struct cil_tree_node *type_node = NULL;
struct cil_tree_node *node = NULL;
struct cil_symtab_datum *lvlrange_datum = NULL;
int rc = SEPOL_ERR;
rc = cil_resolve_name(current, context->user_str, CIL_SYM_USERS, extra_args, &user_datum);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Unable to resolve name: %s\n", context->user_str);
goto exit;
}
node = user_datum->nodes->head->data;
if (node->flavor != CIL_USER) {
cil_log(CIL_ERR, "Context user must be a user: %s\n", user_datum->fqn);
rc = SEPOL_ERR;
goto exit;
}
context->user = (struct cil_user*)user_datum;
rc = cil_resolve_name(current, context->role_str, CIL_SYM_ROLES, extra_args, &role_datum);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Unable to resolve name: %s\n", context->role_str);
goto exit;
}
node = role_datum->nodes->head->data;
if (node->flavor != CIL_ROLE) {
rc = SEPOL_ERR;
cil_log(CIL_ERR, "Context role not a role: %s\n", role_datum->fqn);
goto exit;
}
context->role = (struct cil_role*)role_datum;
rc = cil_resolve_name(current, context->type_str, CIL_SYM_TYPES, extra_args, &type_datum);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Unable to resolve name: %s\n", context->type_str);
goto exit;
}
type_node = type_datum->nodes->head->data;
node = type_datum->nodes->head->data;
if (type_node->flavor != CIL_TYPE && type_node->flavor != CIL_TYPEALIAS) {
if (node->flavor != CIL_TYPE && node->flavor != CIL_TYPEALIAS) {
rc = SEPOL_ERR;
cil_log(CIL_ERR, "Type not a type or type alias\n");
goto exit;
@ -1684,7 +1799,6 @@ int cil_resolve_context(struct cil_tree_node *current, struct cil_context *conte
if (context->range_str != NULL) {
rc = cil_resolve_name(current, context->range_str, CIL_SYM_LEVELRANGES, extra_args, &lvlrange_datum);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Unable to resolve name: %s\n", context->range_str);
goto exit;
}
context->range = (struct cil_levelrange*)lvlrange_datum;
@ -2095,6 +2209,73 @@ exit:
return rc;
}
void cil_print_recursive_blockinherit(struct cil_tree_node *bi_node, struct cil_tree_node *terminating_node)
{
struct cil_list *trace = NULL;
struct cil_list_item *item = NULL;
struct cil_tree_node *curr = NULL;
cil_list_init(&trace, CIL_NODE);
for (curr = bi_node; curr != terminating_node; curr = curr->parent) {
if (curr->flavor == CIL_BLOCK) {
cil_list_prepend(trace, CIL_NODE, curr);
} else {
if (curr != bi_node) {
cil_list_prepend(trace, CIL_NODE, NODE(((struct cil_blockinherit *)curr->data)->block));
}
cil_list_prepend(trace, CIL_NODE, curr);
}
}
cil_list_prepend(trace, CIL_NODE, terminating_node);
cil_list_for_each(item, trace) {
curr = item->data;
cil_log(CIL_ERR, " %s:%d: ", curr->path, curr->line);
if (curr->flavor == CIL_BLOCK) {
cil_log(CIL_ERR, "block %s\n", DATUM(curr->data)->name);
} else {
cil_log(CIL_ERR, "blockinherit %s\n", ((struct cil_blockinherit *)curr->data)->block_str);
}
}
cil_list_destroy(&trace, CIL_FALSE);
}
int cil_check_recursive_blockinherit(struct cil_tree_node *bi_node)
{
struct cil_tree_node *curr = NULL;
struct cil_blockinherit *bi = NULL;
struct cil_block *block = NULL;
int rc = SEPOL_ERR;
bi = bi_node->data;
for (curr = bi_node->parent; curr != NULL; curr = curr->parent) {
if (curr->flavor != CIL_BLOCK) {
continue;
}
block = curr->data;
if (block != bi->block) {
continue;
}
cil_log(CIL_ERR, "Recursive blockinherit found:\n");
cil_print_recursive_blockinherit(bi_node, curr);
rc = SEPOL_ERR;
goto exit;
}
rc = SEPOL_OK;
exit:
return rc;
}
int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_args)
{
struct cil_block *block = current->data;
@ -2118,6 +2299,11 @@ int cil_resolve_blockinherit_copy(struct cil_tree_node *current, void *extra_arg
}
cil_list_for_each(item, block->bi_nodes) {
rc = cil_check_recursive_blockinherit(item->data);
if (rc != SEPOL_OK) {
goto exit;
}
rc = cil_copy_ast(db, current, item->data);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to copy block contents into blockinherit\n");
@ -2351,7 +2537,6 @@ int cil_resolve_default(struct cil_tree_node *current, void *extra_args)
cil_list_for_each(curr, def->class_strs) {
rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to resolve class %s in %s\n", (char *)curr->data, cil_node_to_string(current));
goto exit;
}
cil_list_append(def->class_datums, CIL_CLASS, datum);
@ -2375,7 +2560,6 @@ int cil_resolve_defaultrange(struct cil_tree_node *current, void *extra_args)
cil_list_for_each(curr, def->class_strs) {
rc = cil_resolve_name(current, (char *)curr->data, CIL_SYM_CLASSES, extra_args, &datum);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to resolve class %s in defaultrange\n", (char *)curr->data);
goto exit;
}
cil_list_append(def->class_datums, CIL_CLASS, datum);
@ -2387,6 +2571,80 @@ exit:
return rc;
}
void cil_print_recursive_call(struct cil_tree_node *call_node, struct cil_tree_node *terminating_node)
{
struct cil_list *trace = NULL;
struct cil_list_item * item = NULL;
struct cil_tree_node *curr = NULL;
cil_list_init(&trace, CIL_NODE);
for (curr = call_node; curr != terminating_node; curr = curr->parent) {
if (curr->flavor == CIL_CALL) {
if (curr != call_node) {
cil_list_prepend(trace, CIL_NODE, NODE(((struct cil_call *)curr->data)->macro));
}
cil_list_prepend(trace, CIL_NODE, curr);
}
}
if (terminating_node->flavor == CIL_MACRO) {
cil_list_prepend(trace, CIL_NODE, terminating_node);
} else {
cil_list_prepend(trace, CIL_NODE, NODE(((struct cil_call *)terminating_node->data)->macro));
}
cil_list_for_each(item, trace) {
curr = item->data;
cil_log(CIL_ERR, " %s:%d: ", curr->path, curr->line);
if (curr->flavor == CIL_MACRO) {
cil_log(CIL_ERR, "macro %s\n", DATUM(curr->data)->name);
} else {
cil_log(CIL_ERR, "call %s\n", ((struct cil_call *)curr->data)->macro_str);
}
}
cil_list_destroy(&trace, CIL_FALSE);
}
int cil_check_recursive_call(struct cil_tree_node *call_node, struct cil_tree_node *macro_node)
{
struct cil_tree_node *curr = NULL;
struct cil_call * call = NULL;
int rc = SEPOL_ERR;
for (curr = call_node; curr != NULL; curr = curr->parent) {
if (curr->flavor == CIL_CALL) {
if (curr == call_node) {
continue;
}
call = curr->data;
if (call->macro != macro_node->data) {
continue;
}
} else if (curr->flavor == CIL_MACRO) {
if (curr != macro_node) {
rc = SEPOL_OK;
goto exit;
}
} else {
continue;
}
cil_log(CIL_ERR, "Recursive macro call found:\n");
cil_print_recursive_call(call_node, curr);
rc = SEPOL_ERR;
goto exit;
}
rc = SEPOL_OK;
exit:
return rc;
}
int cil_resolve_call1(struct cil_tree_node *current, void *extra_args)
{
struct cil_call *new_call = current->data;
@ -2408,7 +2666,7 @@ int cil_resolve_call1(struct cil_tree_node *current, void *extra_args)
macro_node = macro_datum->nodes->head->data;
if (macro_node->flavor != CIL_MACRO) {
printf("Failed to resolve macro %s\n", new_call->macro_str);
printf("Failed to resolve %s to a macro\n", new_call->macro_str);
rc = SEPOL_ERR;
goto exit;
}
@ -2623,6 +2881,12 @@ int cil_resolve_call1(struct cil_tree_node *current, void *extra_args)
if (new_call->copied == 0) {
new_call->copied = 1;
rc = cil_check_recursive_call(current, macro_node);
if (rc != SEPOL_OK) {
goto exit;
}
rc = cil_copy_ast(db, macro_node, current);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to copy macro, rc: %d\n", rc);
@ -2974,6 +3238,48 @@ exit:
return rc;
}
int cil_resolve_userattributeset(struct cil_tree_node *current, void *extra_args)
{
int rc = SEPOL_ERR;
struct cil_userattributeset *attrusers = current->data;
struct cil_symtab_datum *attr_datum = NULL;
struct cil_tree_node *attr_node = NULL;
struct cil_userattribute *attr = NULL;
rc = cil_resolve_name(current, attrusers->attr_str, CIL_SYM_USERS, extra_args, &attr_datum);
if (rc != SEPOL_OK) {
goto exit;
}
attr_node = attr_datum->nodes->head->data;
if (attr_node->flavor != CIL_USERATTRIBUTE) {
rc = SEPOL_ERR;
cil_log(CIL_ERR, "Attribute user not an attribute\n");
goto exit;
}
attr = (struct cil_userattribute*)attr_datum;
rc = cil_resolve_expr(CIL_USERATTRIBUTESET, attrusers->str_expr, &attrusers->datum_expr, current, extra_args);
if (rc != SEPOL_OK) {
goto exit;
}
rc = cil_verify_no_self_reference(attr_datum, attrusers->datum_expr);
if (rc != SEPOL_OK) {
goto exit;
}
if (attr->expr_list == NULL) {
cil_list_init(&attr->expr_list, CIL_USERATTRIBUTE);
}
cil_list_append(attr->expr_list, CIL_LIST, attrusers->datum_expr);
return SEPOL_OK;
exit:
return rc;
}
int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
{
@ -3128,6 +3434,12 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
case CIL_AVRULE:
rc = cil_resolve_avrule(node, args);
break;
case CIL_AVRULEX:
rc = cil_resolve_avrulex(node, args);
break;
case CIL_PERMISSIONX:
rc = cil_resolve_permissionx(node, (struct cil_permissionx*)node->data, args);
break;
case CIL_TYPE_RULE:
rc = cil_resolve_type_rule(node, args);
break;
@ -3228,6 +3540,9 @@ int __cil_resolve_ast_node(struct cil_tree_node *node, void *extra_args)
case CIL_DEFAULTRANGE:
rc = cil_resolve_defaultrange(node, args);
break;
case CIL_USERATTRIBUTESET:
rc = cil_resolve_userattributeset(node, args);
break;
default:
break;
}
@ -3250,6 +3565,7 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, __attribute__((unu
struct cil_tree_node *optstack = args->optstack;
struct cil_tree_node *boolif = args->boolif;
struct cil_tree_node *blockstack = args->blockstack;
struct cil_tree_node *macro = args->macro;
if (node == NULL) {
goto exit;
@ -3272,6 +3588,17 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, __attribute__((unu
}
}
if (macro != NULL) {
if (node->flavor == CIL_BLOCKINHERIT ||
node->flavor == CIL_BLOCK ||
node->flavor == CIL_BLOCKABSTRACT ||
node->flavor == CIL_MACRO) {
cil_log(CIL_ERR, "%s statement is not allowed in macros (%s:%d)\n", cil_node_to_string(node), node->path, node->line);
rc = SEPOL_ERR;
goto exit;
}
}
if (boolif != NULL) {
if (!(node->flavor == CIL_CONDBLOCK ||
node->flavor == CIL_AVRULE ||
@ -3304,14 +3631,22 @@ int __cil_resolve_ast_node_helper(struct cil_tree_node *node, __attribute__((unu
}
rc = __cil_resolve_ast_node(node, extra_args);
if (rc == SEPOL_ENOENT && optstack != NULL) {
struct cil_optional *opt = (struct cil_optional *)optstack->data;
cil_log(CIL_WARN, "Disabling optional %s at %d of %s\n", opt->datum.name, node->parent->line, node->parent->path);
/* disable an optional if something failed to resolve */
opt->enabled = CIL_FALSE;
rc = SEPOL_OK;
} else if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to resolve %s statement at %d of %s\n", cil_node_to_string(node), node->line, node->path);
if (rc == SEPOL_ENOENT) {
enum cil_log_level lvl = CIL_ERR;
if (optstack != NULL) {
lvl = CIL_WARN;
struct cil_optional *opt = (struct cil_optional *)optstack->data;
struct cil_tree_node *opt_node = opt->datum.nodes->head->data;
cil_log(lvl, "Disabling optional '%s' at line %d of %s: ", opt->datum.name, opt_node->line, opt_node->path);
/* disable an optional if something failed to resolve */
opt->enabled = CIL_FALSE;
rc = SEPOL_OK;
}
cil_log(lvl, "Failed to resolve '%s' in %s statement at line %d of %s\n",
args->last_resolved_name, cil_node_to_string(node), node->line, node->path);
goto exit;
}
@ -3325,7 +3660,6 @@ int __cil_resolve_ast_first_child_helper(struct cil_tree_node *current, void *ex
{
int rc = SEPOL_ERR;
struct cil_args_resolve *args = extra_args;
struct cil_tree_node *callstack = NULL;
struct cil_tree_node *optstack = NULL;
struct cil_tree_node *parent = NULL;
struct cil_tree_node *blockstack = NULL;
@ -3335,36 +3669,18 @@ int __cil_resolve_ast_first_child_helper(struct cil_tree_node *current, void *ex
goto exit;
}
callstack = args->callstack;
optstack = args->optstack;
parent = current->parent;
blockstack = args->blockstack;
if (parent->flavor == CIL_CALL || parent->flavor == CIL_OPTIONAL || parent->flavor == CIL_BLOCK) {
if (parent->flavor == CIL_OPTIONAL || parent->flavor == CIL_BLOCK) {
/* push this node onto a stack */
cil_tree_node_init(&new);
new->data = parent->data;
new->flavor = parent->flavor;
if (parent->flavor == CIL_CALL) {
if (callstack != NULL) {
struct cil_tree_node *curr = NULL;
struct cil_call *new_call = new->data;
for (curr = callstack->cl_head; curr != NULL;
curr = curr->cl_head) {
struct cil_call *curr_call = curr->data;
if (curr_call->macro == new_call->macro) {
cil_log(CIL_ERR, "Recursive macro call found\n");
rc = SEPOL_ERR;
goto exit;
}
}
callstack->parent = new;
new->cl_head = callstack;
}
args->callstack = new;
} else if (parent->flavor == CIL_OPTIONAL) {
if (parent->flavor == CIL_OPTIONAL) {
if (optstack != NULL) {
optstack->parent = new;
new->cl_head = optstack;
@ -3403,15 +3719,7 @@ int __cil_resolve_ast_last_child_helper(struct cil_tree_node *current, void *ext
parent = current->parent;
if (parent->flavor == CIL_CALL) {
/* pop off the stack */
struct cil_tree_node *callstack = args->callstack;
args->callstack = callstack->cl_head;
if (callstack->cl_head) {
callstack->cl_head->parent = NULL;
}
free(callstack);
} else if (parent->flavor == CIL_MACRO) {
if (parent->flavor == CIL_MACRO) {
args->macro = NULL;
} else if (parent->flavor == CIL_OPTIONAL) {
struct cil_tree_node *optstack;
@ -3460,7 +3768,7 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
extra_args.db = db;
extra_args.pass = pass;
extra_args.changed = &changed;
extra_args.callstack = NULL;
extra_args.last_resolved_name = NULL;
extra_args.optstack = NULL;
extra_args.boolif= NULL;
extra_args.macro = NULL;
@ -3552,12 +3860,6 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
/* reset the arguments */
changed = 0;
while (extra_args.callstack != NULL) {
struct cil_tree_node *curr = extra_args.callstack;
struct cil_tree_node *next = curr->cl_head;
free(curr);
extra_args.callstack = next;
}
while (extra_args.optstack != NULL) {
struct cil_tree_node *curr = extra_args.optstack;
struct cil_tree_node *next = curr->cl_head;
@ -3579,6 +3881,12 @@ int cil_resolve_ast(struct cil_db *db, struct cil_tree_node *current)
rc = SEPOL_OK;
exit:
__cil_ordered_lists_destroy(&extra_args.sidorder_lists);
__cil_ordered_lists_destroy(&extra_args.classorder_lists);
__cil_ordered_lists_destroy(&extra_args.catorder_lists);
__cil_ordered_lists_destroy(&extra_args.sensitivityorder_lists);
cil_list_destroy(&extra_args.in_list, CIL_FALSE);
return rc;
}
@ -3734,8 +4042,6 @@ int cil_resolve_name(struct cil_tree_node *ast_node, char *name, enum cil_sym_in
exit:
if (rc != SEPOL_OK) {
*datum = NULL;
cil_log(CIL_WARN, "Failed to resolve %s in %s statement on line %d of %s\n",
name, cil_node_to_string(ast_node), ast_node->line, ast_node->path);
}
if (*datum != NULL) {
@ -3752,5 +4058,7 @@ exit:
}
}
args->last_resolved_name = name;
return rc;
}

View File

@ -54,6 +54,7 @@ int cil_resolve_userlevel(struct cil_tree_node *current, void *extra_args);
int cil_resolve_userrange(struct cil_tree_node *current, void *extra_args);
int cil_resolve_userbounds(struct cil_tree_node *current, void *extra_args);
int cil_resolve_userprefix(struct cil_tree_node *current, void *extra_args);
int cil_resolve_userattributeset(struct cil_tree_node *current, void *extra_args);
int cil_resolve_selinuxuser(struct cil_tree_node *current, void *extra_args);
int cil_resolve_roletype(struct cil_tree_node *current, void *extra_args);
int cil_resolve_roletransition(struct cil_tree_node *current, void *extra_args);

View File

@ -640,15 +640,18 @@ void cil_tree_print_node(struct cil_tree_node *node)
case CIL_USERROLE: {
struct cil_userrole *userrole = node->data;
cil_log(CIL_INFO, "USERROLE:");
struct cil_symtab_datum *datum = NULL;
if (userrole->user != NULL) {
cil_log(CIL_INFO, " %s", userrole->user->datum.name);
datum = userrole->user;
cil_log(CIL_INFO, " %s", datum->name);
} else if (userrole->user_str != NULL) {
cil_log(CIL_INFO, " %s", userrole->user_str);
}
if (userrole->role != NULL) {
cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)userrole->role)->name);
datum = userrole->role;
cil_log(CIL_INFO, " %s", datum->name);
} else if (userrole->role_str != NULL) {
cil_log(CIL_INFO, " %s", userrole->role_str);
}
@ -785,6 +788,21 @@ void cil_tree_print_node(struct cil_tree_node *node)
cil_log(CIL_INFO, "ROLEATTRIBUTE: %s\n", attr->datum.name);
return;
}
case CIL_USERATTRIBUTESET: {
struct cil_userattributeset *attr = node->data;
cil_log(CIL_INFO, "(USERATTRIBUTESET %s ", attr->attr_str);
cil_tree_print_expr(attr->datum_expr, attr->str_expr);
cil_log(CIL_INFO, "\n");
return;
}
case CIL_USERATTRIBUTE: {
struct cil_userattribute *attr = node->data;
cil_log(CIL_INFO, "USERATTRIBUTE: %s\n", attr->datum.name);
return;
}
case CIL_ROLEBOUNDS: {
struct cil_bounds *bnds = node->data;
cil_log(CIL_INFO, "ROLEBOUNDS: role: %s, bounds: %s\n", bnds->parent_str, bnds->child_str);

View File

@ -179,8 +179,8 @@ int cil_verify_expr_syntax(struct cil_tree_node *current, enum cil_flavor op, en
syntax_len = 2;
break;
case CIL_RANGE:
if (expr_flavor != CIL_CAT) {
cil_log(CIL_ERR,"Operator (%s) only valid for catset expression\n", (char*)current->data);
if (expr_flavor != CIL_CAT && expr_flavor != CIL_PERMISSIONX) {
cil_log(CIL_ERR,"Operator (%s) only valid for catset and permissionx expression\n", (char*)current->data);
goto exit;
}
syntax[1] = CIL_SYN_STRING;
@ -737,16 +737,8 @@ int __cil_verify_context(struct cil_db *db, struct cil_context *ctx)
int found = CIL_FALSE;
if (user->roles != NULL) {
cil_list_for_each(curr, user->roles) {
struct cil_role *userrole = curr->data;
if (userrole == role) {
break;
}
}
if (curr == NULL) {
cil_log(CIL_ERR, "Role %s is invalid for user %s\n",
ctx->role_str, ctx->user_str);
if (!ebitmap_get_bit(user->roles, role->value)) {
cil_log(CIL_ERR, "Role %s is invalid for user %s\n", ctx->role_str, ctx->user_str);
rc = SEPOL_ERR;
goto exit;
}
@ -1494,13 +1486,22 @@ static int __cil_verify_classpermission(struct cil_tree_node *node)
int rc = SEPOL_ERR;
struct cil_classpermission *cp = node->data;
if (cp->classperms == NULL) {
cil_log(CIL_ERR, "Classpermission %s does not have a classpermissionset at line %d of %s\n", cp->datum.name, node->line, node->path);
rc = SEPOL_ERR;
goto exit;
}
rc = __cil_verify_classperms(cp->classperms, &cp->datum);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Found circular class permissions involving the set %s at line %d of %s\n",cp->datum.name, node->line, node->path);
return rc;
goto exit;
}
return SEPOL_OK;
rc = SEPOL_OK;
exit:
return rc;
}
struct cil_verify_map_args {
@ -1515,12 +1516,20 @@ static int __verify_map_perm_classperms(__attribute__((unused)) hashtab_key_t k,
struct cil_verify_map_args *map_args = args;
struct cil_perm *cmp = (struct cil_perm *)d;
if (cmp->classperms == NULL) {
cil_log(CIL_ERR, "Map class %s does not have a classmapping for %s at line %d of %s\n", map_args->class->datum.name, cmp->datum.name, map_args->node->line, map_args->node->path);
map_args->rc = SEPOL_ERR;
goto exit;
}
rc = __cil_verify_classperms(cmp->classperms, &cmp->datum);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Found circular class permissions involving the map class %s and permission %s at line %d of %s\n", map_args->class->datum.name, cmp->datum.name, map_args->node->line, map_args->node->path);
map_args->rc = SEPOL_ERR;
goto exit;
}
exit:
return SEPOL_OK;
}

View File

@ -59,28 +59,29 @@ 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_NEVERALLOW 0x0800
#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

@ -86,6 +86,7 @@ extern unsigned int ebitmap_cardinality(ebitmap_t *e1);
extern int ebitmap_hamming_distance(ebitmap_t * e1, ebitmap_t * e2);
extern int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src);
extern int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2);
extern int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2);
extern int ebitmap_get_bit(const ebitmap_t * e, unsigned int bit);
extern int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value);
extern void ebitmap_destroy(ebitmap_t * e);

View File

@ -25,11 +25,22 @@
#ifndef _SEPOL_POLICYDB_HIERARCHY_H_
#define _SEPOL_POLICYDB_HIERARCHY_H_
#include <sepol/policydb/avtab.h>
#include <sepol/policydb/policydb.h>
#include <sys/cdefs.h>
__BEGIN_DECLS
extern int hierarchy_add_bounds(sepol_handle_t *handle, policydb_t *p);
extern void bounds_destroy_bad(avtab_ptr_t cur);
extern int bounds_check_type(sepol_handle_t *handle, policydb_t *p, uint32_t child,
uint32_t parent, avtab_ptr_t *bad, int *numbad);
extern int bounds_check_users(sepol_handle_t *handle, policydb_t *p);
extern int bounds_check_roles(sepol_handle_t *handle, policydb_t *p);
extern int bounds_check_types(sepol_handle_t *handle, policydb_t *p);
extern int hierarchy_check_constraints(sepol_handle_t * handle, policydb_t * p);
__END_DECLS

View File

@ -241,11 +241,19 @@ 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 */
uint32_t perms[8];
} av_operations_t;
#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)))
#define EXTENDED_PERMS_LEN 8
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[EXTENDED_PERMS_LEN];
} av_extended_perms_t;
typedef struct avrule {
/* these typedefs are almost exactly the same as those in avtab.h - they are
@ -260,24 +268,19 @@ 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_NEVERALLOW 0x0800
#define AVRULE_XPERMS (AVRULE_XPERMS_ALLOWED | AVRULE_XPERMS_AUDITALLOW | \
AVRULE_XPERMS_DONTAUDIT | AVRULE_XPERMS_NEVERALLOW)
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) */
@ -652,7 +655,7 @@ extern void level_datum_init(level_datum_t * x);
extern void level_datum_destroy(level_datum_t * x);
extern void cat_datum_init(cat_datum_t * x);
extern void cat_datum_destroy(cat_datum_t * x);
extern int check_assertion(policydb_t *p, avrule_t *avrule);
extern int check_assertions(sepol_handle_t * handle,
policydb_t * p, avrule_t * avrules);
@ -709,11 +712,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

@ -32,5 +32,13 @@ extern int add_i_to_a(uint32_t i, uint32_t * cnt, uint32_t ** a);
extern char *sepol_av_to_string(policydb_t * policydbp, uint32_t tclass,
sepol_access_vector_t av);
char *sepol_extended_perms_to_string(avtab_extended_perms_t *xperms);
/*
* The tokenize function may be used to
* replace sscanf
*/
extern int tokenize(char *line_buf, char delim, int num_args, ...);
__END_DECLS
#endif

View File

@ -1,8 +1,8 @@
/* Authors: Joshua Brindle <jbrindle@tresys.com>
*
* Assertion checker for avtab entries, taken from
*
* Assertion checker for avtab entries, taken from
* checkpolicy.c by Stephen Smalley <sds@tycho.nsa.gov>
*
*
* Copyright (C) 2005 Tresys Technology, LLC
*
* This library is free software; you can redistribute it and/or
@ -25,13 +25,20 @@
#include <sepol/policydb/expand.h>
#include <sepol/policydb/util.h>
#include "private.h"
#include "debug.h"
static void report_failure(sepol_handle_t *handle, policydb_t *p,
const avrule_t * avrule,
struct avtab_match_args {
sepol_handle_t *handle;
policydb_t *p;
avrule_t *avrule;
avtab_t *avtab;
unsigned long errors;
};
static void report_failure(sepol_handle_t *handle, policydb_t *p, const avrule_t *avrule,
unsigned int stype, unsigned int ttype,
const class_perm_node_t *curperm,
const avtab_ptr_t node)
const class_perm_node_t *curperm, uint32_t perms)
{
if (avrule->source_filename) {
ERR(handle, "neverallow on line %lu of %s (or line %lu of policy.conf) violated by allow %s %s:%s {%s };",
@ -39,69 +46,386 @@ static void report_failure(sepol_handle_t *handle, policydb_t *p,
p->p_type_val_to_name[stype],
p->p_type_val_to_name[ttype],
p->p_class_val_to_name[curperm->tclass - 1],
sepol_av_to_string(p, curperm->tclass,
node->datum.data & curperm->data));
sepol_av_to_string(p, curperm->tclass, perms));
} else if (avrule->line) {
ERR(handle, "neverallow on line %lu violated by allow %s %s:%s {%s };",
avrule->line, p->p_type_val_to_name[stype],
p->p_type_val_to_name[ttype],
p->p_class_val_to_name[curperm->tclass - 1],
sepol_av_to_string(p, curperm->tclass,
node->datum.data & curperm->data));
sepol_av_to_string(p, curperm->tclass, perms));
} else {
ERR(handle, "neverallow violated by allow %s %s:%s {%s };",
p->p_type_val_to_name[stype],
p->p_type_val_to_name[ttype],
p->p_class_val_to_name[curperm->tclass - 1],
sepol_av_to_string(p, curperm->tclass,
node->datum.data & curperm->data));
sepol_av_to_string(p, curperm->tclass, perms));
}
}
static unsigned long check_assertion_helper(sepol_handle_t * handle,
policydb_t * p,
avtab_t * te_avtab, avtab_t * te_cond_avtab,
unsigned int stype, unsigned int ttype,
const avrule_t * avrule)
static int match_any_class_permissions(class_perm_node_t *cp, uint32_t class, uint32_t data)
{
avtab_key_t avkey;
avtab_ptr_t node;
class_perm_node_t *curperm;
unsigned long errors = 0;
for (curperm = avrule->perms; curperm != NULL; curperm = curperm->next) {
avkey.source_type = stype + 1;
avkey.target_type = ttype + 1;
avkey.target_class = curperm->tclass;
avkey.specified = AVTAB_ALLOWED;
for (node = avtab_search_node(te_avtab, &avkey);
node != NULL;
node = avtab_search_node_next(node, avkey.specified)) {
if (node->datum.data & curperm->data) {
report_failure(handle, p, avrule, stype, ttype, curperm, node);
errors++;
}
for (; cp; cp = cp->next) {
if ((cp->tclass == class) && (cp->data & data)) {
break;
}
for (node = avtab_search_node(te_cond_avtab, &avkey);
node != NULL;
node = avtab_search_node_next(node, avkey.specified)) {
if (node->datum.data & curperm->data) {
report_failure(handle, p, avrule, stype, ttype, curperm, node);
errors++;
}
if (!cp)
return 0;
return 1;
}
static int extended_permissions_and(uint32_t *perms1, uint32_t *perms2) {
size_t i;
for (i = 0; i < EXTENDED_PERMS_LEN; i++) {
if (perms1[i] & perms2[i])
return 1;
}
return 0;
}
static int check_extended_permissions(av_extended_perms_t *neverallow, avtab_extended_perms_t *allow)
{
int rc = 0;
if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION)
&& (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
if (neverallow->driver == allow->driver)
rc = extended_permissions_and(neverallow->perms, allow->perms);
} else if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION)
&& (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
rc = xperm_test(neverallow->driver, allow->perms);
} else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER)
&& (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
rc = xperm_test(allow->driver, neverallow->perms);
} else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER)
&& (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
rc = extended_permissions_and(neverallow->perms, allow->perms);
}
return rc;
}
/* Compute which allowed extended permissions violate the neverallow rule */
static void extended_permissions_violated(avtab_extended_perms_t *result,
av_extended_perms_t *neverallow,
avtab_extended_perms_t *allow)
{
size_t i;
if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION)
&& (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
result->specified = AVTAB_XPERMS_IOCTLFUNCTION;
result->driver = allow->driver;
for (i = 0; i < EXTENDED_PERMS_LEN; i++)
result->perms[i] = neverallow->perms[i] & allow->perms[i];
} else if ((neverallow->specified == AVRULE_XPERMS_IOCTLFUNCTION)
&& (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
result->specified = AVTAB_XPERMS_IOCTLFUNCTION;
result->driver = neverallow->driver;
memcpy(result->perms, neverallow->perms, sizeof(result->perms));
} else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER)
&& (allow->specified == AVTAB_XPERMS_IOCTLFUNCTION)) {
result->specified = AVTAB_XPERMS_IOCTLFUNCTION;
result->driver = allow->driver;
memcpy(result->perms, allow->perms, sizeof(result->perms));
} else if ((neverallow->specified == AVRULE_XPERMS_IOCTLDRIVER)
&& (allow->specified == AVTAB_XPERMS_IOCTLDRIVER)) {
result->specified = AVTAB_XPERMS_IOCTLDRIVER;
for (i = 0; i < EXTENDED_PERMS_LEN; i++)
result->perms[i] = neverallow->perms[i] & allow->perms[i];
}
}
/* Same scenarios of interest as check_assertion_extended_permissions */
static int report_assertion_extended_permissions(sepol_handle_t *handle,
policydb_t *p, const avrule_t *avrule,
unsigned int stype, unsigned int ttype,
const class_perm_node_t *curperm, uint32_t perms,
avtab_key_t *k, avtab_t *avtab)
{
avtab_ptr_t node;
avtab_key_t tmp_key;
avtab_extended_perms_t *xperms;
avtab_extended_perms_t error;
int rc = 1;
int ret = 0;
memcpy(&tmp_key, k, sizeof(avtab_key_t));
tmp_key.specified = AVTAB_XPERMS_ALLOWED;
for (node = avtab_search_node(avtab, &tmp_key);
node;
node = avtab_search_node_next(node, tmp_key.specified)) {
xperms = node->datum.xperms;
if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
&& (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER))
continue;
rc = check_extended_permissions(avrule->xperms, xperms);
/* failure on the extended permission check_extended_permissionss */
if (rc) {
extended_permissions_violated(&error, avrule->xperms, xperms);
ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of policy.conf) violated by\n"
"allowxperm %s %s:%s %s;",
avrule->source_line, avrule->source_filename, avrule->line,
p->p_type_val_to_name[stype],
p->p_type_val_to_name[ttype],
p->p_class_val_to_name[curperm->tclass - 1],
sepol_extended_perms_to_string(&error));
rc = 0;
ret++;
}
}
/* failure on the regular permissions */
if (rc) {
ERR(handle, "neverallowxperm on line %lu of %s (or line %lu of policy.conf) violated by\n"
"allow %s %s:%s {%s };",
avrule->source_line, avrule->source_filename, avrule->line,
p->p_type_val_to_name[stype],
p->p_type_val_to_name[ttype],
p->p_class_val_to_name[curperm->tclass - 1],
sepol_av_to_string(p, curperm->tclass, perms));
ret++;
}
return ret;
}
static int report_assertion_avtab_matches(avtab_key_t *k, avtab_datum_t *d, void *args)
{
int rc = 0;
struct avtab_match_args *a = (struct avtab_match_args *)args;
sepol_handle_t *handle = a->handle;
policydb_t *p = a->p;
avtab_t *avtab = a->avtab;
avrule_t *avrule = a->avrule;
class_perm_node_t *cp;
uint32_t perms;
ebitmap_t src_matches, tgt_matches, matches;
ebitmap_node_t *snode, *tnode;
unsigned int i, j;
if (k->specified != AVTAB_ALLOWED)
return 0;
if (!match_any_class_permissions(avrule->perms, k->target_class, d->data))
return 0;
ebitmap_init(&src_matches);
ebitmap_init(&tgt_matches);
ebitmap_init(&matches);
rc = ebitmap_and(&src_matches, &avrule->stypes.types,
&p->attr_type_map[k->source_type - 1]);
if (rc)
goto oom;
if (ebitmap_length(&src_matches) == 0)
goto exit;
if (avrule->flags == RULE_SELF) {
rc = ebitmap_and(&matches, &p->attr_type_map[k->source_type - 1], &p->attr_type_map[k->target_type - 1]);
if (rc)
goto oom;
rc = ebitmap_and(&tgt_matches, &avrule->stypes.types, &matches);
if (rc)
goto oom;
} else {
rc = ebitmap_and(&tgt_matches, &avrule->ttypes.types, &p->attr_type_map[k->target_type -1]);
if (rc)
goto oom;
}
if (ebitmap_length(&tgt_matches) == 0)
goto exit;
for (cp = avrule->perms; cp; cp = cp->next) {
perms = cp->data & d->data;
if ((cp->tclass != k->target_class) || !perms) {
continue;
}
ebitmap_for_each_bit(&src_matches, snode, i) {
if (!ebitmap_node_get_bit(snode, i))
continue;
ebitmap_for_each_bit(&tgt_matches, tnode, j) {
if (!ebitmap_node_get_bit(tnode, j))
continue;
if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) {
a->errors += report_assertion_extended_permissions(handle,p, avrule,
i, j, cp, perms, k, avtab);
} else {
a->errors++;
report_failure(handle, p, avrule, i, j, cp, perms);
}
}
}
}
goto exit;
return errors;
oom:
ERR(NULL, "Out of memory - unable to check neverallows");
exit:
ebitmap_destroy(&src_matches);
ebitmap_destroy(&tgt_matches);
ebitmap_destroy(&matches);
return rc;
}
int report_assertion_failures(sepol_handle_t *handle, policydb_t *p, avrule_t *avrule)
{
int rc;
struct avtab_match_args args;
args.handle = handle;
args.p = p;
args.avrule = avrule;
args.errors = 0;
rc = avtab_map(&p->te_avtab, report_assertion_avtab_matches, &args);
if (rc)
goto oom;
rc = avtab_map(&p->te_cond_avtab, report_assertion_avtab_matches, &args);
if (rc)
goto oom;
return args.errors;
oom:
return rc;
}
/*
* If the ioctl permission is granted in check_assertion_avtab_match for the
* source/target/class matching the current avrule neverallow, a lookup is
* performed to determine if extended permissions exist for the source/target/class.
*
* Four scenarios of interest:
* 1. PASS - the ioctl permission is not granted for this source/target/class
* This case is handled in check_assertion_avtab_match
* 2. PASS - The ioctl permission is granted AND the extended permission
* is NOT granted
* 3. FAIL - The ioctl permission is granted AND no extended permissions
* exist
* 4. FAIL - The ioctl permission is granted AND the extended permission is
* granted
*/
static int check_assertion_extended_permissions(avrule_t *avrule, avtab_t *avtab,
avtab_key_t *k)
{
avtab_ptr_t node;
avtab_key_t tmp_key;
avtab_extended_perms_t *xperms;
av_extended_perms_t *neverallow_xperms = avrule->xperms;
int rc = 1;
memcpy(&tmp_key, k, sizeof(avtab_key_t));
tmp_key.specified = AVTAB_XPERMS_ALLOWED;
for (node = avtab_search_node(avtab, &tmp_key);
node;
node = avtab_search_node_next(node, tmp_key.specified)) {
xperms = node->datum.xperms;
if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
&& (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER))
continue;
rc = check_extended_permissions(neverallow_xperms, xperms);
if (rc)
break;
}
return rc;
}
static int check_assertion_avtab_match(avtab_key_t *k, avtab_datum_t *d, void *args)
{
int rc;
struct avtab_match_args *a = (struct avtab_match_args *)args;
policydb_t *p = a->p;
avrule_t *avrule = a->avrule;
avtab_t *avtab = a->avtab;
if (k->specified != AVTAB_ALLOWED)
goto exit;
if (!match_any_class_permissions(avrule->perms, k->target_class, d->data))
goto exit;
rc = ebitmap_match_any(&avrule->stypes.types, &p->attr_type_map[k->source_type - 1]);
if (rc == 0)
goto exit;
if (avrule->flags == RULE_SELF) {
/* If the neverallow uses SELF, then it is not enough that the
* neverallow's source matches the src and tgt of the rule being checked.
* It must match the same thing in the src and tgt, so AND the source
* and target together and check for a match on the result.
*/
ebitmap_t match;
rc = ebitmap_and(&match, &p->attr_type_map[k->source_type - 1], &p->attr_type_map[k->target_type - 1] );
if (rc) {
ebitmap_destroy(&match);
goto oom;
}
rc = ebitmap_match_any(&avrule->stypes.types, &match);
ebitmap_destroy(&match);
} else {
rc = ebitmap_match_any(&avrule->ttypes.types, &p->attr_type_map[k->target_type -1]);
}
if (rc == 0)
goto exit;
if (avrule->specified == AVRULE_XPERMS_NEVERALLOW) {
rc = check_assertion_extended_permissions(avrule, avtab, k);
if (rc == 0)
goto exit;
}
return 1;
exit:
return 0;
oom:
ERR(NULL, "Out of memory - unable to check neverallows");
return rc;
}
int check_assertion(policydb_t *p, avrule_t *avrule)
{
int rc;
struct avtab_match_args args;
args.handle = NULL;
args.p = p;
args.avrule = avrule;
args.errors = 0;
args.avtab = &p->te_avtab;
rc = avtab_map(&p->te_avtab, check_assertion_avtab_match, &args);
if (rc == 0) {
args.avtab = &p->te_cond_avtab;
rc = avtab_map(&p->te_cond_avtab, check_assertion_avtab_match, &args);
}
return rc;
}
int check_assertions(sepol_handle_t * handle, policydb_t * p,
avrule_t * avrules)
{
int rc;
avrule_t *a;
avtab_t te_avtab, te_cond_avtab;
ebitmap_node_t *snode, *tnode;
unsigned int i, j;
unsigned long errors = 0;
if (!avrules) {
@ -111,54 +435,22 @@ int check_assertions(sepol_handle_t * handle, policydb_t * p,
return 0;
}
if (avrules) {
if (avtab_init(&te_avtab))
goto oom;
if (avtab_init(&te_cond_avtab)) {
avtab_destroy(&te_avtab);
goto oom;
}
if (expand_avtab(p, &p->te_avtab, &te_avtab) ||
expand_avtab(p, &p->te_cond_avtab, &te_cond_avtab)) {
avtab_destroy(&te_avtab);
avtab_destroy(&te_cond_avtab);
goto oom;
}
}
for (a = avrules; a != NULL; a = a->next) {
ebitmap_t *stypes = &a->stypes.types;
ebitmap_t *ttypes = &a->ttypes.types;
if (!(a->specified & AVRULE_NEVERALLOW))
if (!(a->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW)))
continue;
ebitmap_for_each_bit(stypes, snode, i) {
if (!ebitmap_node_get_bit(snode, i))
continue;
if (a->flags & RULE_SELF) {
errors += check_assertion_helper
(handle, p, &te_avtab, &te_cond_avtab, i, i,
a);
}
ebitmap_for_each_bit(ttypes, tnode, j) {
if (!ebitmap_node_get_bit(tnode, j))
continue;
errors += check_assertion_helper
(handle, p, &te_avtab, &te_cond_avtab, i, j,
a);
rc = check_assertion(p, a);
if (rc) {
rc = report_assertion_failures(handle, p, a);
if (rc < 0) {
ERR(handle, "Error occurred while checking neverallows");
return -1;
}
errors += rc;
}
}
if (errors)
ERR(handle, "%lu neverallow failures occurred", errors);
avtab_destroy(&te_avtab);
avtab_destroy(&te_cond_avtab);
return errors ? -1 : 0;
oom:
ERR(handle, "Out of memory - unable to check neverallows");
return -1;
}

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;
}
@ -308,6 +309,9 @@ void avtab_destroy(avtab_t * h)
for (i = 0; i < h->nslot; i++) {
cur = h->htable[i];
while (cur != NULL) {
if (cur->key.specified & AVTAB_XPERMS) {
free(cur->datum.xperms);
}
temp = cur;
cur = cur->next;
free(temp);
@ -416,12 +420,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 +434,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 +534,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

@ -224,6 +224,28 @@ int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2)
return 1;
}
int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2)
{
ebitmap_node_t *n1 = e1->node;
ebitmap_node_t *n2 = e2->node;
while (n1 && n2) {
if (n1->startbit < n2->startbit) {
n1 = n1->next;
} else if (n2->startbit < n1->startbit) {
n2 = n2->next;
} else {
if (n1->map & n2->map) {
return 1;
}
n1 = n1->next;
n2 = n2->next;
}
}
return 0;
}
int ebitmap_get_bit(const ebitmap_t * e, unsigned int bit)
{
ebitmap_node_t *n;

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 {
@ -1954,6 +1948,8 @@ static int convert_and_expand_rule(sepol_handle_t * handle,
if (!do_neverallow && source_rule->specified & AVRULE_NEVERALLOW)
return EXPAND_RULE_SUCCESS;
if (source_rule->specified & AVRULE_XPERMS_NEVERALLOW)
return EXPAND_RULE_SUCCESS;
ebitmap_init(&stypes);
ebitmap_init(&ttypes);
@ -2317,25 +2313,33 @@ static int type_attr_map(hashtab_key_t key
policydb_t *p = state->out;
unsigned int i;
ebitmap_node_t *tnode;
int value;
type = (type_datum_t *) datum;
value = type->s.value;
if (type->flavor == TYPE_ATTRIB) {
if (ebitmap_cpy(&p->attr_type_map[type->s.value - 1],
&type->types)) {
ERR(state->handle, "Out of memory!");
return -1;
if (ebitmap_cpy(&p->attr_type_map[value - 1], &type->types)) {
goto oom;
}
ebitmap_for_each_bit(&type->types, tnode, i) {
if (!ebitmap_node_get_bit(tnode, i))
continue;
if (ebitmap_set_bit(&p->type_attr_map[i],
type->s.value - 1, 1)) {
ERR(state->handle, "Out of memory!");
return -1;
if (ebitmap_set_bit(&p->type_attr_map[i], value - 1, 1)) {
goto oom;
}
}
} else {
if (ebitmap_set_bit(&p->attr_type_map[value - 1], value - 1, 1)) {
goto oom;
}
}
return 0;
oom:
ERR(state->handle, "Out of memory!");
return -1;
}
/* converts typeset using typemap and expands into ebitmap_t types using the attributes in the passed in policy.
@ -2376,7 +2380,8 @@ int expand_rule(sepol_handle_t * handle,
int retval;
ebitmap_t stypes, ttypes;
if (source_rule->specified & AVRULE_NEVERALLOW)
if ((source_rule->specified & AVRULE_NEVERALLOW)
|| (source_rule->specified & AVRULE_XPERMS_NEVERALLOW))
return 1;
ebitmap_init(&stypes);
@ -2590,6 +2595,7 @@ static int copy_neverallow(policydb_t * dest_pol, uint32_t * typemap,
ebitmap_t stypes, ttypes;
avrule_t *avrule;
class_perm_node_t *cur_perm, *new_perm, *tail_perm;
av_extended_perms_t *xperms = NULL;
ebitmap_init(&stypes);
ebitmap_init(&ttypes);
@ -2606,7 +2612,7 @@ static int copy_neverallow(policydb_t * dest_pol, uint32_t * typemap,
return -1;
avrule_init(avrule);
avrule->specified = AVRULE_NEVERALLOW;
avrule->specified = source_rule->specified;
avrule->line = source_rule->line;
avrule->flags = source_rule->flags;
avrule->source_line = source_rule->source_line;
@ -2645,6 +2651,15 @@ static int copy_neverallow(policydb_t * dest_pol, uint32_t * typemap,
cur_perm = cur_perm->next;
}
/* copy over extended permissions */
if (source_rule->xperms) {
xperms = calloc(1, sizeof(av_extended_perms_t));
if (!xperms)
goto err;
memcpy(xperms, source_rule->xperms, sizeof(av_extended_perms_t));
avrule->xperms = xperms;
}
/* just prepend the avrule to the first branch; it'll never be
written to disk */
if (!dest_pol->global->branch_list->avrules)
@ -2670,6 +2685,7 @@ static int copy_neverallow(policydb_t * dest_pol, uint32_t * typemap,
free(cur_perm);
cur_perm = tail_perm;
}
free(xperms);
free(avrule);
return -1;
}
@ -2722,16 +2738,15 @@ static int copy_and_expand_avrule_block(expand_state_t * state)
cur_avrule = decl->avrules;
while (cur_avrule != NULL) {
if (!(state->expand_neverallow)
&& cur_avrule->specified & AVRULE_NEVERALLOW) {
&& cur_avrule->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW)) {
/* copy this over directly so that assertions are checked later */
if (copy_neverallow
(state->out, state->typemap, cur_avrule))
ERR(state->handle,
"Error while copying neverallow.");
} else {
if (cur_avrule->specified & AVRULE_NEVERALLOW) {
if (cur_avrule->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW))
state->out->unsupported_format = 1;
}
if (convert_and_expand_rule
(state->handle, state->out, state->typemap,
cur_avrule, &state->out->te_avtab, NULL,
@ -3155,24 +3170,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 +3205,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 +3214,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!");

File diff suppressed because it is too large Load Diff

View File

@ -2859,7 +2859,7 @@ static int level_string_to_cil(char *levelstr)
char *token = NULL;
char *ranged = NULL;
matched = sscanf(levelstr, "%m[^:]:%ms", &sens, &cats);
matched = tokenize(levelstr, ':', 2, &sens, &cats);
if (matched < 1 || matched > 2) {
log_err("Invalid level: %s", levelstr);
rc = -1;
@ -2924,7 +2924,7 @@ static int context_string_to_cil(char *contextstr)
char *type = NULL;
char *level = NULL;
matched = sscanf(contextstr, "%m[^:]:%m[^:]:%m[^:]:%ms", &user, &role, &type, &level);
matched = tokenize(contextstr, ':', 4, &user, &role, &type, &level);
if (matched < 3 || matched > 4) {
log_err("Invalid context: %s", contextstr);
rc = -1;
@ -2965,6 +2965,7 @@ static int seusers_to_cil(struct sepol_module_package *mod_pkg)
char *user = NULL;
char *seuser = NULL;
char *level = NULL;
char *tmp = NULL;
int matched;
if (seusers_len == 0) {
@ -2972,11 +2973,18 @@ static int seusers_to_cil(struct sepol_module_package *mod_pkg)
}
while ((rc = get_line(&cur, end, &line)) > 0) {
if (line[0] == '#') {
tmp = line;
while (isspace(*tmp)) {
tmp++;
}
if (tmp[0] == '#' || tmp[0] == '\0') {
free(line);
line = NULL;
continue;
}
matched = sscanf(line, "%m[^:]:%m[^:]:%ms", &user, &seuser, &level);
matched = tokenize(tmp, ':', 3, &user, &seuser, &level);
if (matched < 2 || matched > 3) {
log_err("Invalid seuser line: %s", line);
@ -3045,28 +3053,51 @@ static int user_extra_to_cil(struct sepol_module_package *mod_pkg)
int matched;
char *user = NULL;
char *prefix = NULL;
int prefix_len = 0;
char *user_str = NULL;
char *prefix_str = NULL;
char *eol = NULL;
char *tmp = NULL;
if (userx_len == 0) {
return 0;
}
while ((rc = get_line(&cur, end, &line)) > 0) {
if (line[0] == '#') {
tmp = line;
while (isspace(*tmp)) {
tmp++;
}
if (tmp[0] == '#' || tmp[0] == '\0') {
free(line);
line = NULL;
continue;
}
matched = sscanf(line, "user %ms prefix %m[^;];", &user, &prefix);
if (matched != 2) {
matched = tokenize(tmp, ' ', 4, &user_str, &user, &prefix_str, &prefix);
if (matched != 4) {
rc = -1;
log_err("Invalid file context line: %s", line);
log_err("Invalid user extra line: %s", line);
goto exit;
}
prefix_len = strlen(prefix);
eol = prefix + prefix_len - 1;
if (*eol != ';' || strcmp(user_str, "user") || strcmp(prefix_str, "prefix")) {
rc = -1;
log_err("Invalid user extra line: %s", line);
goto exit;
}
*eol = '\0';
cil_println(0, "(userprefix %s %s)", user, prefix);
free(user);
free(prefix);
free(line);
user = prefix = line = NULL;
free(user_str);
free(prefix_str);
user = prefix = line = user_str = prefix_str = NULL;
}
if (rc == -1) {
@ -3096,17 +3127,25 @@ static int file_contexts_to_cil(struct sepol_module_package *mod_pkg)
char *mode = NULL;
char *context = NULL;
const char *cilmode;
char *tmp = NULL;
if (fc_len == 0) {
return 0;
}
while ((rc = get_line(&cur, end, &line)) > 0) {
if (line[0] == '#') {
tmp = line;
while (isspace(*tmp)) {
tmp++;
}
if (tmp[0] == '#' || tmp[0] == '\0') {
free(line);
line = NULL;
continue;
}
matched = sscanf(line, "%ms %ms %ms", &regex, &mode, &context);
matched = tokenize(tmp, ' ', 3, &regex, &mode, &context);
if (matched < 2 || matched > 3) {
rc = -1;
log_err("Invalid file context line: %s", line);

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,
@ -3936,6 +3936,10 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
/* add the type itself as the degenerate case */
if (ebitmap_set_bit(&p->type_attr_map[i], i, 1))
goto bad;
if (p->type_val_to_struct[i] && p->type_val_to_struct[i]->flavor != TYPE_ATTRIB) {
if (ebitmap_set_bit(&p->attr_type_map[i], i, 1))
goto bad;
}
}
}

View File

@ -19,11 +19,15 @@
*/
#include <assert.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <sepol/policydb/flask_types.h>
#include <sepol/policydb/policydb.h>
#include <sepol/policydb/util.h>
#include <dso.h>
struct val_to_name {
unsigned int val;
@ -114,3 +118,169 @@ char *sepol_av_to_string(policydb_t * policydbp, uint32_t tclass,
return avbuf;
}
#define next_bit_in_range(i, p) ((i + 1 < sizeof(p)*8) && xperm_test((i + 1), p))
char *sepol_extended_perms_to_string(avtab_extended_perms_t *xperms)
{
uint16_t value;
uint16_t low_bit;
uint16_t low_value;
unsigned int bit;
unsigned int in_range = 0;
static char xpermsbuf[2048];
xpermsbuf[0] = '\0';
char *p;
int len, xpermslen = 0;
p = xpermsbuf;
if ((xperms->specified != AVTAB_XPERMS_IOCTLFUNCTION)
&& (xperms->specified != AVTAB_XPERMS_IOCTLDRIVER))
return NULL;
len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "ioctl { ");
p += len;
xpermslen += len;
for (bit = 0; bit < sizeof(xperms->perms)*8; bit++) {
if (!xperm_test(bit, xperms->perms))
continue;
if (in_range && next_bit_in_range(bit, xperms->perms)) {
/* continue until high value found */
continue;
} else if (next_bit_in_range(bit, xperms->perms)) {
/* low value */
low_bit = bit;
in_range = 1;
continue;
}
if (xperms->specified & AVTAB_XPERMS_IOCTLFUNCTION) {
value = xperms->driver<<8 | bit;
low_value = xperms->driver<<8 | low_bit;
if (in_range) {
len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx-0x%hx ", low_value, value);
} else {
len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx ", value);
}
} else if (xperms->specified & AVTAB_XPERMS_IOCTLDRIVER) {
value = bit << 8;
low_value = low_bit << 8;
if (in_range) {
len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx-0x%hx ", low_value, (uint16_t) (value|0xff));
} else {
len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "0x%hx-0x%hx ", value, (uint16_t) (value|0xff));
}
}
if (len < 0 || (size_t) len >= (sizeof(xpermsbuf) - xpermslen))
return NULL;
p += len;
xpermslen += len;
if (in_range)
in_range = 0;
}
len = snprintf(p, sizeof(xpermsbuf) - xpermslen, "}");
if (len < 0 || (size_t) len >= (sizeof(xpermsbuf) - xpermslen))
return NULL;
return xpermsbuf;
}
/*
* The tokenize and tokenize_str functions may be used to
* replace sscanf to read tokens from buffers.
*/
/* Read a token from a buffer */
static inline int tokenize_str(char delim, char **str, char **ptr, size_t *len)
{
char *tmp_buf = *ptr;
*str = NULL;
while (**ptr != '\0') {
if (isspace(delim) && isspace(**ptr)) {
(*ptr)++;
break;
} else if (!isspace(delim) && **ptr == delim) {
(*ptr)++;
break;
}
(*ptr)++;
}
*len = *ptr - tmp_buf;
/* If the end of the string has not been reached, this will ensure the
* delimiter is not included when returning the token.
*/
if (**ptr != '\0') {
(*len)--;
}
*str = strndup(tmp_buf, *len);
if (!*str) {
return -1;
}
/* Squash spaces if the delimiter is a whitespace character */
while (**ptr != '\0' && isspace(delim) && isspace(**ptr)) {
(*ptr)++;
}
return 0;
}
/*
* line_buf - Buffer containing string to tokenize.
* delim - The delimiter used to tokenize line_buf. A whitespace delimiter will
* be tokenized using isspace().
* num_args - The number of parameter entries to process.
* ... - A 'char **' for each parameter.
* returns - The number of items processed.
*
* This function calls tokenize_str() to do the actual string processing. The
* caller is responsible for calling free() on each additional argument. The
* function will not tokenize more than num_args and the last argument will
* contain the remaining content of line_buf. If the delimiter is any whitespace
* character, then all whitespace will be squashed.
*/
int hidden tokenize(char *line_buf, char delim, int num_args, ...)
{
char **arg, *buf_p;
int rc, items;
size_t arg_len = 0;
va_list ap;
buf_p = line_buf;
/* Process the arguments */
va_start(ap, num_args);
for (items = 0; items < num_args && *buf_p != '\0'; items++) {
arg = va_arg(ap, char **);
/* Save the remainder of the string in arg */
if (items == num_args - 1) {
*arg = strdup(buf_p);
if (*arg == NULL) {
goto exit;
}
continue;
}
rc = tokenize_str(delim, arg, &buf_p, &arg_len);
if (rc < 0) {
goto exit;
}
}
exit:
va_end(ap);
return items;
}

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;
}

View File

@ -1,3 +1,11 @@
* audit2allow/why: ignore setlocale errors, from Petr Lautrbach.
* semodule: Add --extract/-E, --cil/-c, and --hll/-H to extract modules, from Yuli Khodorkovskiy.
* audit2allow: Comment constraint rules in output, from Miroslav Grepl via Petr Lautrbach.
* Fix PEP8 issues, from Jason Zaman.
* semanage: fix moduleRecords deleteall method, from Stephen Smalley.
* Improve compatibility with Python 3, from Michal Srb.
* semanage: Set self.sename to sename after calling semanage_seuser_set_sename(), from Laurent Bigonville.
* semanage: Fix typo in semanage args for minimium policy store, from Petr Lautrbach.
* sepolicy: Only invoke RPM on RPM-enabled Linux distributions, from Sven Vermeulen.
* mcstransd: don't reinvent getpeercon, from Stephen Smalley.
* setfiles/restorecon: fix -r/-R option, from Petr Lautrbach.

View File

@ -19,7 +19,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import sys, os
import sys
import os
import sepolgen.audit as audit
import sepolgen.policygen as policygen
@ -31,7 +32,11 @@ import sepolgen.module as module
from sepolgen.sepolgeni18n import _
import selinux.audit2why as audit2why
import locale
locale.setlocale(locale.LC_ALL, '')
try:
locale.setlocale(locale.LC_ALL, '')
except:
pass
class AuditToPolicy:
VERSION = "%prog .1"
@ -65,8 +70,8 @@ class AuditToPolicy:
help="generate a module package - conflicts with -o and -m")
parser.add_option("-o", "--output", dest="output",
help="append output to <filename>, conflicts with -M")
parser.add_option("-D", "--dontaudit", action="store_true",
dest="dontaudit", default=False,
parser.add_option("-D", "--dontaudit", action="store_true",
dest="dontaudit", default=False,
help="generate policy with dontaudit rules")
parser.add_option("-R", "--reference", action="store_true", dest="refpolicy",
default=True, help="generate refpolicy style output")
@ -83,7 +88,7 @@ class AuditToPolicy:
parser.add_option("--interface-info", dest="interface_info", help="file name of interface information")
parser.add_option("--debug", dest="debug", action="store_true", default=False,
help="leave generated modules for -M")
parser.add_option("-w", "--why", dest="audit2why", action="store_true", default=(os.path.basename(sys.argv[0])=="audit2why"),
parser.add_option("-w", "--why", dest="audit2why", action="store_true", default=(os.path.basename(sys.argv[0]) == "audit2why"),
help="Translates SELinux audit messages into a description of why the access was denied")
options, args = parser.parse_args()
@ -135,13 +140,13 @@ class AuditToPolicy:
elif self.__options.audit:
try:
messages = audit.get_audit_msgs()
except OSError, e:
except OSError as e:
sys.stderr.write('could not run ausearch - "%s"\n' % str(e))
sys.exit(1)
elif self.__options.boot:
try:
messages = audit.get_audit_boot_msgs()
except OSError, e:
except OSError as e:
sys.stderr.write('could not run ausearch - "%s"\n' % str(e))
sys.exit(1)
else:
@ -152,7 +157,7 @@ class AuditToPolicy:
if filename is not None:
try:
f = open(filename)
except IOError, e:
except IOError as e:
sys.stderr.write('could not open file %s - "%s"\n' % (filename, str(e)))
sys.exit(1)
@ -214,7 +219,7 @@ class AuditToPolicy:
try:
fd = open(filename, "w")
except IOError, e:
except IOError as e:
sys.stderr.write("could not write output file: %s\n" % str(e))
sys.exit(1)
@ -225,71 +230,71 @@ class AuditToPolicy:
try:
mc.create_module_package(filename, self.__options.refpolicy)
except RuntimeError, e:
print e
except RuntimeError as e:
print(e)
sys.exit(1)
sys.stdout.write(_("******************** IMPORTANT ***********************\n"))
sys.stdout.write((_("To make this policy package active, execute:" +\
"\n\nsemodule -i %s\n\n") % packagename))
sys.stdout.write((_("To make this policy package active, execute:" +
"\n\nsemodule -i %s\n\n") % packagename))
def __output_audit2why(self):
import selinux
import seobject
for i in self.__parser.avc_msgs:
rc = i.type
data = i.data
if rc >= 0:
print "%s\n\tWas caused by:" % i.message
if rc == audit2why.ALLOW:
print "\t\tUnknown - would be allowed by active policy\n",
print "\t\tPossible mismatch between this policy and the one under which the audit message was generated.\n"
print "\t\tPossible mismatch between current in-memory boolean settings vs. permanent ones.\n"
continue
if rc == audit2why.DONTAUDIT:
print "\t\tUnknown - should be dontaudit'd by active policy\n",
print "\t\tPossible mismatch between this policy and the one under which the audit message was generated.\n"
print "\t\tPossible mismatch between current in-memory boolean settings vs. permanent ones.\n"
continue
if rc == audit2why.BOOLEAN:
if len(data) > 1:
print "\tOne of the following booleans was set incorrectly."
for b in data:
print "\tDescription:\n\t%s\n" % seobject.boolean_desc(b[0])
print "\tAllow access by executing:\n\t# setsebool -P %s %d" % (b[0], b[1])
else:
print "\tThe boolean %s was set incorrectly. " % (data[0][0])
print "\tDescription:\n\t%s\n" % seobject.boolean_desc(data[0][0])
print "\tAllow access by executing:\n\t# setsebool -P %s %d" % (data[0][0], data[0][1])
continue
import selinux
import seobject
for i in self.__parser.avc_msgs:
rc = i.type
data = i.data
if rc >= 0:
print("%s\n\tWas caused by:" % i.message)
if rc == audit2why.ALLOW:
print("\t\tUnknown - would be allowed by active policy")
print("\t\tPossible mismatch between this policy and the one under which the audit message was generated.\n")
print("\t\tPossible mismatch between current in-memory boolean settings vs. permanent ones.\n")
continue
if rc == audit2why.DONTAUDIT:
print("\t\tUnknown - should be dontaudit'd by active policy")
print("\t\tPossible mismatch between this policy and the one under which the audit message was generated.\n")
print("\t\tPossible mismatch between current in-memory boolean settings vs. permanent ones.\n")
continue
if rc == audit2why.BOOLEAN:
if len(data) > 1:
print("\tOne of the following booleans was set incorrectly.")
for b in data:
print("\tDescription:\n\t%s\n" % seobject.boolean_desc(b[0]))
print("\tAllow access by executing:\n\t# setsebool -P %s %d" % (b[0], b[1]))
else:
print("\tThe boolean %s was set incorrectly. " % (data[0][0]))
print("\tDescription:\n\t%s\n" % seobject.boolean_desc(data[0][0]))
print("\tAllow access by executing:\n\t# setsebool -P %s %d" % (data[0][0], data[0][1]))
continue
if rc == audit2why.TERULE:
print "\t\tMissing type enforcement (TE) allow rule.\n"
print "\t\tYou can use audit2allow to generate a loadable module to allow this access.\n"
continue
if rc == audit2why.TERULE:
print("\t\tMissing type enforcement (TE) allow rule.\n")
print("\t\tYou can use audit2allow to generate a loadable module to allow this access.\n")
continue
if rc == audit2why.CONSTRAINT:
print #!!!! This avc is a constraint violation. You would need to modify the attributes of either the source or target types to allow this access.\n"
print "#Constraint rule:"
print "\n\t" + data[0]
for reason in data[1:]:
print "#\tPossible cause is the source %s and target %s are different.\n" % reason
if rc == audit2why.CONSTRAINT:
print() # !!!! This avc is a constraint violation. You would need to modify the attributes of either the source or target types to allow this access.\n"
print("#Constraint rule:")
print("\n#\t" + data[0])
for reason in data[1:]:
print("#\tPossible cause is the source %s and target %s are different.\n" % reason)
if rc == audit2why.RBAC:
print "\t\tMissing role allow rule.\n"
print "\t\tAdd an allow rule for the role pair.\n"
continue
if rc == audit2why.RBAC:
print("\t\tMissing role allow rule.\n")
print("\t\tAdd an allow rule for the role pair.\n")
continue
audit2why.finish()
return
audit2why.finish()
return
def __output(self):
if self.__options.audit2why:
try:
return self.__output_audit2why()
except RuntimeError, e:
print e
except RuntimeError as e:
print(e)
sys.exit(1)
g = policygen.PolicyGenerator()
@ -348,11 +353,11 @@ class AuditToPolicy:
self.__output()
except KeyboardInterrupt:
sys.exit(0)
except ValueError, e:
print e
except ValueError as e:
print(e)
sys.exit(1)
except IOError, e:
print e
except IOError as e:
print(e)
sys.exit(1)
if __name__ == "__main__":

View File

@ -19,7 +19,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
import sys, os
import sys
import os
import sepolgen.audit as audit
import sepolgen.policygen as policygen
@ -31,7 +32,11 @@ import sepolgen.module as module
from sepolgen.sepolgeni18n import _
import selinux.audit2why as audit2why
import locale
locale.setlocale(locale.LC_ALL, '')
try:
locale.setlocale(locale.LC_ALL, '')
except:
pass
class AuditToPolicy:
VERSION = "%prog .1"
@ -83,7 +88,7 @@ class AuditToPolicy:
parser.add_option("--interface-info", dest="interface_info", help="file name of interface information")
parser.add_option("--debug", dest="debug", action="store_true", default=False,
help="leave generated modules for -M")
parser.add_option("-w", "--why", dest="audit2why", action="store_true", default=(os.path.basename(sys.argv[0])=="audit2why"),
parser.add_option("-w", "--why", dest="audit2why", action="store_true", default=(os.path.basename(sys.argv[0]) == "audit2why"),
help="Translates SELinux audit messages into a description of why the access was denied")
options, args = parser.parse_args()
@ -135,13 +140,13 @@ class AuditToPolicy:
elif self.__options.audit:
try:
messages = audit.get_audit_msgs()
except OSError, e:
except OSError as e:
sys.stderr.write('could not run ausearch - "%s"\n' % str(e))
sys.exit(1)
elif self.__options.boot:
try:
messages = audit.get_audit_boot_msgs()
except OSError, e:
except OSError as e:
sys.stderr.write('could not run ausearch - "%s"\n' % str(e))
sys.exit(1)
else:
@ -152,7 +157,7 @@ class AuditToPolicy:
if filename is not None:
try:
f = open(filename)
except IOError, e:
except IOError as e:
sys.stderr.write('could not open file %s - "%s"\n' % (filename, str(e)))
sys.exit(1)
@ -214,7 +219,7 @@ class AuditToPolicy:
try:
fd = open(filename, "w")
except IOError, e:
except IOError as e:
sys.stderr.write("could not write output file: %s\n" % str(e))
sys.exit(1)
@ -225,70 +230,70 @@ class AuditToPolicy:
try:
mc.create_module_package(filename, self.__options.refpolicy)
except RuntimeError, e:
print e
except RuntimeError as e:
print(e)
sys.exit(1)
sys.stdout.write(_("******************** IMPORTANT ***********************\n"))
sys.stdout.write((_("To make this policy package active, execute:" +\
"\n\nsemodule -i %s\n\n") % packagename))
sys.stdout.write((_("To make this policy package active, execute:" +
"\n\nsemodule -i %s\n\n") % packagename))
def __output_audit2why(self):
import selinux
import seobject
for i in self.__parser.avc_msgs:
rc = i.type
data = i.data
if rc >= 0:
print "%s\n\tWas caused by:" % i.message
if rc == audit2why.ALLOW:
print "\t\tUnknown - would be allowed by active policy\n",
print "\t\tPossible mismatch between this policy and the one under which the audit message was generated.\n"
print "\t\tPossible mismatch between current in-memory boolean settings vs. permanent ones.\n"
continue
if rc == audit2why.DONTAUDIT:
print "\t\tUnknown - should be dontaudit'd by active policy\n",
print "\t\tPossible mismatch between this policy and the one under which the audit message was generated.\n"
print "\t\tPossible mismatch between current in-memory boolean settings vs. permanent ones.\n"
continue
if rc == audit2why.BOOLEAN:
if len(data) > 1:
print "\tOne of the following booleans was set incorrectly."
for b in data:
print "\tDescription:\n\t%s\n" % seobject.boolean_desc(b[0])
print "\tAllow access by executing:\n\t# setsebool -P %s %d" % (b[0], b[1])
else:
print "\tThe boolean %s was set incorrectly. " % (data[0][0])
print "\tDescription:\n\t%s\n" % seobject.boolean_desc(data[0][0])
print "\tAllow access by executing:\n\t# setsebool -P %s %d" % (data[0][0], data[0][1])
continue
import selinux
import seobject
for i in self.__parser.avc_msgs:
rc = i.type
data = i.data
if rc >= 0:
print("%s\n\tWas caused by:" % i.message)
if rc == audit2why.ALLOW:
print("\t\tUnknown - would be allowed by active policy")
print("\t\tPossible mismatch between this policy and the one under which the audit message was generated.\n")
print("\t\tPossible mismatch between current in-memory boolean settings vs. permanent ones.\n")
continue
if rc == audit2why.DONTAUDIT:
print("\t\tUnknown - should be dontaudit'd by active policy")
print("\t\tPossible mismatch between this policy and the one under which the audit message was generated.\n")
print("\t\tPossible mismatch between current in-memory boolean settings vs. permanent ones.\n")
continue
if rc == audit2why.BOOLEAN:
if len(data) > 1:
print("\tOne of the following booleans was set incorrectly.")
for b in data:
print("\tDescription:\n\t%s\n" % seobject.boolean_desc(b[0]))
print("\tAllow access by executing:\n\t# setsebool -P %s %d" % (b[0], b[1]))
else:
print("\tThe boolean %s was set incorrectly. " % (data[0][0]))
print("\tDescription:\n\t%s\n" % seobject.boolean_desc(data[0][0]))
print("\tAllow access by executing:\n\t# setsebool -P %s %d" % (data[0][0], data[0][1]))
continue
if rc == audit2why.TERULE:
print "\t\tMissing type enforcement (TE) allow rule.\n"
print "\t\tYou can use audit2allow to generate a loadable module to allow this access.\n"
continue
if rc == audit2why.TERULE:
print("\t\tMissing type enforcement (TE) allow rule.\n")
print("\t\tYou can use audit2allow to generate a loadable module to allow this access.\n")
continue
if rc == audit2why.CONSTRAINT:
print #!!!! This avc is a constraint violation. You would need to modify the attributes of either the source or target types to allow this access.\n"
print "#Constraint rule: \n\t" + data[0]
for reason in data[1:]:
print "#\tPossible cause is the source %s and target %s are different.\n\b" % reason
if rc == audit2why.CONSTRAINT:
print() # !!!! This avc is a constraint violation. You would need to modify the attributes of either the source or target types to allow this access.\n"
print("#Constraint rule: \n\t" + data[0])
for reason in data[1:]:
print("#\tPossible cause is the source %s and target %s are different.\n\b" % reason)
if rc == audit2why.RBAC:
print "\t\tMissing role allow rule.\n"
print "\t\tAdd an allow rule for the role pair.\n"
continue
if rc == audit2why.RBAC:
print("\t\tMissing role allow rule.\n")
print("\t\tAdd an allow rule for the role pair.\n")
continue
audit2why.finish()
return
audit2why.finish()
return
def __output(self):
if self.__options.audit2why:
try:
return self.__output_audit2why()
except RuntimeError, e:
print e
except RuntimeError as e:
print(e)
sys.exit(1)
g = policygen.PolicyGenerator()
@ -347,11 +352,11 @@ class AuditToPolicy:
self.__output()
except KeyboardInterrupt:
sys.exit(0)
except ValueError, e:
print e
except ValueError as e:
print(e)
sys.exit(1)
except IOError, e:
print e
except IOError as e:
print(e)
sys.exit(1)
if __name__ == "__main__":

View File

@ -2,7 +2,7 @@
#
# Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
#
# Copyright (C) 2006 Red Hat
# Copyright (C) 2006 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or
@ -41,6 +41,7 @@ import sepolgen.interfaces as interfaces
VERSION = "%prog .1"
ATTR_HELPER = "/usr/bin/sepolgen-ifgen-attr-helper"
def parse_options():
from optparse import OptionParser
@ -54,13 +55,14 @@ def parse_options():
parser.add_option("-v", "--verbose", action="store_true", default=False,
help="print debuging output")
parser.add_option("-d", "--debug", action="store_true", default=False,
help="extra debugging output")
help="extra debugging output")
parser.add_option("--no_attrs", action="store_true", default=False,
help="do not retrieve attribute access from kernel policy")
options, args = parser.parse_args()
return options
def get_policy():
p = selinux.selinux_current_policy_path()
if p and os.path.exists(p):
@ -74,6 +76,7 @@ def get_policy():
return p
return None
def get_attrs(policy_path):
try:
if not policy_path:
@ -82,14 +85,14 @@ def get_attrs(policy_path):
sys.stderr.write("No installed policy to check\n")
return None
outfile = tempfile.NamedTemporaryFile()
except IOError, e:
except IOError as e:
sys.stderr.write("could not open attribute output file\n")
return None
except OSError:
# SELinux Disabled Machine
return None
fd = open("/dev/null","w")
fd = open("/dev/null", "w")
ret = subprocess.Popen([ATTR_HELPER, policy_path, outfile.name], stdout=fd).wait()
fd.close()
if ret != 0:
@ -100,18 +103,19 @@ def get_attrs(policy_path):
try:
attrs.from_file(outfile)
except:
print "error parsing attribute info"
print("error parsing attribute info")
return None
return attrs
def main():
options = parse_options()
# Open the output first to generate errors before parsing
try:
f = open(options.output, "w")
except IOError, e:
except IOError as e:
sys.stderr.write("could not open output file [%s]\n" % options.output)
return 1
@ -130,9 +134,9 @@ def main():
# Parse the headers
try:
headers = refparser.parse_headers(options.headers, output=log, debug=options.debug)
except ValueError, e:
print "error parsing headers"
print str(e)
except ValueError as e:
print("error parsing headers")
print(str(e))
return 1
if_set = interfaces.InterfaceSet(output=log)
@ -144,6 +148,6 @@ def main():
return 0
else:
return 1
if __name__ == "__main__":
sys.exit(main())

View File

@ -1,26 +1,31 @@
import unittest, os, shutil
import unittest
import os
import shutil
from tempfile import mkdtemp
from subprocess import Popen, PIPE
class Audit2allowTests(unittest.TestCase):
def assertDenied(self, err):
self.assert_('Permission denied' in err,
'"Permission denied" not found in %r' % err)
self.assertTrue('Permission denied' in err,
'"Permission denied" not found in %r' % err)
def assertNotFound(self, err):
self.assert_('not found' in err,
'"not found" not found in %r' % err)
self.assertTrue('not found' in err,
'"not found" not found in %r' % err)
def assertFailure(self, status):
self.assert_(status != 0,
'"Succeeded when it should have failed')
self.assertTrue(status != 0,
'"Succeeded when it should have failed')
def assertSuccess(self, cmd, status, err):
self.assert_(status == 0,
'"%s should have succeeded for this test %r' % (cmd, err))
self.assertTrue(status == 0,
'"%s should have succeeded for this test %r' % (cmd, err))
def test_sepolgen_ifgen(self):
"Verify sepolgen-ifgen works"
p = Popen(['sudo', 'sepolgen-ifgen'], stdout = PIPE)
p = Popen(['sudo', 'sepolgen-ifgen'], stdout=PIPE)
out, err = p.communicate()
if err:
print(out, err)
@ -28,7 +33,7 @@ class Audit2allowTests(unittest.TestCase):
def test_audit2allow(self):
"Verify audit2allow works"
p = Popen(['audit2allow',"-i","test.log"], stdout = PIPE)
p = Popen(['audit2allow', "-i", "test.log"], stdout=PIPE)
out, err = p.communicate()
if err:
print(out, err)
@ -36,7 +41,7 @@ class Audit2allowTests(unittest.TestCase):
def test_audit2why(self):
"Verify audit2why works"
p = Popen(['audit2why',"-i","test.log"], stdout = PIPE)
p = Popen(['audit2why', "-i", "test.log"], stdout=PIPE)
out, err = p.communicate()
if err:
print(out, err)

View File

@ -28,18 +28,18 @@ import tempfile
import seobject
import semanagePage
INSTALLPATH='/usr/share/system-config-selinux'
INSTALLPATH = '/usr/share/system-config-selinux'
sys.path.append(INSTALLPATH)
import commands
ENFORCING=0
PERMISSIVE=1
DISABLED=2
ENFORCING = 0
PERMISSIVE = 1
DISABLED = 2
##
## I18N
##
PROGNAME="policycoreutils"
PROGNAME = "policycoreutils"
import gettext
gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
@ -48,41 +48,47 @@ try:
gettext.install(PROGNAME,
localedir="/usr/share/locale",
unicode=False,
codeset = 'utf-8')
codeset='utf-8')
except IOError:
import __builtin__
__builtin__.__dict__['_'] = unicode
from glob import fnmatch
class Modifier:
def __init__(self,name, on, save):
self.on=on
self.name=name
self.save=save
def set(self,value):
self.on=value
self.save=True
class Modifier:
def __init__(self, name, on, save):
self.on = on
self.name = name
self.save = save
def set(self, value):
self.on = value
self.save = True
def isOn(self):
return self.on
class Boolean(Modifier):
def __init__(self,name, val, save=False):
Modifier.__init__(self,name, val, save)
def __init__(self, name, val, save=False):
Modifier.__init__(self, name, val, save)
ACTIVE = 0
MODULE = 1
DESC = 2
BOOLEAN = 3
class booleansPage:
def __init__(self, xml, doDebug=None):
self.xml = xml
self.window = self.xml.get_widget("mainWindow").get_root_window()
self.local = False
self.types=[]
self.types = []
self.selinuxsupport = True
self.typechanged = False
self.doDebug = doDebug
@ -112,7 +118,7 @@ class booleansPage:
checkbox = gtk.CellRendererToggle()
checkbox.connect("toggled", self.boolean_toggled)
col = gtk.TreeViewColumn('Active', checkbox, active = ACTIVE)
col = gtk.TreeViewColumn('Active', checkbox, active=ACTIVE)
col.set_clickable(True)
col.set_sort_column_id(ACTIVE)
self.booleansView.append_column(col)
@ -123,7 +129,7 @@ class booleansPage:
self.booleansView.append_column(col)
col = gtk.TreeViewColumn("Description", gtk.CellRendererText(), text=DESC)
col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
col.set_fixed_width(400)
col.set_sort_column_id(DESC)
col.set_resizable(True)
@ -134,7 +140,7 @@ class booleansPage:
col.set_resizable(True)
self.booleansView.set_search_equal_func(self.__search)
self.booleansView.append_column(col)
self.filter=""
self.filter = ""
self.load(self.filter)
def error(self, message):
@ -182,10 +188,10 @@ class booleansPage:
self.error(e.args[0])
def filter_changed(self, *arg):
filter = arg[0].get_text()
filter = arg[0].get_text()
if filter != self.filter:
self.load(filter)
self.filter=filter
self.filter = filter
def use_menus(self):
return False
@ -193,17 +199,16 @@ class booleansPage:
def get_description(self):
return _("Boolean")
def match(self,key, filter=""):
def match(self, key, filter=""):
try:
f=filter.lower()
cat=self.booleans.get_category(key).lower()
val=self.booleans.get_desc(key).lower()
k=key.lower()
f = filter.lower()
cat = self.booleans.get_category(key).lower()
val = self.booleans.get_desc(key).lower()
k = key.lower()
return val.find(f) >= 0 or k.find(f) >= 0 or cat.find(f) >= 0
except:
return False
def load(self, filter=None):
self.store.clear()
self.booleans = seobject.booleanRecords()
@ -211,7 +216,7 @@ class booleansPage:
for name in booleansList:
rec = booleansList[name]
if self.match(name, filter):
iter=self.store.append()
iter = self.store.append()
self.store.set_value(iter, ACTIVE, rec[2] == 1)
self.store.set_value(iter, MODULE, self.booleans.get_category(name))
self.store.set_value(iter, DESC, self.booleans.get_desc(name))
@ -221,10 +226,10 @@ class booleansPage:
iter = self.store.get_iter(row)
val = self.store.get_value(iter, ACTIVE)
key = self.store.get_value(iter, BOOLEAN)
self.store.set_value(iter, ACTIVE , not val)
self.store.set_value(iter, ACTIVE, not val)
self.wait()
setsebool="/usr/sbin/setsebool -P %s %d" % (key, not val)
rc,out = commands.getstatusoutput(setsebool)
setsebool = "/usr/sbin/setsebool -P %s %d" % (key, not val)
rc, out = commands.getstatusoutput(setsebool)
if rc != 0:
self.error(out)
self.load(self.filter)
@ -232,7 +237,7 @@ class booleansPage:
def on_revert_clicked(self, button):
self.wait()
setsebool="semanage boolean --deleteall"
setsebool = "semanage boolean --deleteall"
commands.getstatusoutput(setsebool)
self.load(self.filter)
self.ready()

View File

@ -25,13 +25,13 @@ import gobject
import sys
import seobject
import selinux
from semanagePage import *;
from semanagePage import *
from sepolicy import get_all_entrypoint_domains
##
## I18N
##
PROGNAME="policycoreutils"
PROGNAME = "policycoreutils"
import gettext
gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
gettext.textdomain(PROGNAME)
@ -39,12 +39,14 @@ try:
gettext.install(PROGNAME,
localedir="/usr/share/locale",
unicode=False,
codeset = 'utf-8')
codeset='utf-8')
except IOError:
import __builtin__
__builtin__.__dict__['_'] = unicode
class domainsPage(semanagePage):
def __init__(self, xml):
semanagePage.__init__(self, xml, "domains", _("Process Domain"))
self.domain_filter = xml.get_widget("domainsFilterEntry")
@ -54,12 +56,12 @@ class domainsPage(semanagePage):
self.store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
self.view.set_model(self.store)
self.store.set_sort_column_id(0, gtk.SORT_ASCENDING)
col = gtk.TreeViewColumn(_("Domain Name"), gtk.CellRendererText(), text = 0)
col = gtk.TreeViewColumn(_("Domain Name"), gtk.CellRendererText(), text=0)
col.set_sort_column_id(0)
col.set_resizable(True)
self.view.append_column(col)
self.store.set_sort_column_id(0, gtk.SORT_ASCENDING)
col = gtk.TreeViewColumn(_("Mode"), gtk.CellRendererText(), text = 1)
col = gtk.TreeViewColumn(_("Mode"), gtk.CellRendererText(), text=1)
col.set_sort_column_id(1)
col.set_resizable(True)
self.view.append_column(col)
@ -68,12 +70,12 @@ class domainsPage(semanagePage):
self.permissive_button = xml.get_widget("permissiveButton")
self.enforcing_button = xml.get_widget("enforcingButton")
self.domains=get_all_entrypoint_domains()
self.domains = get_all_entrypoint_domains()
self.load()
def get_modules(self):
modules=[]
fd=os.popen("semodule -l")
modules = []
fd = os.popen("semodule -l")
mods = fd.readlines()
fd.close()
for l in mods:
@ -81,10 +83,10 @@ class domainsPage(semanagePage):
return modules
def load(self, filter=""):
self.filter=filter
self.filter = filter
self.store.clear()
try:
modules=self.get_modules()
modules = self.get_modules()
for domain in self.domains:
if not self.match(domain, filter):
continue
@ -97,7 +99,7 @@ class domainsPage(semanagePage):
self.store.set_value(iter, 1, "")
except:
pass
self.view.get_selection().select_path ((0,))
self.view.get_selection().select_path((0,))
def itemSelected(self, selection):
store, iter = selection.get_selected()

View File

@ -22,16 +22,18 @@ import os
import gobject
import seobject
import commands
from semanagePage import *;
from semanagePage import *
SPEC_COL = 0
TYPE_COL = 1
FTYPE_COL = 2
class context:
def __init__(self, scontext):
self.scontext = scontext
con=scontext.split(":")
con = scontext.split(":")
self.type = con[0]
if len(con) > 1:
self.mls = con[1]
@ -44,7 +46,7 @@ class context:
##
## I18N
##
PROGNAME="policycoreutils"
PROGNAME = "policycoreutils"
import gettext
gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
@ -53,13 +55,14 @@ try:
gettext.install(PROGNAME,
localedir="/usr/share/locale",
unicode=False,
codeset = 'utf-8')
codeset='utf-8')
except IOError:
import __builtin__
__builtin__.__dict__['_'] = unicode
class fcontextPage(semanagePage):
def __init__(self, xml):
semanagePage.__init__(self, xml, "fcontext", _("File Labeling"))
self.fcontextFilter = xml.get_widget("fcontextFilterEntry")
@ -72,16 +75,16 @@ class fcontextPage(semanagePage):
self.view.set_search_equal_func(self.search)
col = gtk.TreeViewColumn(_("File\nSpecification"), gtk.CellRendererText(), text=SPEC_COL)
col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
col.set_fixed_width(250)
col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
col.set_fixed_width(250)
col.set_sort_column_id(SPEC_COL)
col.set_resizable(True)
self.view.append_column(col)
col = gtk.TreeViewColumn(_("Selinux\nFile Type"), gtk.CellRendererText(), text=TYPE_COL)
col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
col.set_fixed_width(250)
col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
col.set_fixed_width(250)
col.set_sort_column_id(TYPE_COL)
col.set_resizable(True)
self.view.append_column(col)
@ -94,10 +97,10 @@ class fcontextPage(semanagePage):
self.load()
self.fcontextEntry = xml.get_widget("fcontextEntry")
self.fcontextFileTypeCombo = xml.get_widget("fcontextFileTypeCombo")
liststore=self.fcontextFileTypeCombo.get_model()
liststore = self.fcontextFileTypeCombo.get_model()
for k in seobject.file_types:
if len(k) > 0 and k[0] != '-':
iter=liststore.append()
if len(k) > 0 and k[0] != '-':
iter = liststore.append()
liststore.set_value(iter, 0, k)
iter = liststore.get_iter_first()
self.fcontextFileTypeCombo.set_active_iter(iter)
@ -106,13 +109,13 @@ class fcontextPage(semanagePage):
def match(self, fcon_dict, k, filter):
try:
f=filter.lower()
f = filter.lower()
for con in k:
k=con.lower()
k = con.lower()
if k.find(f) >= 0:
return True
for con in fcon_dict[k]:
k=con.lower()
k = con.lower()
if k.find(f) >= 0:
return True
except:
@ -120,27 +123,27 @@ class fcontextPage(semanagePage):
return False
def load(self, filter=""):
self.filter=filter
self.fcontext=seobject.fcontextRecords()
self.filter = filter
self.fcontext = seobject.fcontextRecords()
self.store.clear()
fcon_dict=self.fcontext.get_all(self.local)
fcon_dict = self.fcontext.get_all(self.local)
keys = fcon_dict.keys()
keys.sort()
for k in keys:
if not self.match(fcon_dict, k, filter):
continue
iter=self.store.append()
iter = self.store.append()
self.store.set_value(iter, SPEC_COL, k[0])
self.store.set_value(iter, FTYPE_COL, k[1])
if fcon_dict[k]:
rec="%s:%s" % (fcon_dict[k][2], seobject.translate(fcon_dict[k][3],False))
rec = "%s:%s" % (fcon_dict[k][2], seobject.translate(fcon_dict[k][3], False))
else:
rec="<<None>>"
rec = "<<None>>"
self.store.set_value(iter, TYPE_COL, rec)
self.view.get_selection().select_path ((0,))
self.view.get_selection().select_path((0,))
def filter_changed(self, *arg):
filter = arg[0].get_text()
filter = arg[0].get_text()
if filter != self.filter:
self.load(filter)
@ -149,13 +152,13 @@ class fcontextPage(semanagePage):
self.fcontextEntry.set_text(store.get_value(iter, SPEC_COL))
self.fcontextEntry.set_sensitive(False)
scontext = store.get_value(iter, TYPE_COL)
scon=context(scontext)
scon = context(scontext)
self.fcontextTypeEntry.set_text(scon.type)
self.fcontextMLSEntry.set_text(scon.mls)
type=store.get_value(iter, FTYPE_COL)
liststore=self.fcontextFileTypeCombo.get_model()
type = store.get_value(iter, FTYPE_COL)
liststore = self.fcontextFileTypeCombo.get_model()
iter = liststore.get_iter_first()
while iter != None and liststore.get_value(iter,0) != type:
while iter != None and liststore.get_value(iter, 0) != type:
iter = liststore.iter_next(iter)
if iter != None:
self.fcontextFileTypeCombo.set_active_iter(iter)
@ -171,8 +174,8 @@ class fcontextPage(semanagePage):
def delete(self):
store, iter = self.view.get_selection().get_selected()
try:
fspec=store.get_value(iter, SPEC_COL)
ftype=store.get_value(iter, FTYPE_COL)
fspec = store.get_value(iter, SPEC_COL)
ftype = store.get_value(iter, FTYPE_COL)
self.wait()
(rc, out) = commands.getstatusoutput("semanage fcontext -d -f '%s' '%s'" % (ftype, fspec))
self.ready()
@ -180,16 +183,16 @@ class fcontextPage(semanagePage):
if rc != 0:
return self.error(out)
store.remove(iter)
self.view.get_selection().select_path ((0,))
self.view.get_selection().select_path((0,))
except ValueError, e:
self.error(e.args[0])
def add(self):
ftype=["", "--", "-d", "-c", "-b", "-s", "-l", "-p" ]
fspec=self.fcontextEntry.get_text().strip()
type=self.fcontextTypeEntry.get_text().strip()
mls=self.fcontextMLSEntry.get_text().strip()
list_model=self.fcontextFileTypeCombo.get_model()
ftype = ["", "--", "-d", "-c", "-b", "-s", "-l", "-p"]
fspec = self.fcontextEntry.get_text().strip()
type = self.fcontextTypeEntry.get_text().strip()
mls = self.fcontextMLSEntry.get_text().strip()
list_model = self.fcontextFileTypeCombo.get_model()
active = self.fcontextFileTypeCombo.get_active()
self.wait()
(rc, out) = commands.getstatusoutput("semanage fcontext -a -t %s -r %s -f '%s' '%s'" % (type, mls, ftype[active], fspec))
@ -198,18 +201,18 @@ class fcontextPage(semanagePage):
self.error(out)
return False
iter=self.store.append()
iter = self.store.append()
self.store.set_value(iter, SPEC_COL, fspec)
self.store.set_value(iter, FTYPE_COL, ftype)
self.store.set_value(iter, TYPE_COL, "%s:%s" % (type, mls))
def modify(self):
fspec=self.fcontextEntry.get_text().strip()
type=self.fcontextTypeEntry.get_text().strip()
mls=self.fcontextMLSEntry.get_text().strip()
list_model=self.fcontextFileTypeCombo.get_model()
fspec = self.fcontextEntry.get_text().strip()
type = self.fcontextTypeEntry.get_text().strip()
mls = self.fcontextMLSEntry.get_text().strip()
list_model = self.fcontextFileTypeCombo.get_model()
iter = self.fcontextFileTypeCombo.get_active_iter()
ftype=list_model.get_value(iter,0)
ftype = list_model.get_value(iter, 0)
self.wait()
(rc, out) = commands.getstatusoutput("semanage fcontext -m -t %s -r %s -f '%s' '%s'" % (type, mls, ftype, fspec))
self.ready()

View File

@ -34,7 +34,9 @@ import StringIO
#------------------------------------------------------------------------------
class TextWriter(Formatter.DumbWriter):
def __init__(self, file=None, maxcol=80, indent_width=4):
Formatter.DumbWriter.__init__(self, file, maxcol)
self.indent_level = 0
@ -58,7 +60,8 @@ class TextWriter(Formatter.DumbWriter):
self.send_literal_data(' ' * offset + data)
def send_flowing_data(self, data):
if not data: return
if not data:
return
atbreak = self.atbreak or data[0] in string.whitespace
col = self.col
maxcol = self.maxcol
@ -81,6 +84,7 @@ class TextWriter(Formatter.DumbWriter):
self.col = col
self.atbreak = data[-1] in string.whitespace
class HTMLParserAnchor(htmllib.HTMLParser):
def __init__(self, formatter, verbose=0):
@ -96,9 +100,11 @@ class HTMLParserAnchor(htmllib.HTMLParser):
#------------------------------------------------------------------------------
def escape_html(s):
if s is None: return None
s = s.replace("&", "&amp;") # Must be done first!
if s is None:
return None
s = s.replace("&", "&amp;") # Must be done first!
s = s.replace("<", "&lt;")
s = s.replace(">", "&gt;")
s = s.replace("'", "&apos;")
@ -107,16 +113,18 @@ def escape_html(s):
def unescape_html(s):
if s is None: return None
if s is None:
return None
if '&' not in s:
return s
s = s.replace("&lt;", "<")
s = s.replace("&gt;", ">")
s = s.replace("&apos;", "'")
s = s.replace("&quot;", '"')
s = s.replace("&amp;", "&") # Must be last
s = s.replace("&amp;", "&") # Must be last
return s
def html_to_text(html, maxcol=80):
try:
buffer = StringIO.StringIO()
@ -131,6 +139,7 @@ def html_to_text(html, maxcol=80):
log_program.error('cannot convert html to text: %s' % e)
return None
def html_document(*body_components):
'''Wrap the body components in a HTML document structure with a valid header.
Accepts a variable number of arguments of of which canb be:

View File

@ -24,12 +24,12 @@ import gobject
import sys
import commands
import seobject
from semanagePage import *;
from semanagePage import *
##
## I18N
##
PROGNAME="policycoreutils"
PROGNAME = "policycoreutils"
import gettext
gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
gettext.textdomain(PROGNAME)
@ -37,26 +37,28 @@ try:
gettext.install(PROGNAME,
localedir="/usr/share/locale",
unicode=False,
codeset = 'utf-8')
codeset='utf-8')
except IOError:
import __builtin__
__builtin__.__dict__['_'] = unicode
class loginsPage(semanagePage):
def __init__(self, xml):
self.firstTime = False
semanagePage.__init__(self, xml, "logins", _("User Mapping"))
self.store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
self.view.set_model(self.store)
self.store.set_sort_column_id(0, gtk.SORT_ASCENDING)
col = gtk.TreeViewColumn(_("Login\nName"), gtk.CellRendererText(), text = 0)
col = gtk.TreeViewColumn(_("Login\nName"), gtk.CellRendererText(), text=0)
col.set_sort_column_id(0)
col.set_resizable(True)
self.view.append_column(col)
col = gtk.TreeViewColumn(_("SELinux\nUser"), gtk.CellRendererText(), text = 1)
col = gtk.TreeViewColumn(_("SELinux\nUser"), gtk.CellRendererText(), text=1)
col.set_resizable(True)
self.view.append_column(col)
col = gtk.TreeViewColumn(_("MLS/\nMCS Range"), gtk.CellRendererText(), text = 2)
col = gtk.TreeViewColumn(_("MLS/\nMCS Range"), gtk.CellRendererText(), text=2)
col.set_resizable(True)
self.view.append_column(col)
self.load()
@ -64,8 +66,8 @@ class loginsPage(semanagePage):
self.loginsSelinuxUserCombo = xml.get_widget("loginsSelinuxUserCombo")
self.loginsMLSEntry = xml.get_widget("loginsMLSEntry")
def load(self, filter = ""):
self.filter=filter
def load(self, filter=""):
self.filter = filter
self.login = seobject.loginRecords()
dict = self.login.get_all(0)
keys = dict.keys()
@ -79,7 +81,7 @@ class loginsPage(semanagePage):
self.store.set_value(iter, 0, k)
self.store.set_value(iter, 1, dict[k][0])
self.store.set_value(iter, 2, range)
self.view.get_selection().select_path ((0,))
self.view.get_selection().select_path((0,))
def __dialogSetup(self):
if self.firstTime == True:
@ -99,7 +101,7 @@ class loginsPage(semanagePage):
self.loginsSelinuxUserCombo.append_text(k)
iter = liststore.get_iter_first()
while liststore.get_value(iter,0) != "user_u":
while liststore.get_value(iter, 0) != "user_u":
iter = liststore.iter_next(iter)
self.loginsSelinuxUserCombo.set_active_iter(iter)
@ -113,12 +115,11 @@ class loginsPage(semanagePage):
seuser = store.get_value(iter, 1)
liststore = self.loginsSelinuxUserCombo.get_model()
iter = liststore.get_iter_first()
while iter != None and liststore.get_value(iter,0) != seuser:
while iter != None and liststore.get_value(iter, 0) != seuser:
iter = liststore.iter_next(iter)
if iter != None:
self.loginsSelinuxUserCombo.set_active_iter(iter)
def dialogClear(self):
self.__dialogSetup()
self.loginsNameEntry.set_text("")
@ -128,7 +129,7 @@ class loginsPage(semanagePage):
def delete(self):
store, iter = self.view.get_selection().get_selected()
try:
login=store.get_value(iter, 0)
login = store.get_value(iter, 0)
if login == "root" or login == "__default__":
raise ValueError(_("Login '%s' is required") % login)
@ -139,18 +140,18 @@ class loginsPage(semanagePage):
self.error(out)
return False
store.remove(iter)
self.view.get_selection().select_path ((0,))
self.view.get_selection().select_path((0,))
except ValueError, e:
self.error(e.args[0])
def add(self):
target=self.loginsNameEntry.get_text().strip()
serange=self.loginsMLSEntry.get_text().strip()
target = self.loginsNameEntry.get_text().strip()
serange = self.loginsMLSEntry.get_text().strip()
if serange == "":
serange="s0"
list_model=self.loginsSelinuxUserCombo.get_model()
serange = "s0"
list_model = self.loginsSelinuxUserCombo.get_model()
iter = self.loginsSelinuxUserCombo.get_active_iter()
seuser = list_model.get_value(iter,0)
seuser = list_model.get_value(iter, 0)
self.wait()
(rc, out) = commands.getstatusoutput("semanage login -a -s %s -r %s %s" % (seuser, serange, target))
self.ready()
@ -164,13 +165,13 @@ class loginsPage(semanagePage):
self.store.set_value(iter, 2, seobject.translate(serange))
def modify(self):
target=self.loginsNameEntry.get_text().strip()
serange=self.loginsMLSEntry.get_text().strip()
target = self.loginsNameEntry.get_text().strip()
serange = self.loginsMLSEntry.get_text().strip()
if serange == "":
serange = "s0"
list_model = self.loginsSelinuxUserCombo.get_model()
iter = self.loginsSelinuxUserCombo.get_active_iter()
seuser=list_model.get_value(iter,0)
seuser = list_model.get_value(iter, 0)
self.wait()
(rc, out) = commands.getstatusoutput("semanage login -m -s %s -r %s %s" % (seuser, serange, target))
self.ready()

View File

@ -27,7 +27,7 @@ import seobject
##
## I18N
##
PROGNAME="policycoreutils"
PROGNAME = "policycoreutils"
import gettext
gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
gettext.textdomain(PROGNAME)
@ -35,12 +35,14 @@ try:
gettext.install(PROGNAME,
localedir="/usr/share/locale",
unicode=False,
codeset = 'utf-8')
codeset='utf-8')
except IOError:
import __builtin__
__builtin__.__dict__['_'] = unicode
class loginsPage:
def __init__(self, xml):
self.xml = xml
self.view = xml.get_widget("mappingsView")

View File

@ -25,13 +25,13 @@ import gobject
import sys
import seobject
import selinux
from semanagePage import *;
from semanagePage import *
from subprocess import Popen, PIPE
##
## I18N
##
PROGNAME="policycoreutils"
PROGNAME = "policycoreutils"
import gettext
gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
gettext.textdomain(PROGNAME)
@ -39,12 +39,14 @@ try:
gettext.install(PROGNAME,
localedir="/usr/share/locale",
unicode=False,
codeset = 'utf-8')
codeset='utf-8')
except IOError:
import __builtin__
__builtin__.__dict__['_'] = unicode
class modulesPage(semanagePage):
def __init__(self, xml):
semanagePage.__init__(self, xml, "modules", _("Policy Module"))
self.module_filter = xml.get_widget("modulesFilterEntry")
@ -55,12 +57,12 @@ class modulesPage(semanagePage):
self.store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
self.view.set_model(self.store)
self.store.set_sort_column_id(0, gtk.SORT_ASCENDING)
col = gtk.TreeViewColumn(_("Module Name"), gtk.CellRendererText(), text = 0)
col = gtk.TreeViewColumn(_("Module Name"), gtk.CellRendererText(), text=0)
col.set_sort_column_id(0)
col.set_resizable(True)
self.view.append_column(col)
self.store.set_sort_column_id(0, gtk.SORT_ASCENDING)
col = gtk.TreeViewColumn(_("Version"), gtk.CellRendererText(), text = 1)
col = gtk.TreeViewColumn(_("Version"), gtk.CellRendererText(), text=1)
self.enable_audit_button = xml.get_widget("enableAuditButton")
self.enable_audit_button.connect("clicked", self.enable_audit)
self.new_button = xml.get_widget("newModuleButton")
@ -68,15 +70,15 @@ class modulesPage(semanagePage):
col.set_sort_column_id(1)
col.set_resizable(True)
self.view.append_column(col)
self.store.set_sort_func(1,self.sort_int, "")
self.store.set_sort_func(1, self.sort_int, "")
status, self.policy_type = selinux.selinux_getpolicytype()
self.load()
def sort_int(self, treemodel, iter1, iter2, user_data):
try:
p1 = int(treemodel.get_value(iter1,1))
p2 = int(treemodel.get_value(iter1,1))
p1 = int(treemodel.get_value(iter1, 1))
p2 = int(treemodel.get_value(iter1, 1))
if p1 > p2:
return 1
if p1 == p2:
@ -86,7 +88,7 @@ class modulesPage(semanagePage):
return 0
def load(self, filter=""):
self.filter=filter
self.filter = filter
self.store.clear()
try:
fd = Popen("semodule -l", shell=True, stdout=PIPE).stdout
@ -101,8 +103,7 @@ class modulesPage(semanagePage):
self.store.set_value(iter, 1, ver.strip())
except:
pass
self.view.get_selection().select_path ((0,))
self.view.get_selection().select_path((0,))
def new_module(self, args):
try:
@ -121,7 +122,7 @@ class modulesPage(semanagePage):
self.error(output)
else:
store.remove(iter)
self.view.get_selection().select_path ((0,))
self.view.get_selection().select_path((0,))
except ValueError, e:
self.error(e.args[0])
@ -131,10 +132,10 @@ class modulesPage(semanagePage):
try:
self.wait()
if self.audit_enabled:
status, output =commands.getstatusoutput("semodule -DB")
status, output = commands.getstatusoutput("semodule -DB")
button.set_label(_("Disable Audit"))
else:
status, output =commands.getstatusoutput("semodule -B")
status, output = commands.getstatusoutput("semodule -B")
button.set_label(_("Enable Audit"))
self.ready()
@ -147,7 +148,7 @@ class modulesPage(semanagePage):
def disable_audit(self, button):
try:
self.wait()
status, output =commands.getstatusoutput("semodule -B")
status, output = commands.getstatusoutput("semodule -B")
self.ready()
if status != 0:
self.error(output)
@ -180,7 +181,7 @@ class modulesPage(semanagePage):
def add(self, file):
try:
self.wait()
status, output =commands.getstatusoutput("semodule -i %s" % file)
status, output = commands.getstatusoutput("semodule -i %s" % file)
self.ready()
if status != 0:
self.error(output)

View File

@ -30,7 +30,7 @@ import gnome
import sys
try:
from sepolicy import generate
except ValueError,e:
except ValueError, e:
sys.stderr.write("%s: %s\n" % (e.__class__.__name__, str(e)))
sys.exit(1)
@ -39,10 +39,11 @@ import commands
import re
def get_all_modules():
try:
all_modules = []
rc, output=commands.getstatusoutput("semodule -l 2>/dev/null")
rc, output = commands.getstatusoutput("semodule -l 2>/dev/null")
if rc == 0:
l = output.split("\n")
for i in l:
@ -56,7 +57,7 @@ def get_all_modules():
##
## I18N
##
PROGNAME="policycoreutils"
PROGNAME = "policycoreutils"
import gettext
gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
@ -65,7 +66,7 @@ try:
gettext.install(PROGNAME,
localedir="/usr/share/locale",
unicode=False,
codeset = 'utf-8')
codeset='utf-8')
except IOError:
import __builtin__
__builtin__.__dict__['_'] = unicode
@ -78,6 +79,8 @@ sys.path.append('/usr/share/system-config-selinux')
sys.path.append('.')
# From John Hunter http://www.daa.com.au/pipermail/pygtk/2003-February/004454.html
def foreach(model, path, iter, selected):
selected.append(model.get_value(iter, 0))
@ -85,13 +88,14 @@ def foreach(model, path, iter, selected):
## Pull in the Glade file
##
if os.access("polgen.glade", os.F_OK):
xml = gtk.glade.XML ("polgen.glade", domain=PROGNAME)
xml = gtk.glade.XML("polgen.glade", domain=PROGNAME)
else:
xml = gtk.glade.XML ("/usr/share/system-config-selinux/polgen.glade", domain=PROGNAME)
xml = gtk.glade.XML("/usr/share/system-config-selinux/polgen.glade", domain=PROGNAME)
FILE = 1
DIR = 2
class childWindow:
START_PAGE = 0
SELECT_TYPE_PAGE = 0
@ -111,82 +115,82 @@ class childWindow:
def __init__(self):
self.xml = xml
self.notebook = xml.get_widget ("notebook")
self.notebook = xml.get_widget("notebook")
self.label_dict = {}
self.tooltip_dict = {}
label = xml.get_widget ("select_label")
label = xml.get_widget("select_label")
self.label_dict[label] = label.get_text()
label = xml.get_widget ("select_user_roles_label")
label = xml.get_widget("select_user_roles_label")
self.label_dict[label] = label.get_text()
label = xml.get_widget ("select_dir_label")
label = xml.get_widget("select_dir_label")
self.label_dict[label] = label.get_text()
label = xml.get_widget ("select_domain_admin_label")
label = xml.get_widget("select_domain_admin_label")
self.label_dict[label] = label.get_text()
label = xml.get_widget ("select_in_label")
label = xml.get_widget("select_in_label")
self.label_dict[label] = label.get_text()
label = xml.get_widget ("select_out_label")
label = xml.get_widget("select_out_label")
self.label_dict[label] = label.get_text()
label = xml.get_widget ("select_common_label")
label = xml.get_widget("select_common_label")
self.label_dict[label] = label.get_text()
label = xml.get_widget ("select_manages_label")
label = xml.get_widget("select_manages_label")
self.label_dict[label] = label.get_text()
label = xml.get_widget ("select_booleans_label")
label = xml.get_widget("select_booleans_label")
self.label_dict[label] = label.get_text()
label = xml.get_widget ("existing_user_treeview")
label = xml.get_widget("existing_user_treeview")
self.tooltip_dict[label] = label.get_tooltip_text()
label = xml.get_widget ("transition_treeview")
label = xml.get_widget("transition_treeview")
self.tooltip_dict[label] = label.get_tooltip_text()
label = xml.get_widget ("in_tcp_all_checkbutton")
label = xml.get_widget("in_tcp_all_checkbutton")
self.tooltip_dict[label] = label.get_tooltip_text()
label = xml.get_widget ("in_tcp_reserved_checkbutton")
label = xml.get_widget("in_tcp_reserved_checkbutton")
self.tooltip_dict[label] = label.get_tooltip_text()
label = xml.get_widget ("in_tcp_unreserved_checkbutton")
label = xml.get_widget("in_tcp_unreserved_checkbutton")
self.tooltip_dict[label] = label.get_tooltip_text()
label = xml.get_widget ("in_tcp_entry")
label = xml.get_widget("in_tcp_entry")
self.tooltip_dict[label] = label.get_tooltip_text()
label = xml.get_widget ("in_udp_all_checkbutton")
label = xml.get_widget("in_udp_all_checkbutton")
self.tooltip_dict[label] = label.get_tooltip_text()
label = xml.get_widget ("in_udp_reserved_checkbutton")
label = xml.get_widget("in_udp_reserved_checkbutton")
self.tooltip_dict[label] = label.get_tooltip_text()
label = xml.get_widget ("in_udp_unreserved_checkbutton")
label = xml.get_widget("in_udp_unreserved_checkbutton")
self.tooltip_dict[label] = label.get_tooltip_text()
label = xml.get_widget ("in_udp_entry")
label = xml.get_widget("in_udp_entry")
self.tooltip_dict[label] = label.get_tooltip_text()
label = xml.get_widget ("out_tcp_entry")
label = xml.get_widget("out_tcp_entry")
self.tooltip_dict[label] = label.get_tooltip_text()
label = xml.get_widget ("out_udp_entry")
label = xml.get_widget("out_udp_entry")
self.tooltip_dict[label] = label.get_tooltip_text()
label = xml.get_widget ("out_tcp_all_checkbutton")
label = xml.get_widget("out_tcp_all_checkbutton")
self.tooltip_dict[label] = label.get_tooltip_text()
label = xml.get_widget ("out_udp_all_checkbutton")
label = xml.get_widget("out_udp_all_checkbutton")
self.tooltip_dict[label] = label.get_tooltip_text()
label = xml.get_widget ("boolean_treeview")
label = xml.get_widget("boolean_treeview")
self.tooltip_dict[label] = label.get_tooltip_text()
label = xml.get_widget ("write_treeview")
label = xml.get_widget("write_treeview")
self.tooltip_dict[label] = label.get_tooltip_text()
try:
@ -201,7 +205,7 @@ class childWindow:
self.all_users = []
self.error(str(e))
self.name=""
self.name = ""
xml.signal_connect("on_delete_clicked", self.delete)
xml.signal_connect("on_delete_boolean_clicked", self.delete_boolean)
xml.signal_connect("on_exec_select_clicked", self.exec_select)
@ -210,68 +214,67 @@ class childWindow:
xml.signal_connect("on_add_boolean_clicked", self.add_boolean)
xml.signal_connect("on_add_dir_clicked", self.add_dir)
xml.signal_connect("on_about_clicked", self.on_about_clicked)
xml.get_widget ("cancel_button").connect("clicked",self.quit)
self.forward_button = xml.get_widget ("forward_button")
self.forward_button.connect("clicked",self.forward)
self.back_button = xml.get_widget ("back_button")
self.back_button.connect("clicked",self.back)
xml.get_widget("cancel_button").connect("clicked", self.quit)
self.forward_button = xml.get_widget("forward_button")
self.forward_button.connect("clicked", self.forward)
self.back_button = xml.get_widget("back_button")
self.back_button.connect("clicked", self.back)
self.boolean_dialog = xml.get_widget ("boolean_dialog")
self.boolean_name_entry = xml.get_widget ("boolean_name_entry")
self.boolean_description_entry = xml.get_widget ("boolean_description_entry")
self.boolean_dialog = xml.get_widget("boolean_dialog")
self.boolean_name_entry = xml.get_widget("boolean_name_entry")
self.boolean_description_entry = xml.get_widget("boolean_description_entry")
self.pages={}
self.pages = {}
for i in generate.USERS:
self.pages[i] = [ self.SELECT_TYPE_PAGE, self.APP_PAGE, self.TRANSITION_PAGE, self.ROLE_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE ]
self.pages[generate.RUSER] = [ self.SELECT_TYPE_PAGE, self.APP_PAGE, self.ADMIN_PAGE, self.USER_TRANSITION_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE ]
self.pages[generate.LUSER] = [ self.SELECT_TYPE_PAGE, self.APP_PAGE, self.TRANSITION_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE ]
self.pages[generate.SANDBOX] = [ self.SELECT_TYPE_PAGE, self.APP_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE]
self.pages[generate.EUSER] = [ self.SELECT_TYPE_PAGE, self.EXISTING_USER_PAGE, self.TRANSITION_PAGE, self.ROLE_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE ]
self.pages[i] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.TRANSITION_PAGE, self.ROLE_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE]
self.pages[generate.RUSER] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.ADMIN_PAGE, self.USER_TRANSITION_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE]
self.pages[generate.LUSER] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.TRANSITION_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE]
self.pages[generate.SANDBOX] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE]
self.pages[generate.EUSER] = [self.SELECT_TYPE_PAGE, self.EXISTING_USER_PAGE, self.TRANSITION_PAGE, self.ROLE_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE]
for i in generate.APPLICATIONS:
self.pages[i] = [ self.SELECT_TYPE_PAGE, self.APP_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.COMMON_APPS_PAGE, self.FILES_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE]
self.pages[generate.USER] = [ self.SELECT_TYPE_PAGE, self.APP_PAGE, self.USER_TRANSITION_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.COMMON_APPS_PAGE, self.FILES_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE ]
self.pages[i] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.COMMON_APPS_PAGE, self.FILES_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE]
self.pages[generate.USER] = [self.SELECT_TYPE_PAGE, self.APP_PAGE, self.USER_TRANSITION_PAGE, self.IN_NET_PAGE, self.OUT_NET_PAGE, self.COMMON_APPS_PAGE, self.FILES_PAGE, self.BOOLEAN_PAGE, self.SELECT_DIR_PAGE]
self.current_page = 0
self.back_button.set_sensitive(0)
self.network_buttons = {}
self.in_tcp_all_checkbutton = xml.get_widget ("in_tcp_all_checkbutton")
self.in_tcp_reserved_checkbutton = xml.get_widget ("in_tcp_reserved_checkbutton")
self.in_tcp_unreserved_checkbutton = xml.get_widget ("in_tcp_unreserved_checkbutton")
self.in_tcp_all_checkbutton = xml.get_widget("in_tcp_all_checkbutton")
self.in_tcp_reserved_checkbutton = xml.get_widget("in_tcp_reserved_checkbutton")
self.in_tcp_unreserved_checkbutton = xml.get_widget("in_tcp_unreserved_checkbutton")
self.in_tcp_entry = self.xml.get_widget("in_tcp_entry")
self.network_buttons[self.in_tcp_all_checkbutton] = [ self.in_tcp_reserved_checkbutton, self.in_tcp_unreserved_checkbutton, self.in_tcp_entry ]
self.network_buttons[self.in_tcp_all_checkbutton] = [self.in_tcp_reserved_checkbutton, self.in_tcp_unreserved_checkbutton, self.in_tcp_entry]
self.out_tcp_all_checkbutton = xml.get_widget ("out_tcp_all_checkbutton")
self.out_tcp_reserved_checkbutton = xml.get_widget ("out_tcp_reserved_checkbutton")
self.out_tcp_unreserved_checkbutton = xml.get_widget ("out_tcp_unreserved_checkbutton")
self.out_tcp_all_checkbutton = xml.get_widget("out_tcp_all_checkbutton")
self.out_tcp_reserved_checkbutton = xml.get_widget("out_tcp_reserved_checkbutton")
self.out_tcp_unreserved_checkbutton = xml.get_widget("out_tcp_unreserved_checkbutton")
self.out_tcp_entry = self.xml.get_widget("out_tcp_entry")
self.network_buttons[self.out_tcp_all_checkbutton] = [ self.out_tcp_entry ]
self.network_buttons[self.out_tcp_all_checkbutton] = [self.out_tcp_entry]
self.in_udp_all_checkbutton = xml.get_widget ("in_udp_all_checkbutton")
self.in_udp_reserved_checkbutton = xml.get_widget ("in_udp_reserved_checkbutton")
self.in_udp_unreserved_checkbutton = xml.get_widget ("in_udp_unreserved_checkbutton")
self.in_udp_all_checkbutton = xml.get_widget("in_udp_all_checkbutton")
self.in_udp_reserved_checkbutton = xml.get_widget("in_udp_reserved_checkbutton")
self.in_udp_unreserved_checkbutton = xml.get_widget("in_udp_unreserved_checkbutton")
self.in_udp_entry = self.xml.get_widget("in_udp_entry")
self.network_buttons[self.in_udp_all_checkbutton] = [ self.in_udp_reserved_checkbutton, self.in_udp_unreserved_checkbutton, self.in_udp_entry ]
self.network_buttons[self.in_udp_all_checkbutton] = [self.in_udp_reserved_checkbutton, self.in_udp_unreserved_checkbutton, self.in_udp_entry]
self.out_udp_all_checkbutton = xml.get_widget ("out_udp_all_checkbutton")
self.out_udp_all_checkbutton = xml.get_widget("out_udp_all_checkbutton")
self.out_udp_entry = self.xml.get_widget("out_udp_entry")
self.network_buttons[self.out_udp_all_checkbutton] = [ self.out_udp_entry ]
self.network_buttons[self.out_udp_all_checkbutton] = [self.out_udp_entry]
for b in self.network_buttons.keys():
b.connect("clicked",self.network_all_clicked)
b.connect("clicked", self.network_all_clicked)
self.boolean_treeview = self.xml.get_widget("boolean_treeview")
self.boolean_store = gtk.ListStore(gobject.TYPE_STRING,gobject.TYPE_STRING)
self.boolean_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
self.boolean_treeview.set_model(self.boolean_store)
self.boolean_store.set_sort_column_id(0, gtk.SORT_ASCENDING)
col = gtk.TreeViewColumn(_("Name"), gtk.CellRendererText(), text = 0)
col = gtk.TreeViewColumn(_("Name"), gtk.CellRendererText(), text=0)
self.boolean_treeview.append_column(col)
col = gtk.TreeViewColumn(_("Description"), gtk.CellRendererText(), text = 1)
col = gtk.TreeViewColumn(_("Description"), gtk.CellRendererText(), text=1)
self.boolean_treeview.append_column(col)
self.role_treeview = self.xml.get_widget("role_treeview")
@ -279,28 +282,28 @@ class childWindow:
self.role_treeview.set_model(self.role_store)
self.role_treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
self.role_store.set_sort_column_id(0, gtk.SORT_ASCENDING)
col = gtk.TreeViewColumn(_("Role"), gtk.CellRendererText(), text = 0)
col = gtk.TreeViewColumn(_("Role"), gtk.CellRendererText(), text=0)
self.role_treeview.append_column(col)
self.existing_user_treeview = self.xml.get_widget("existing_user_treeview")
self.existing_user_store = gtk.ListStore(gobject.TYPE_STRING)
self.existing_user_treeview.set_model(self.existing_user_store)
self.existing_user_store.set_sort_column_id(0, gtk.SORT_ASCENDING)
col = gtk.TreeViewColumn(_("Existing_User"), gtk.CellRendererText(), text = 0)
col = gtk.TreeViewColumn(_("Existing_User"), gtk.CellRendererText(), text=0)
self.existing_user_treeview.append_column(col)
for i in self.all_roles:
iter = self.role_store.append()
self.role_store.set_value(iter, 0, i[:-2])
self.in_tcp_reserved_checkbutton = xml.get_widget ("in_tcp_reserved_checkbutton")
self.in_tcp_reserved_checkbutton = xml.get_widget("in_tcp_reserved_checkbutton")
self.transition_treeview = self.xml.get_widget("transition_treeview")
self.transition_store = gtk.ListStore(gobject.TYPE_STRING)
self.transition_treeview.set_model(self.transition_store)
self.transition_treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
self.transition_store.set_sort_column_id(0, gtk.SORT_ASCENDING)
col = gtk.TreeViewColumn(_("Application"), gtk.CellRendererText(), text = 0)
col = gtk.TreeViewColumn(_("Application"), gtk.CellRendererText(), text=0)
self.transition_treeview.append_column(col)
self.user_transition_treeview = self.xml.get_widget("user_transition_treeview")
@ -308,7 +311,7 @@ class childWindow:
self.user_transition_treeview.set_model(self.user_transition_store)
self.user_transition_treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
self.user_transition_store.set_sort_column_id(0, gtk.SORT_ASCENDING)
col = gtk.TreeViewColumn(_("Application"), gtk.CellRendererText(), text = 0)
col = gtk.TreeViewColumn(_("Application"), gtk.CellRendererText(), text=0)
self.user_transition_treeview.append_column(col)
for i in self.all_users:
@ -322,7 +325,7 @@ class childWindow:
self.admin_treeview.set_model(self.admin_store)
self.admin_treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
self.admin_store.set_sort_column_id(0, gtk.SORT_ASCENDING)
col = gtk.TreeViewColumn(_("Application"), gtk.CellRendererText(), text = 0)
col = gtk.TreeViewColumn(_("Application"), gtk.CellRendererText(), text=0)
self.admin_treeview.append_column(col)
try:
@ -333,7 +336,7 @@ class childWindow:
for a in sepolicy.interface.get_admin():
iter = self.admin_store.append()
self.admin_store.set_value(iter, 0, a)
except ValueError,e:
except ValueError, e:
self.error(e.message)
def confine_application(self):
@ -367,19 +370,19 @@ class childWindow:
if self.pages[type][self.current_page] == self.SELECT_DIR_PAGE:
outputdir = self.output_entry.get_text()
if not os.path.isdir(outputdir):
self.error(_("%s must be a directory") % outputdir )
self.error(_("%s must be a directory") % outputdir)
return False
if self.pages[type][self.current_page] == self.FINISH_PAGE:
self.generate_policy()
self.xml.get_widget ("cancel_button").set_label(gtk.STOCK_CLOSE)
self.xml.get_widget("cancel_button").set_label(gtk.STOCK_CLOSE)
else:
self.current_page = self.current_page + 1
self.notebook.set_current_page(self.pages[type][self.current_page])
if self.pages[type][self.current_page] == self.FINISH_PAGE:
self.forward_button.set_label(gtk.STOCK_APPLY)
def back(self,arg):
def back(self, arg):
type = self.get_type()
if self.pages[type][self.current_page] == self.FINISH_PAGE:
self.forward_button.set_label(gtk.STOCK_GO_FORWARD)
@ -394,7 +397,7 @@ class childWindow:
for b in self.network_buttons[button]:
b.set_sensitive(not active)
def verify(self, message, title="" ):
def verify(self, message, title=""):
dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO,
gtk.BUTTONS_YES_NO,
message)
@ -461,12 +464,12 @@ class childWindow:
def generate_policy(self, *args):
outputdir = self.output_entry.get_text()
try:
my_policy=generate.policy(self.get_name(), self.get_type())
my_policy = generate.policy(self.get_name(), self.get_type())
iter= self.boolean_store.get_iter_first()
iter = self.boolean_store.get_iter_first()
while(iter):
my_policy.add_boolean(self.boolean_store.get_value(iter, 0), self.boolean_store.get_value(iter, 1))
iter= self.boolean_store.iter_next(iter)
iter = self.boolean_store.iter_next(iter)
if self.get_type() in generate.APPLICATIONS:
my_policy.set_program(self.exec_entry.get_text())
@ -509,13 +512,13 @@ class childWindow:
my_policy.set_out_tcp(self.out_tcp_all_checkbutton.get_active(), self.out_tcp_entry.get_text())
my_policy.set_out_udp(self.out_udp_all_checkbutton.get_active(), self.out_udp_entry.get_text())
iter= self.store.get_iter_first()
iter = self.store.get_iter_first()
while(iter):
if self.store.get_value(iter, 1) == FILE:
my_policy.add_file(self.store.get_value(iter, 0))
else:
my_policy.add_dir(self.store.get_value(iter, 0))
iter= self.store.iter_next(iter)
iter = self.store.iter_next(iter)
self.info(my_policy.generate(outputdir))
return False
@ -526,15 +529,15 @@ class childWindow:
store, iter = self.view.get_selection().get_selected()
if iter != None:
store.remove(iter)
self.view.get_selection().select_path ((0,))
self.view.get_selection().select_path((0,))
def delete_boolean(self, args):
store, iter = self.boolean_treeview.get_selection().get_selected()
if iter != None:
store.remove(iter)
self.boolean_treeview.get_selection().select_path ((0,))
self.boolean_treeview.get_selection().select_path((0,))
def add_boolean(self,type):
def add_boolean(self, type):
self.boolean_name_entry.set_text("")
self.boolean_description_entry.set_text("")
rc = self.boolean_dialog.run()
@ -545,7 +548,7 @@ class childWindow:
self.boolean_store.set_value(iter, 0, self.boolean_name_entry.get_text())
self.boolean_store.set_value(iter, 1, self.boolean_description_entry.get_text())
def __add(self,type):
def __add(self, type):
rc = self.file_dialog.run()
self.file_dialog.hide()
if rc == gtk.RESPONSE_CANCEL:
@ -592,9 +595,9 @@ class childWindow:
self.__add(DIR)
def on_about_clicked(self, args):
dlg = xml.get_widget ("about_dialog")
dlg.run ()
dlg.hide ()
dlg = xml.get_widget("about_dialog")
dlg.run()
dlg.hide()
def quit(self, args):
gtk.main_quit()
@ -605,15 +608,15 @@ class childWindow:
self.druid = self.xml.get_widget("druid")
self.type = 0
self.name_entry = self.xml.get_widget("name_entry")
self.name_entry.connect("insert_text",self.on_name_entry_changed)
self.name_entry.connect("focus_out_event",self.on_focus_out_event)
self.name_entry.connect("insert_text", self.on_name_entry_changed)
self.name_entry.connect("focus_out_event", self.on_focus_out_event)
self.exec_entry = self.xml.get_widget("exec_entry")
self.exec_button = self.xml.get_widget("exec_button")
self.init_script_entry = self.xml.get_widget("init_script_entry")
self.init_script_button = self.xml.get_widget("init_script_button")
self.output_entry = self.xml.get_widget("output_entry")
self.output_entry.set_text(os.getcwd())
self.xml.get_widget("output_button").connect("clicked",self.output_button_clicked)
self.xml.get_widget("output_button").connect("clicked", self.output_button_clicked)
self.xwindows_user_radiobutton = self.xml.get_widget("xwindows_user_radiobutton")
self.terminal_user_radiobutton = self.xml.get_widget("terminal_user_radiobutton")
@ -641,10 +644,10 @@ class childWindow:
self.store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_INT)
self.view.set_model(self.store)
col = gtk.TreeViewColumn("", gtk.CellRendererText(), text = 0)
col = gtk.TreeViewColumn("", gtk.CellRendererText(), text=0)
col.set_resizable(True)
self.view.append_column(col)
self.view.get_selection().select_path ((0,))
self.view.get_selection().select_path((0,))
def output_button_clicked(self, *args):
self.file_dialog.set_title(_("Select directory to generate policy files in"))
@ -712,7 +715,7 @@ class childWindow:
return True
def on_name_page_next(self, *args):
name=self.name_entry.get_text()
name = self.name_entry.get_text()
if not name.isalnum():
self.error(_("You must add a name made up of letters and numbers and containing no spaces."))
return True
@ -730,7 +733,7 @@ class childWindow:
if exe == "":
self.error(_("You must enter a executable"))
return True
policy=generate.policy(name, self.get_type())
policy = generate.policy(name, self.get_type())
policy.set_program(exe)
policy.gen_writeable()
policy.gen_symbols()
@ -762,7 +765,7 @@ class childWindow:
gtk.main()
if __name__ == "__main__":
signal.signal (signal.SIGINT, signal.SIG_DFL)
signal.signal(signal.SIGINT, signal.SIG_DFL)
app = childWindow()
app.stand_alone()

View File

@ -24,7 +24,7 @@ import gobject
import sys
import seobject
import commands
from semanagePage import *;
from semanagePage import *
##
## I18N
@ -41,12 +41,14 @@ try:
gettext.install(PROGNAME,
localedir="/usr/share/locale",
unicode=False,
codeset = 'utf-8')
codeset='utf-8')
except IOError:
import __builtin__
__builtin__.__dict__['_'] = unicode
class portsPage(semanagePage):
def __init__(self, xml):
semanagePage.__init__(self, xml, "ports", _("Network Port"))
xml.signal_connect("on_group_clicked", self.on_group_clicked)
@ -69,7 +71,7 @@ class portsPage(semanagePage):
self.load()
def filter_changed(self, *arg):
filter = arg[0].get_text()
filter = arg[0].get_text()
if filter != self.filter:
if self.edit:
self.load(filter)
@ -77,37 +79,37 @@ class portsPage(semanagePage):
self.group_load(filter)
def init_store(self):
self.store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING , gobject.TYPE_STRING)
self.store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_STRING)
self.view.set_model(self.store)
self.store.set_sort_column_id(0, gtk.SORT_ASCENDING)
self.view.set_search_equal_func(self.search)
col = gtk.TreeViewColumn(_("SELinux Port\nType"), gtk.CellRendererText(), text = TYPE_COL)
col = gtk.TreeViewColumn(_("SELinux Port\nType"), gtk.CellRendererText(), text=TYPE_COL)
col.set_sort_column_id(TYPE_COL)
col.set_resizable(True)
self.view.append_column(col)
self.store.set_sort_column_id(TYPE_COL, gtk.SORT_ASCENDING)
col = gtk.TreeViewColumn(_("Protocol"), gtk.CellRendererText(), text = PROTOCOL_COL)
col = gtk.TreeViewColumn(_("Protocol"), gtk.CellRendererText(), text=PROTOCOL_COL)
col.set_sort_column_id(PROTOCOL_COL)
col.set_resizable(True)
self.view.append_column(col)
self.mls_col = gtk.TreeViewColumn(_("MLS/MCS\nLevel"), gtk.CellRendererText(), text = MLS_COL)
self.mls_col = gtk.TreeViewColumn(_("MLS/MCS\nLevel"), gtk.CellRendererText(), text=MLS_COL)
self.mls_col.set_resizable(True)
self.mls_col.set_sort_column_id(MLS_COL)
self.view.append_column(self.mls_col)
col = gtk.TreeViewColumn(_("Port"), gtk.CellRendererText(), text = PORT_COL)
col = gtk.TreeViewColumn(_("Port"), gtk.CellRendererText(), text=PORT_COL)
col.set_sort_column_id(PORT_COL)
col.set_resizable(True)
self.view.append_column(col)
self.store.set_sort_func(PORT_COL,self.sort_int, "")
self.store.set_sort_func(PORT_COL, self.sort_int, "")
def sort_int(self, treemodel, iter1, iter2, user_data):
try:
p1 = int(treemodel.get_value(iter1,PORT_COL).split('-')[0])
p2 = int(treemodel.get_value(iter2,PORT_COL).split('-')[0])
p1 = int(treemodel.get_value(iter1, PORT_COL).split('-')[0])
p2 = int(treemodel.get_value(iter2, PORT_COL).split('-')[0])
if p1 > p2:
return 1
if p1 == p2:
@ -116,8 +118,8 @@ class portsPage(semanagePage):
except:
return 0
def load(self,filter = ""):
self.filter=filter
def load(self, filter=""):
self.filter = filter
self.port = seobject.portRecords()
dict = self.port.get_all(self.local)
keys = dict.keys()
@ -135,10 +137,10 @@ class portsPage(semanagePage):
self.store.set_value(iter, TYPE_COL, dict[k][0])
self.store.set_value(iter, PROTOCOL_COL, k[2])
self.store.set_value(iter, MLS_COL, dict[k][1])
self.view.get_selection().select_path ((0,))
self.view.get_selection().select_path((0,))
def group_load(self, filter = ""):
self.filter=filter
def group_load(self, filter=""):
self.filter = filter
self.port = seobject.portRecords()
dict = self.port.get_all_by_type(self.local)
keys = dict.keys()
@ -146,14 +148,14 @@ class portsPage(semanagePage):
self.store.clear()
for k in keys:
ports_string = ", ".join(dict[k])
if not (self.match(ports_string, filter) or self.match(k[0], filter) or self.match(k[1], filter) ):
if not (self.match(ports_string, filter) or self.match(k[0], filter) or self.match(k[1], filter)):
continue
iter = self.store.append()
self.store.set_value(iter, TYPE_COL, k[0])
self.store.set_value(iter, PROTOCOL_COL, k[1])
self.store.set_value(iter, PORT_COL, ports_string)
self.store.set_value(iter, MLS_COL, "")
self.view.get_selection().select_path ((0,))
self.view.get_selection().select_path((0,))
def propertiesDialog(self):
if self.edit:
@ -169,7 +171,7 @@ class portsPage(semanagePage):
protocol = store.get_value(iter, PROTOCOL_COL)
liststore = self.ports_protocol_combo.get_model()
iter = liststore.get_iter_first()
while iter != None and liststore.get_value(iter,0) != protocol:
while iter != None and liststore.get_value(iter, 0) != protocol:
iter = liststore.iter_next(iter)
if iter != None:
self.ports_protocol_combo.set_active_iter(iter)
@ -192,7 +194,7 @@ class portsPage(semanagePage):
if rc != 0:
return self.error(out)
store.remove(iter)
self.view.get_selection().select_path ((0,))
self.view.get_selection().select_path((0,))
except ValueError, e:
self.error(e.args[0])
@ -204,11 +206,11 @@ class portsPage(semanagePage):
port_number = "1"
for i in port_number.split("-"):
if not i.isdigit():
self.error(_("Port number \"%s\" is not valid. 0 < PORT_NUMBER < 65536 ") % port_number )
self.error(_("Port number \"%s\" is not valid. 0 < PORT_NUMBER < 65536 ") % port_number)
return False
list_model = self.ports_protocol_combo.get_model()
iter = self.ports_protocol_combo.get_active_iter()
protocol = list_model.get_value(iter,0)
protocol = list_model.get_value(iter, 0)
self.wait()
(rc, out) = commands.getstatusoutput("semanage port -a -p %s -r %s -t %s %s" % (protocol, mls, target, port_number))
self.ready()
@ -228,7 +230,7 @@ class portsPage(semanagePage):
port_number = self.ports_number_entry.get_text().strip()
list_model = self.ports_protocol_combo.get_model()
iter = self.ports_protocol_combo.get_active_iter()
protocol = list_model.get_value(iter,0)
protocol = list_model.get_value(iter, 0)
self.wait()
(rc, out) = commands.getstatusoutput("semanage port -m -p %s -r %s -t %s %s" % (protocol, mls, target, port_number))
self.ready()

View File

@ -27,7 +27,7 @@ import seobject
##
## I18N
##
PROGNAME="policycoreutils"
PROGNAME = "policycoreutils"
import gettext
gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
gettext.textdomain(PROGNAME)
@ -35,16 +35,19 @@ try:
gettext.install(PROGNAME,
localedir="/usr/share/locale",
unicode=False,
codeset = 'utf-8')
codeset='utf-8')
except IOError:
import __builtin__
__builtin__.__dict__['_'] = unicode
def idle_func():
while gtk.events_pending():
gtk.main_iteration()
class semanagePage:
def __init__(self, xml, name, description):
self.xml = xml
self.window = self.xml.get_widget("mainWindow").get_root_window()
@ -54,13 +57,13 @@ class semanagePage:
self.local = False
self.view = xml.get_widget("%sView" % name)
self.dialog = xml.get_widget("%sDialog" % name)
self.filter_entry = xml.get_widget("%sFilterEntry" % name )
self.filter_entry = xml.get_widget("%sFilterEntry" % name)
self.filter_entry.connect("focus_out_event", self.filter_changed)
self.filter_entry.connect("activate", self.filter_changed)
self.view.connect("row_activated", self.rowActivated)
self.view.get_selection().connect("changed", self.itemSelected)
self.description = description;
self.description = description
def wait(self):
self.window.set_cursor(self.busy_cursor)
@ -77,21 +80,21 @@ class semanagePage:
return
def filter_changed(self, *arg):
filter = arg[0].get_text()
filter = arg[0].get_text()
if filter != self.filter:
self.load(filter)
def search(self, model, col, key, i):
sort_col = self.store.get_sort_column_id()[0]
val = model.get_value(i,sort_col)
val = model.get_value(i, sort_col)
if val.lower().startswith(key.lower()):
return False
return True
def match(self, target, filter):
try:
f=filter.lower()
t=target.lower()
f = filter.lower()
t = target.lower()
if t.find(f) >= 0:
return True
except:
@ -101,7 +104,7 @@ class semanagePage:
def rowActivated(self, view, row, Column):
self.propertiesDialog()
def verify(self, message, title="" ):
def verify(self, message, title=""):
dlg = gtk.MessageDialog(None, 0, gtk.MESSAGE_INFO,
gtk.BUTTONS_YES_NO,
message)
@ -134,11 +137,11 @@ class semanagePage:
self.dialog.set_title(_("Add %s" % self.description))
self.dialog.set_position(gtk.WIN_POS_MOUSE)
while self.dialog.run() == gtk.RESPONSE_OK:
while self.dialog.run() == gtk.RESPONSE_OK:
try:
if self.add() == False:
continue
break;
break
except ValueError, e:
self.error(e.args[0])
self.dialog.hide()
@ -147,11 +150,11 @@ class semanagePage:
self.dialogInit()
self.dialog.set_title(_("Modify %s" % self.description))
self.dialog.set_position(gtk.WIN_POS_MOUSE)
while self.dialog.run() == gtk.RESPONSE_OK:
while self.dialog.run() == gtk.RESPONSE_OK:
try:
if self.modify() == False:
continue
break;
break
except ValueError, e:
self.error(e.args[0])
self.dialog.hide()

View File

@ -31,7 +31,7 @@ import commands
ENFORCING = 1
PERMISSIVE = 0
DISABLED = -1
modearray = ( "disabled", "permissive", "enforcing" )
modearray = ("disabled", "permissive", "enforcing")
SELINUXDIR = "/etc/selinux/"
RELABELFILE = "/.autorelabel"
@ -39,7 +39,7 @@ RELABELFILE = "/.autorelabel"
##
## I18N
##
PROGNAME="policycoreutils"
PROGNAME = "policycoreutils"
import gettext
gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
gettext.textdomain(PROGNAME)
@ -50,7 +50,9 @@ except IOError:
import __builtin__
__builtin__.__dict__['_'] = unicode
class statusPage:
def __init__(self, xml):
self.xml = xml
self.needRelabel = False
@ -66,15 +68,15 @@ class statusPage:
self.relabel_checkbutton.set_active(self.is_relabel())
self.relabel_checkbutton.connect("toggled", self.on_relabel_toggle)
if self.get_current_mode() == ENFORCING or self.get_current_mode() == PERMISSIVE:
self.currentOptionMenu.append_text(_("Permissive"))
self.currentOptionMenu.append_text(_("Enforcing"))
self.currentOptionMenu.set_active(self.get_current_mode())
self.currentOptionMenu.connect("changed", self.set_current_mode)
self.currentOptionMenu.set_sensitive(True)
self.currentOptionMenu.append_text(_("Permissive"))
self.currentOptionMenu.append_text(_("Enforcing"))
self.currentOptionMenu.set_active(self.get_current_mode())
self.currentOptionMenu.connect("changed", self.set_current_mode)
self.currentOptionMenu.set_sensitive(True)
else:
self.currentOptionMenu.append_text(_("Disabled"))
self.currentOptionMenu.set_active(0)
self.currentOptionMenu.set_sensitive(False)
self.currentOptionMenu.append_text(_("Disabled"))
self.currentOptionMenu.set_active(0)
self.currentOptionMenu.set_sensitive(False)
if self.read_selinux_config() == None:
self.selinuxsupport = False
@ -102,15 +104,15 @@ class statusPage:
else:
return DISABLED
def set_current_mode(self,menu):
def set_current_mode(self, menu):
selinux.security_setenforce(menu.get_active() == 1)
def is_relabel(self):
return os.access(RELABELFILE, os.F_OK) != 0
def on_relabel_toggle(self,button):
def on_relabel_toggle(self, button):
if button.get_active():
fd = open(RELABELFILE,"w")
fd = open(RELABELFILE, "w")
fd.close()
else:
if os.access(RELABELFILE, os.F_OK) != 0:
@ -136,7 +138,7 @@ class statusPage:
self.relabel_checkbutton.set_active(True)
self.write_selinux_config(modearray[enabled], type )
self.write_selinux_config(modearray[enabled], type)
self.typeHistory = menu.get_active()
def enabled_changed(self, combo):
@ -154,11 +156,11 @@ class statusPage:
return None
self.relabel_checkbutton.set_active(True)
self.write_selinux_config(modearray[enabled], type )
self.write_selinux_config(modearray[enabled], type)
self.enabled = enabled
def write_selinux_config(self, enforcing, type):
path = selinux.selinux_path() + "config"
path = selinux.selinux_path() + "config"
backup_path = path + ".bck"
fd = open(path)
lines = fd.readlines()
@ -183,7 +185,7 @@ class statusPage:
self.initEnabled = False
pass
self.enabled = self.initEnabled
self.enabledOptionMenu.set_active(self.enabled + 1 )
self.enabledOptionMenu.set_active(self.enabled + 1)
self.types = []
@ -191,12 +193,12 @@ class statusPage:
current = n
for i in os.listdir(SELINUXDIR):
if os.path.isdir(SELINUXDIR+i) and os.path.isdir(SELINUXDIR+i+"/policy"):
if os.path.isdir(SELINUXDIR + i) and os.path.isdir(SELINUXDIR + i + "/policy"):
self.types.append(i)
self.selinuxTypeOptionMenu.append_text(i)
if i == self.initialtype:
current = n
n = n+1
n = n + 1
self.selinuxTypeOptionMenu.set_active(current)
self.typeHistory = current

View File

@ -28,7 +28,7 @@ try:
except RuntimeError, e:
print "system-config-selinux:", e
print "This is a graphical application and requires DISPLAY to be set."
sys.exit (1)
sys.exit(1)
import gtk.glade
import os
@ -46,7 +46,7 @@ import selinux
##
## I18N
##
PROGNAME="policycoreutils"
PROGNAME = "policycoreutils"
import gettext
gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
@ -55,7 +55,7 @@ try:
gettext.install(PROGNAME,
localedir="/usr/share/locale",
unicode=False,
codeset = 'utf-8')
codeset='utf-8')
except IOError:
import __builtin__
__builtin__.__dict__['_'] = unicode
@ -67,18 +67,19 @@ version = "1.0"
sys.path.append('/usr/share/system-config-selinux')
##
## Pull in the Glade file
##
if os.access("system-config-selinux.glade", os.F_OK):
xml = gtk.glade.XML ("system-config-selinux.glade", domain=PROGNAME)
xml = gtk.glade.XML("system-config-selinux.glade", domain=PROGNAME)
else:
xml = gtk.glade.XML ("/usr/share/system-config-selinux/system-config-selinux.glade", domain=PROGNAME)
xml = gtk.glade.XML("/usr/share/system-config-selinux/system-config-selinux.glade", domain=PROGNAME)
class childWindow:
def __init__(self):
self.tabs=[]
self.tabs = []
self.xml = xml
xml.signal_connect("on_quit_activate", self.destroy)
xml.signal_connect("on_delete_clicked", self.delete)
@ -93,8 +94,8 @@ class childWindow:
self.add_page(loginsPage.loginsPage(xml))
self.add_page(usersPage.usersPage(xml))
self.add_page(portsPage.portsPage(xml))
self.add_page(modulesPage.modulesPage(xml)) # modules
self.add_page(domainsPage.domainsPage(xml)) # domains
self.add_page(modulesPage.modulesPage(xml)) # modules
self.add_page(domainsPage.domainsPage(xml)) # domains
except ValueError, e:
self.error(e.message)
@ -121,6 +122,7 @@ class childWindow:
def policy(self, args):
os.spawnl(os.P_NOWAIT, "/usr/share/system-config-selinux/semanagegui.py")
def logging(self, args):
os.spawnl(os.P_NOWAIT, "/usr/bin/seaudit")
@ -137,9 +139,9 @@ class childWindow:
self.tabs[self.notebook.get_current_page()].on_local_clicked(button)
def on_about_activate(self, args):
dlg = xml.get_widget ("aboutWindow")
dlg.run ()
dlg.hide ()
dlg = xml.get_widget("aboutWindow")
dlg.run()
dlg.hide()
def destroy(self, args):
gtk.main_quit()
@ -158,7 +160,6 @@ class childWindow:
self.notebook.set_current_page(0)
self.use_menus(self.tabs[0].use_menus())
def setupScreen(self):
# Bring in widgets from glade file.
self.mainWindow = self.xml.get_widget("mainWindow")
@ -167,14 +168,14 @@ class childWindow:
self.view.get_selection().connect("changed", self.itemSelected)
self.store = gtk.ListStore(gobject.TYPE_STRING)
self.view.set_model(self.store)
col = gtk.TreeViewColumn("", gtk.CellRendererText(), text = 0)
col = gtk.TreeViewColumn("", gtk.CellRendererText(), text=0)
col.set_resizable(True)
self.view.append_column(col)
for page in self.tabs:
iter = self.store.append()
self.store.set_value(iter, 0, page.get_description())
self.view.get_selection().select_path ((0,))
self.view.get_selection().select_path((0,))
def stand_alone(self):
desktopName = _("Configue SELinux")
@ -187,7 +188,7 @@ class childWindow:
gtk.main()
if __name__ == "__main__":
signal.signal (signal.SIGINT, signal.SIG_DFL)
signal.signal(signal.SIGINT, signal.SIG_DFL)
app = childWindow()
app.stand_alone()

View File

@ -24,12 +24,12 @@ import gobject
import sys
import commands
import seobject
from semanagePage import *;
from semanagePage import *
##
## I18N
##
PROGNAME="policycoreutils"
PROGNAME = "policycoreutils"
import gettext
gettext.bindtextdomain(PROGNAME, "/usr/share/locale")
gettext.textdomain(PROGNAME)
@ -39,7 +39,9 @@ except IOError:
import __builtin__
__builtin__.__dict__['_'] = unicode
class usersPage(semanagePage):
def __init__(self, xml):
semanagePage.__init__(self, xml, "users", _("SELinux User"))
@ -47,16 +49,16 @@ class usersPage(semanagePage):
self.view.set_model(self.store)
self.store.set_sort_column_id(0, gtk.SORT_ASCENDING)
col = gtk.TreeViewColumn(_("SELinux\nUser"), gtk.CellRendererText(), text = 0)
col = gtk.TreeViewColumn(_("SELinux\nUser"), gtk.CellRendererText(), text=0)
col.set_sort_column_id(0)
col.set_resizable(True)
self.view.append_column(col)
col = gtk.TreeViewColumn(_("MLS/\nMCS Range"), gtk.CellRendererText(), text = 1)
col = gtk.TreeViewColumn(_("MLS/\nMCS Range"), gtk.CellRendererText(), text=1)
col.set_resizable(True)
self.view.append_column(col)
col = gtk.TreeViewColumn(_("SELinux Roles"), gtk.CellRendererText(), text = 2)
col = gtk.TreeViewColumn(_("SELinux Roles"), gtk.CellRendererText(), text=2)
col.set_resizable(True)
self.view.append_column(col)
@ -65,8 +67,8 @@ class usersPage(semanagePage):
self.mlsRangeEntry = xml.get_widget("mlsRangeEntry")
self.selinuxRolesEntry = xml.get_widget("selinuxRolesEntry")
def load(self, filter = ""):
self.filter=filter
def load(self, filter=""):
self.filter = filter
self.user = seobject.seluserRecords()
dict = self.user.get_all()
keys = dict.keys()
@ -81,11 +83,11 @@ class usersPage(semanagePage):
self.store.set_value(iter, 0, k)
self.store.set_value(iter, 1, range)
self.store.set_value(iter, 2, dict[k][3])
self.view.get_selection().select_path ((0,))
self.view.get_selection().select_path((0,))
def delete(self):
if semanagePage.delete(self) == gtk.RESPONSE_NO:
return None
return None
def dialogInit(self):
store, iter = self.view.get_selection().get_selected()
@ -106,7 +108,7 @@ class usersPage(semanagePage):
roles = self.selinuxRolesEntry.get_text()
self.wait()
(rc, out) = commands.getstatusoutput("semanage user -a -R '%s' -r %s %s" % (roles, range, user))
(rc, out) = commands.getstatusoutput("semanage user -a -R '%s' -r %s %s" % (roles, range, user))
self.ready()
if rc != 0:
self.error(out)
@ -122,7 +124,7 @@ class usersPage(semanagePage):
roles = self.selinuxRolesEntry.get_text()
self.wait()
(rc, out) = commands.getstatusoutput("semanage user -m -R '%s' -r %s %s" % (roles, range, user))
(rc, out) = commands.getstatusoutput("semanage user -m -R '%s' -r %s %s" % (roles, range, user))
self.ready()
if rc != 0:
@ -133,17 +135,17 @@ class usersPage(semanagePage):
def delete(self):
store, iter = self.view.get_selection().get_selected()
try:
user=store.get_value(iter, 0)
user = store.get_value(iter, 0)
if user == "root" or user == "user_u":
raise ValueError(_("SELinux user '%s' is required") % user)
self.wait()
(rc, out) = commands.getstatusoutput("semanage user -d %s" % user)
(rc, out) = commands.getstatusoutput("semanage user -d %s" % user)
self.ready()
if rc != 0:
self.error(out)
return False
store.remove(iter)
self.view.get_selection().select_path ((0,))
self.view.get_selection().select_path((0,))
except ValueError, e:
self.error(e.args[0])

Some files were not shown because too many files have changed in this diff Show More