Skip to content

Commit e5a2262

Browse files
cgzonesfishilico
authored andcommitted
libsepol: add compile-time constraint for mutual exclusive attributes
Add a new compile-time constraint, similar to neverallow, which enables to specify two or more type attributes to be mutual exclusive. This means no type can be associated with more than one of them. The constraints are stored as a linked-list in the policy for modular policies, by a new modular policy version, and are discarded in kernel policies, not needing any kernel support. Some Reference Policy examples: unpriv_userdomain, admindomain: <no violations> client_packet_type, server_packet_type: <no violations> auth_file_type, non_auth_file_type: <no violations> pseudofs, xattrfs, noxattrfs: <no violations> reserved_port_type, unreserved_port_type: <no violations> security_file_type, non_security_file_type: libsepol.check_segregate_attributes: segregate_attributes violated by type dnssec_t associated with attributes security_file_type and non_security_file_type ibendport_type, packet_type, sysctl_type, device_node, ibpkey_type, sysfs_types, domain, boolean_type, netif_type, file_type, node_type, proc_type, port_type: libsepol.check_segregate_attributes: segregate_attributes violated by type virt_content_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: segregate_attributes violated by type sysctl_fs_t associated with attributes sysctl_type and file_type libsepol.check_segregate_attributes: segregate_attributes violated by type initrc_devpts_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: segregate_attributes violated by type qemu_image_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: segregate_attributes violated by type user_devpts_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: segregate_attributes violated by type dockerc_t associated with attributes domain and file_type libsepol.check_segregate_attributes: segregate_attributes violated by type cpu_online_t associated with attributes sysfs_types and file_type libsepol.check_segregate_attributes: segregate_attributes violated by type cardmgr_dev_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: segregate_attributes violated by type sysctl_t associated with attributes sysctl_type and file_type libsepol.check_segregate_attributes: segregate_attributes violated by type bootloader_tmp_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: segregate_attributes violated by type xen_image_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: segregate_attributes violated by type svirt_prot_exec_image_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: segregate_attributes violated by type xen_devpts_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: segregate_attributes violated by type proc_t associated with attributes file_type and proc_type libsepol.check_segregate_attributes: segregate_attributes violated by type sysfs_t associated with attributes sysfs_types and file_type libsepol.check_segregate_attributes: segregate_attributes violated by type proc_xen_t associated with attributes file_type and proc_type libsepol.check_segregate_attributes: segregate_attributes violated by type svirt_image_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: segregate_attributes violated by type virt_image_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: segregate_attributes violated by type container_file_t associated with attributes device_node and file_type libsepol.check_assertions: 20 segregate attribute failures occurred Closes: SELinuxProject#42 Signed-off-by: Christian Göttsche <[email protected]>
1 parent 34b6453 commit e5a2262

File tree

7 files changed

+323
-5
lines changed

7 files changed

+323
-5
lines changed

libsepol/include/sepol/policydb/policydb.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,16 @@ typedef struct type_datum {
192192
uint32_t bounds; /* bounds type, if exist */
193193
} type_datum_t;
194194

195+
/* Mutual exclusive attributes */
196+
typedef struct segregate_attribute {
197+
ebitmap_t attrs; /* mutual exclusive attributes */
198+
unsigned long line; /* line number from policy.conf where this rule originated */
199+
/* source file name and line number (e.g. .te file) */
200+
char *source_filename;
201+
unsigned long source_line;
202+
struct segregate_attribute *next;
203+
} segregate_attribute_t;
204+
195205
/*
196206
* Properties of type_datum
197207
* available on the policy version >= (MOD_)POLICYDB_VERSION_BOUNDARY
@@ -605,6 +615,9 @@ typedef struct policydb {
605615
bitmaps. Someday the 0 bit may be used for global permissive */
606616
ebitmap_t permissive_map;
607617

618+
/* mutual exclusive attributes (not preserved in kernel policy) */
619+
segregate_attribute_t *segregate_attributes;
620+
608621
unsigned policyvers;
609622

610623
unsigned handle_unknown;
@@ -696,6 +709,8 @@ extern void level_datum_init(level_datum_t * x);
696709
extern void level_datum_destroy(level_datum_t * x);
697710
extern void cat_datum_init(cat_datum_t * x);
698711
extern void cat_datum_destroy(cat_datum_t * x);
712+
extern void segregate_attribute_init(segregate_attribute_t * x);
713+
extern void segregate_attribute_destroy(segregate_attribute_t * x);
699714
extern int check_assertion(policydb_t *p, avrule_t *avrule);
700715
extern int check_assertions(sepol_handle_t * handle,
701716
policydb_t * p, avrule_t * avrules);
@@ -783,9 +798,10 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
783798
#define MOD_POLICYDB_VERSION_INFINIBAND 19
784799
#define MOD_POLICYDB_VERSION_GLBLUB 20
785800
#define MOD_POLICYDB_VERSION_SELF_TYPETRANS 21
801+
#define MOD_POLICYDB_VERSION_SEGREGATEATTRIBUTE 22
786802

