Skip to content

Commit e0dff82

Browse files
committed
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 violation, 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 violation, type sysctl_fs_t associated with attributes sysctl_type and file_type libsepol.check_segregate_attributes: Segregate Attributes violation, type sysctl_t associated with attributes sysctl_type and file_type libsepol.check_segregate_attributes: Segregate Attributes violation, type virt_content_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: Segregate Attributes violation, type initrc_devpts_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: Segregate Attributes violation, type qemu_image_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: Segregate Attributes violation, type user_devpts_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: Segregate Attributes violation, type cardmgr_dev_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: Segregate Attributes violation, type bootloader_tmp_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: Segregate Attributes violation, type xen_image_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: Segregate Attributes violation, type svirt_prot_exec_image_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: Segregate Attributes violation, type xen_devpts_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: Segregate Attributes violation, type svirt_image_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: Segregate Attributes violation, type virt_image_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: Segregate Attributes violation, type container_file_t associated with attributes device_node and file_type libsepol.check_segregate_attributes: Segregate Attributes violation, type cpu_online_t associated with attributes sysfs_types and file_type libsepol.check_segregate_attributes: Segregate Attributes violation, type sysfs_t associated with attributes sysfs_types and file_type libsepol.check_segregate_attributes: Segregate Attributes violation, type dockerc_t associated with attributes domain and file_type libsepol.check_segregate_attributes: Segregate Attributes violation, type proc_t associated with attributes file_type and proc_type libsepol.check_segregate_attributes: Segregate Attributes violation, type proc_xen_t associated with attributes file_type and proc_type libsepol.check_assertions: 20 Segregate Attributes failures occurred Closes: SELinuxProject#42 Signed-off-by: Christian Göttsche <[email protected]> --- v3: - drop source location information: this information was already lost for binary modular policies and CIL policies; also typeattribute statements have none and the few segregate_attributes statements can be easily grepped - misc renaming v2: rebase onto _after suffix change
1 parent 0dd24ea commit e0dff82

File tree

8 files changed

+325
-13
lines changed

8 files changed

+325
-13
lines changed

libsepol/include/sepol/policydb/policydb.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,12 @@ 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_attributes_rule {
197+
ebitmap_t attrs; /* mutual exclusive attributes */
198+
struct segregate_attributes_rule *next;
199+
} segregate_attributes_rule_t;
200+
195201
/*
196202
* Properties of type_datum
197203
* available on the policy version >= (MOD_)POLICYDB_VERSION_BOUNDARY
@@ -605,6 +611,10 @@ typedef struct policydb {
605611
bitmaps. Someday the 0 bit may be used for global permissive */
606612
ebitmap_t permissive_map;
607613

614+
/* mutual exclusive attributes (not preserved in kernel policy).
615+
stored as linked list */
616+
segregate_attributes_rule_t *segregate_attributes;
617+
608618
unsigned policyvers;
609619

610620
unsigned handle_unknown;
@@ -696,6 +706,8 @@ extern void level_datum_init(level_datum_t * x);
696706
extern void level_datum_destroy(level_datum_t * x);
697707
extern void cat_datum_init(cat_datum_t * x);
698708
extern void cat_datum_destroy(cat_datum_t * x);
709+
extern void segregate_attributes_rule_init(segregate_attributes_rule_t * x);
710+
extern void segregate_attributes_rule_destroy(segregate_attributes_rule_t * x);
699711
extern int check_assertion(policydb_t *p, avrule_t *avrule);
700712
extern int check_assertions(sepol_handle_t * handle,
701713
policydb_t * p, avrule_t * avrules);
@@ -783,9 +795,10 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
783795
#define MOD_POLICYDB_VERSION_INFINIBAND 19
784796
#define MOD_POLICYDB_VERSION_GLBLUB 20
785797
#define MOD_POLICYDB_VERSION_SELF_TYPETRANS 21
798+
#define MOD_POLICYDB_VERSION_SEGREGATE_ATTRIBUTES 22
786799

787800
#define MOD_POLICYDB_VERSION_MIN MOD_POLICYDB_VERSION_BASE
788-
#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_SELF_TYPETRANS
801+
#define MOD_POLICYDB_VERSION_MAX MOD_POLICYDB_VERSION_SEGREGATE_ATTRIBUTES
789802