787803
#define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE
788-
#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_SELF_TYPETRANS
804+
#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_SEGREGATEATTRIBUTE
789805

790806
#define POLICYDB_CONFIG_MLS 1
791807

libsepol/src/assertion.c

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ struct avtab_match_args {
3636
unsigned long errors;
3737
};
3838

39-
static const char* policy_name(policydb_t *p) {
39+
static const char* policy_name(const policydb_t *p) {
4040
const char *policy_file = "policy.conf";
4141
if (p->name) {
4242
policy_file = p->name;
@@ -535,6 +535,53 @@ int check_assertion(policydb_t *p, avrule_t *avrule)
535535
return rc;
536536
}
537537

538+
static int check_segregate_attributes(sepol_handle_t *handle, const policydb_t *p)
539+
{
540+
int errors = 0;
541+
const segregate_attribute_t *sattr;
542+
543+
for (sattr = p->segregate_attributes; sattr; sattr = sattr->next) {
544+
ebitmap_node_t *first_node;
545+
unsigned int first_bit;
546+
547+
ebitmap_for_each_positive_bit(&sattr->attrs, first_node, first_bit) {
548+
ebitmap_node_t *second_node;
549+
unsigned int second_bit;
550+
551+
ebitmap_for_each_positive_bit_starting(&sattr->attrs, first_node, first_bit, second_node, second_bit) {
552+
ebitmap_t attr_union;
553+
ebitmap_node_t *type_node;
554+
unsigned int type_bit;
555+
556+
if (ebitmap_and(&attr_union, &p->attr_type_map[first_bit], &p->attr_type_map[second_bit]))
557+
return -1;
558+
559+
ebitmap_for_each_positive_bit(&attr_union, type_node, type_bit) {
560+
if (sattr->source_filename)
561+
ERR(handle, "segregate_attributes on line %lu of %s (or line %lu of %s) violated by "
562+
"type %s associated with attributes %s and %s",
563+
sattr->source_line, sattr->source_filename, sattr->line, policy_name(p),
564+
p->p_type_val_to_name[type_bit], p->p_type_val_to_name[first_bit], p->p_type_val_to_name[second_bit]);
565+
else if (sattr->line)
566+
ERR(handle, "segregate_attributes on line %lu of %s violated by "
567+
"type %s associated with attributes %s and %s",
568+
sattr->line, policy_name(p),
569+
p->p_type_val_to_name[type_bit], p->p_type_val_to_name[first_bit], p->p_type_val_to_name[second_bit]);
570+
else
571+
ERR(handle, "segregate_attributes violated by "
572+
"type %s associated with attributes %s and %s",
573+
p->p_type_val_to_name[type_bit], p->p_type_val_to_name[first_bit], p->p_type_val_to_name[second_bit]);
574+
errors++;
575+
}
576+
577+
ebitmap_destroy(&attr_union);
578+
}
579+
}
580+
}
581+
582+
return errors;
583+
}
584+
538585
int check_assertions(sepol_handle_t * handle, policydb_t * p,
539586
avrule_t * avrules)
540587
{
@@ -570,5 +617,15 @@ int check_assertions(sepol_handle_t * handle, policydb_t * p,
570617
if (errors)
571618
ERR(handle, "%lu neverallow failures occurred", errors);
572619

620+
rc = check_segregate_attributes(handle, p);
621+
if (rc < 0) {
622+
ERR(handle, "Error occurred while checking segregate attributes");
623+
return -1;
624+
}
625+
if (rc) {
626+
ERR(handle, "%d segregate attribute failures occurred", rc);
627+
errors += rc;
628+
}
629+
573630
return errors ? -1 : 0;
574631
}

libsepol/src/expand.c

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ static void expand_state_init(expand_state_t * state)
5656
memset(state, 0, sizeof(expand_state_t));
5757
}
5858

59-
static int map_ebitmap(ebitmap_t * src, ebitmap_t * dst, uint32_t * map)
59+
static int map_ebitmap(const ebitmap_t * src, ebitmap_t * dst, const uint32_t * map)
6060
{
6161
unsigned int i;
6262
ebitmap_node_t *tnode;
@@ -2341,6 +2341,56 @@ static int genfs_copy(expand_state_t * state)
23412341
return 0;
23422342
}
23432343

2344+
static int segregate_attribute_copy(expand_state_t *state)
2345+
{
2346+
const segregate_attribute_t *old;
2347+
segregate_attribute_t *list = NULL;
2348+
2349+
for (old = state->base->segregate_attributes; old; old = old->next) {
2350+
segregate_attribute_t *new;
2351+
2352+
new = calloc(1, sizeof(segregate_attribute_t));
2353+
if (!new) {
2354+
ERR(state->handle, "Out of memory!");
2355+
return -1;
2356+
}
2357+
2358+
new->next = NULL;
2359+
new->line = old->line;
2360+
new->source_line = old->source_line;
2361+
if (old->source_filename) {
2362+
new->source_filename = strdup(old->source_filename);
2363+
if (!new->source_filename) {
2364+
ERR(state->handle, "Out of memory!");
2365+
free(new);
2366+
return -1;
2367+
}
2368+
}
2369+
2370+
if (map_ebitmap(&old->attrs, &new->attrs, state->typemap)) {
2371+
ERR(state->handle, "out of memory");
2372+
ebitmap_destroy(&new->attrs);
2373+
free(new->source_filename);
2374+
free(new);
2375+
return -1;
2376+
}
2377+
2378+
if (list)
2379+
list->next = new;
2380+
else {
2381+
if (state->out->segregate_attributes) {
2382+
segregate_attribute_t *s;
2383+
for (s = state->out->segregate_attributes; s->next; s = s->next) {}
2384+
s->next = new;
2385+
} else
2386+
state->out->segregate_attributes = new;
2387+
}
2388+
list = new;
2389+
}
2390+
2391+
return 0;
2392+
}
2393+
23442394
static int type_attr_map(hashtab_key_t key
23452395
__attribute__ ((unused)), hashtab_datum_t datum,
23462396
void *ptr)
@@ -3173,6 +3223,10 @@ int expand_module(sepol_handle_t * handle,
31733223
if (genfs_copy(&state))
31743224
goto cleanup;
31753225

3226+
/* copy segregate attributes */
3227+
if (segregate_attribute_copy(&state))
3228+
goto cleanup;
3229+
31763230
/* Build the type<->attribute maps and remove attributes. */
31773231
state.out->attr_type_map = calloc(state.out->p_types.nprim,
31783232
sizeof(ebitmap_t));

libsepol/src/link.c

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,6 +1857,58 @@ static int scope_copy_callback(hashtab_key_t key, hashtab_datum_t datum,
18571857
return -1;
18581858
}
18591859

1860+
static int copy_segregate_attributes(link_state_t * state, const policy_module_t *module)
1861+
{
1862+
const segregate_attribute_t *src_sattr;
1863+
segregate_attribute_t *list = NULL;
1864+
1865+
for (src_sattr = module->policy->segregate_attributes; src_sattr; src_sattr = src_sattr->next) {
1866+
segregate_attribute_t *new_sattr;
1867+
1868+
new_sattr = calloc(1, sizeof(segregate_attribute_t));
1869+
if (!new_sattr) {
1870+
ERR(state->handle, "Out of memory!");
1871+
return -1;
1872+
}
1873+
1874+
ebitmap_init(&new_sattr->attrs);
1875+
if (ebitmap_convert(&src_sattr->attrs, &new_sattr->attrs, module->map[SYM_TYPES])) {
1876+
ebitmap_destroy(&new_sattr->attrs);
1877+
free(new_sattr);
1878+
ERR(state->handle, "Out of memory!");
1879+
return -1;
1880+
}
1881+
1882+
new_sattr->line = src_sattr->line;
1883+
1884+
if (src_sattr->source_filename) {
1885+
new_sattr->source_filename = strdup(src_sattr->source_filename);
1886+
if (!new_sattr->source_filename) {
1887+
ebitmap_destroy(&new_sattr->attrs);
1888+
free(new_sattr);
1889+
ERR(state->handle, "Out of memory!");
1890+
return -1;
1891+
}
1892+
}
1893+
1894+
new_sattr->source_line = src_sattr->source_line;
1895+
1896+
if (list)
1897+
list->next = new_sattr;
1898+
else {
1899+
if (state->base->segregate_attributes) {
1900+
segregate_attribute_t *s;
1901+
for (s = state->base->segregate_attributes; s->next; s = s->next) {}
1902+
s->next = new_sattr;
1903+
} else
1904+
state->base->segregate_attributes = new_sattr;
1905+
}
1906+
list = new_sattr;
1907+
}
1908+
1909+
return 0;
1910+
}
1911+
18601912
/* Copy a module over to a base, remapping all values within. After
18611913
* all identifiers and rules are done, copy the scoping information.
18621914
* This is when it checks for duplicate declarations. */
@@ -1891,6 +1943,11 @@ static int copy_module(link_state_t * state, policy_module_t * module)
18911943
}
18921944
}
18931945

1946+
ret = copy_segregate_attributes(state, module);
1947+
if (ret) {
1948+
return ret;
1949+
}
1950+
18941951
return 0;
18951952
}
18961953

libsepol/src/policydb.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,13 @@ static const struct policydb_compat_info policydb_compat[] = {
334334
.ocon_num = OCON_IBENDPORT + 1,
335335
.target_platform = SEPOL_TARGET_SELINUX,
336336
},
337+
{
338+
.type = POLICY_BASE,
339+
.version = MOD_POLICYDB_VERSION_SEGREGATEATTRIBUTE,
340+
.sym_num = SYM_NUM,
341+
.ocon_num = OCON_IBENDPORT + 1,
342+
.target_platform = SEPOL_TARGET_SELINUX,
343+
},
337344
{
338345
.type = POLICY_MOD,
339346
.version = MOD_POLICYDB_VERSION_BASE,
@@ -460,6 +467,13 @@ static const struct policydb_compat_info policydb_compat[] = {
460467
.ocon_num = 0,
461468
.target_platform = SEPOL_TARGET_SELINUX,
462469
},
470+
{
471+
.type = POLICY_MOD,
472+
.version = MOD_POLICYDB_VERSION_SEGREGATEATTRIBUTE,
473+
.sym_num = SYM_NUM,
474+
.ocon_num = 0,
475+
.target_platform = SEPOL_TARGET_SELINUX,
476+
},
463477
};
464478

465479
#if 0
@@ -760,6 +774,21 @@ void avrule_list_destroy(avrule_t * x)
760774
}
761775
}
762776