790803
#define POLICYDB_CONFIG_MLS 1
791804

libsepol/src/assertion.c

Lines changed: 49 additions & 8 deletions
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,20 +535,51 @@ 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+
const segregate_attributes_rule_t *sattr;
541+
int errors = 0, rc;
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_after(&sattr->attrs, second_node, second_bit, first_node, first_bit) {
552+
ebitmap_t attr_union;
553+
ebitmap_node_t *type_node;
554+
unsigned int type_bit;
555+
556+
rc = ebitmap_and(&attr_union, &p->attr_type_map[first_bit], &p->attr_type_map[second_bit]);
557+
if (rc < 0)
558+
return rc;
559+
560+
ebitmap_for_each_positive_bit(&attr_union, type_node, type_bit) {
561+
ERR(handle, "Segregate Attributes violation, type %s associated with attributes %s and %s",
562+
p->p_type_val_to_name[type_bit],
563+
p->p_type_val_to_name[first_bit],
564+
p->p_type_val_to_name[second_bit]);
565+
errors++;
566+
}
567+
568+
ebitmap_destroy(&attr_union);
569+
}
570+
}
571+
}
572+
573+
return errors;
574+
}
575+
538576
int check_assertions(sepol_handle_t * handle, policydb_t * p,
539577
avrule_t * avrules)
540578
{
541579
int rc;
542580
avrule_t *a;
543581
unsigned long errors = 0;
544582

545-
if (!avrules) {
546-
/* Since assertions are stored in avrules, if it is NULL
547-
there won't be any to check. This also prevents an invalid
548-
free if the avtabs are never initialized */
549-
return 0;
550-
}
551-
552583
for (a = avrules; a != NULL; a = a->next) {
553584
if (!(a->specified & (AVRULE_NEVERALLOW | AVRULE_XPERMS_NEVERALLOW)))
554585
continue;
@@ -570,5 +601,15 @@ int check_assertions(sepol_handle_t * handle, policydb_t * p,
570601
if (errors)
571602
ERR(handle, "%lu neverallow failures occurred", errors);
572603

604+
rc = check_segregate_attributes(handle, p);
605+
if (rc < 0) {
606+
ERR(handle, "Error occurred while checking Segregate Attributes");
607+
return -1;
608+
}
609+
if (rc) {
610+
ERR(handle, "%d Segregate Attributes failures occurred", rc);
611+
errors += rc;
612+
}
613+
573614
return errors ? -1 : 0;
574615
}

libsepol/src/expand.c

Lines changed: 44 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,45 @@ static int genfs_copy(expand_state_t * state)
23412341
return 0;
23422342
}
23432343

2344+
static int segregate_attributes_copy(expand_state_t *state)
2345+
{
2346+
const segregate_attributes_rule_t *old;
2347+
segregate_attributes_rule_t *list = NULL;
2348+
2349+
for (old = state->base->segregate_attributes; old; old = old->next) {
2350+
segregate_attributes_rule_t *new;
2351+
2352+
new = malloc(sizeof(segregate_attributes_rule_t));
2353+
if (!new) {
2354+
ERR(state->handle, "Out of memory!");
2355+
return -1;
2356+
}
2357+
2358+
segregate_attributes_rule_init(new);
2359+
2360+
if (map_ebitmap(&old->attrs, &new->attrs, state->typemap)) {
2361+
ERR(state->handle, "out of memory");
2362+
ebitmap_destroy(&new->attrs);
2363+
free(new);
2364+
return -1;
2365+
}
2366+
2367+
if (list)
2368+
list->next = new;
2369+
else {
2370+
if (state->out->segregate_attributes) {
2371+
segregate_attributes_rule_t *s;
2372+
for (s = state->out->segregate_attributes; s->next; s = s->next) {}
2373+
s->next = new;
2374+
} else
2375+
state->out->segregate_attributes = new;
2376+
}
2377+
list = new;
2378+
}
2379+
2380+
return 0;
2381+
}
2382+
23442383
static int type_attr_map(hashtab_key_t key
23452384
__attribute__ ((unused)), hashtab_datum_t datum,
23462385
void *ptr)
@@ -3173,6 +3212,10 @@ int expand_module(sepol_handle_t * handle,
31733212
if (genfs_copy(&state))
31743213
goto cleanup;
31753214

3215+
/* copy segregate attributes */
3216+
if (segregate_attributes_copy(&state))
3217+
goto cleanup;
3218+
31763219
/* Build the type<->attribute maps and remove attributes. */
31773220
state.out->attr_type_map = calloc(state.out->p_types.nprim,
31783221
sizeof(ebitmap_t));

libsepol/src/kernel_to_conf.c

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1839,6 +1839,33 @@ static int write_avtab_to_conf(FILE *out, struct policydb *pdb, int indent)
18391839
return rc;
18401840
}
18411841

1842+
static int write_segregate_attributes_to_conf(FILE *out, const struct policydb *pdb)
1843+
{
1844+
const segregate_attributes_rule_t *sattr;
1845+
1846+
for (sattr = pdb->segregate_attributes; sattr; sattr = sattr->next) {
1847+
struct ebitmap_node *node;
1848+
unsigned int bit;
1849+
int first = 1;
1850+
1851+
sepol_printf(out, "segregate_attributes ");
1852+
1853+
ebitmap_for_each_positive_bit(&sattr->attrs, node, bit) {
1854+
if (first) {
1855+
first = 0;
1856+
} else {
1857+
sepol_printf(out, ", ");
1858+
}
1859+
1860+
sepol_printf(out, "%s", pdb->p_type_val_to_name[bit - 1]);
1861+
}
1862+
1863+
sepol_printf(out, ";\n");
1864+
}
1865+
1866+
return 0;
1867+
}
1868+
18421869
struct map_filename_trans_args {
18431870
struct policydb *pdb;
18441871
struct strs *strs;
@@ -3200,7 +3227,16 @@ int sepol_kernel_policydb_to_conf(FILE *out, struct policydb *pdb)
32003227
if (rc != 0) {
32013228
goto exit;
32023229
}
3203-
write_filename_trans_rules_to_conf(out, pdb);
3230+
3231+
rc = write_segregate_attributes_to_conf(out, pdb);
3232+
if (rc != 0) {
3233+
goto exit;
3234+
}
3235+
3236+
rc = write_filename_trans_rules_to_conf(out, pdb);
3237+
if (rc != 0) {
3238+
goto exit;
3239+
}
32043240

32053241
if (pdb->mls) {
32063242
rc = write_range_trans_rules_to_conf(out, pdb);

libsepol/src/link.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,6 +1857,45 @@ 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_attributes_rule_t *src_sattr;
1863+
segregate_attributes_rule_t *list = NULL;
1864+
1865+
for (src_sattr = module->policy->segregate_attributes; src_sattr; src_sattr = src_sattr->next) {
1866+
segregate_attributes_rule_t *new_sattr;
1867+
1868+
new_sattr = malloc(sizeof(segregate_attributes_rule_t));
1869+
if (!new_sattr) {
1870+
ERR(state->handle, "Out of memory!");
1871+
return -1;
1872+
}
1873+
1874+
segregate_attributes_rule_init(new_sattr);
1875+
1876+
if (ebitmap_convert(&src_sattr->attrs, &new_sattr->attrs, module->map[SYM_TYPES])) {
1877+
ebitmap_destroy(&new_sattr->attrs);
1878+
free(new_sattr);
1879+
ERR(state->handle, "Out of memory!");
1880+
return -1;
1881+
}
1882+
1883+
if (list)
1884+
list->next = new_sattr;
1885+
else {
1886+
if (state->base->segregate_attributes) {
1887+
segregate_attributes_rule_t *s;
1888+
for (s = state->base->segregate_attributes; s->next; s = s->next) {}
1889+
s->next = new_sattr;
1890+
} else
1891+
state->base->segregate_attributes = new_sattr;
1892+
}
1893+
list = new_sattr;
1894+
}
1895+
1896+
return 0;
1897+
}
1898+
18601899
/* Copy a module over to a base, remapping all values within. After
18611900
* all identifiers and rules are done, copy the scoping information.
18621901
* This is when it checks for duplicate declarations. */
@@ -1891,6 +1930,11 @@ static int copy_module(link_state_t * state, policy_module_t * module)
18911930
}
18921931
}
18931932

1933+
ret = copy_segregate_attributes(state, module);
1934+
if (ret) {
1935+
return ret;
1936+
}
1937+
18941938
return 0;
18951939
}
18961940

0 commit comments

Comments
 (0)