777+
void segregate_attribute_init(segregate_attribute_t * x)
778+
{
779+
memset(x, 0, sizeof(segregate_attribute_t));
780+
ebitmap_init(&x->attrs);
781+
}
782+
783+
784+
void segregate_attribute_destroy(segregate_attribute_t * x)
785+
{
786+
if (!x)
787+
return;
788+
ebitmap_destroy(&x->attrs);
789+
free(x->source_filename);
790+
}
791+
763792
/*
764793
* Initialize the role table by implicitly adding role 'object_r'. If
765794
* the policy is a module, set object_r's scope to be SCOPE_REQ,
@@ -1492,6 +1521,7 @@ void policydb_destroy(policydb_t * p)
14921521
unsigned int i;
14931522
role_allow_t *ra, *lra = NULL;
14941523
role_trans_t *tr, *ltr = NULL;
1524+
segregate_attribute_t *sattr, *sattr_next;
14951525

14961526
if (!p)
14971527
return;
@@ -1585,6 +1615,12 @@ void policydb_destroy(policydb_t * p)
15851615
free(p->attr_type_map);
15861616
}
15871617

1618+
for (sattr = p->segregate_attributes; sattr; sattr = sattr_next) {
1619+
sattr_next = sattr->next;
1620+
segregate_attribute_destroy(sattr);
1621+
free(sattr);
1622+
}
1623+
15881624
return;
15891625
}
15901626

@@ -4174,6 +4210,39 @@ static int scope_read(policydb_t * p, int symnum, struct policy_file *fp)
41744210
return -1;
41754211
}
41764212

4213+
static int segregate_attributes_read(policydb_t * p, struct policy_file *fp)
4214+
{
4215+
segregate_attribute_t *list = NULL;
4216+
uint32_t buf, nel, i;
4217+
int rc;
4218+
4219+
rc = next_entry(&buf, fp, sizeof(uint32_t));
4220+
if (rc < 0)
4221+
return -1;
4222+
nel = le32_to_cpu(buf);
4223+
for (i = 0; i < nel; i++) {
4224+
segregate_attribute_t *sattr;
4225+
4226+
sattr = calloc(1, sizeof(segregate_attribute_t));
4227+
if (!sattr)
4228+
return -1;
4229+
4230+
if (ebitmap_read(&sattr->attrs, fp) < 0) {
4231+
ebitmap_destroy(&sattr->attrs);
4232+
free(sattr);
4233+
return -1;
4234+
}
4235+
4236+
if (list)
4237+
list->next = sattr;
4238+
else
4239+
p->segregate_attributes = sattr;
4240+
list = sattr;
4241+
}
4242+
4243+
return 0;
4244+
}
4245+
41774246
static sepol_security_class_t policydb_string_to_security_class(
41784247
struct policydb *policydb,
41794248
const char *class_name)
@@ -4570,6 +4639,12 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose)
45704639
}
45714640
}
45724641

4642+
if (p->policyvers >= MOD_POLICYDB_VERSION_SEGREGATEATTRIBUTE &&
4643+
p->policy_type != POLICY_KERN) {
4644+
if (segregate_attributes_read(p, fp))
4645+
return POLICYDB_ERROR;
4646+
}
4647+
45734648
if (validate_policydb(fp->handle, p))
45744649
goto bad;
45754650

0 commit comments

Comments
 (0)