Commit 64dbf07474d011540ca479a2e87fe998f570d6e3
Committed by
James Morris
1 parent
0356357c51
Exists in
master
and in
7 other branches
selinux: introduce permissive types
Introduce the concept of a permissive type. A new ebitmap is introduced to the policy database which indicates if a given type has the permissive bit set or not. This bit is tested for the scontext of any denial. The bit is meaningless on types which only appear as the target of a decision and never the source. A domain running with a permissive type will be allowed to perform any action similarly to when the system is globally set permissive. Signed-off-by: Eric Paris <eparis@redhat.com> Acked-by: Stephen Smalley <sds@tycho.nsa.gov> Signed-off-by: James Morris <jmorris@namei.org>
Showing 6 changed files with 48 additions and 6 deletions Side-by-side Diff
security/selinux/Kconfig
... | ... | @@ -145,7 +145,7 @@ |
145 | 145 | config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE |
146 | 146 | int "NSA SELinux maximum supported policy format version value" |
147 | 147 | depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX |
148 | - range 15 22 | |
148 | + range 15 23 | |
149 | 149 | default 19 |
150 | 150 | help |
151 | 151 | This option sets the value for the maximum policy format version |
security/selinux/avc.c
... | ... | @@ -893,12 +893,13 @@ |
893 | 893 | denied = requested & ~(p_ae->avd.allowed); |
894 | 894 | |
895 | 895 | if (denied) { |
896 | - if (selinux_enforcing || (flags & AVC_STRICT)) | |
896 | + if (flags & AVC_STRICT) | |
897 | 897 | rc = -EACCES; |
898 | + else if (!selinux_enforcing || security_permissive_sid(ssid)) | |
899 | + avc_update_node(AVC_CALLBACK_GRANT, requested, ssid, | |
900 | + tsid, tclass); | |
898 | 901 | else |
899 | - if (node) | |
900 | - avc_update_node(AVC_CALLBACK_GRANT,requested, | |
901 | - ssid,tsid,tclass); | |
902 | + rc = -EACCES; | |
902 | 903 | } |
903 | 904 | |
904 | 905 | rcu_read_unlock(); |
security/selinux/include/security.h
... | ... | @@ -26,13 +26,14 @@ |
26 | 26 | #define POLICYDB_VERSION_AVTAB 20 |
27 | 27 | #define POLICYDB_VERSION_RANGETRANS 21 |
28 | 28 | #define POLICYDB_VERSION_POLCAP 22 |
29 | +#define POLICYDB_VERSION_PERMISSIVE 23 | |
29 | 30 | |
30 | 31 | /* Range of policy versions we understand*/ |
31 | 32 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE |
32 | 33 | #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX |
33 | 34 | #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE |
34 | 35 | #else |
35 | -#define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP | |
36 | +#define POLICYDB_VERSION_MAX POLICYDB_VERSION_PERMISSIVE | |
36 | 37 | #endif |
37 | 38 | |
38 | 39 | #define CONTEXT_MNT 0x01 |
... | ... | @@ -68,6 +69,8 @@ |
68 | 69 | u32 auditdeny; |
69 | 70 | u32 seqno; |
70 | 71 | }; |
72 | + | |
73 | +int security_permissive_sid(u32 sid); | |
71 | 74 | |
72 | 75 | int security_compute_av(u32 ssid, u32 tsid, |
73 | 76 | u16 tclass, u32 requested, |
security/selinux/ss/policydb.c
... | ... | @@ -111,6 +111,11 @@ |
111 | 111 | .version = POLICYDB_VERSION_POLCAP, |
112 | 112 | .sym_num = SYM_NUM, |
113 | 113 | .ocon_num = OCON_NUM, |
114 | + }, | |
115 | + { | |
116 | + .version = POLICYDB_VERSION_PERMISSIVE, | |
117 | + .sym_num = SYM_NUM, | |
118 | + .ocon_num = OCON_NUM, | |
114 | 119 | } |
115 | 120 | }; |
116 | 121 | |
... | ... | @@ -194,6 +199,7 @@ |
194 | 199 | goto out_free_symtab; |
195 | 200 | |
196 | 201 | ebitmap_init(&p->policycaps); |
202 | + ebitmap_init(&p->permissive_map); | |
197 | 203 | |
198 | 204 | out: |
199 | 205 | return rc; |
... | ... | @@ -687,6 +693,7 @@ |
687 | 693 | kfree(p->type_attr_map); |
688 | 694 | kfree(p->undefined_perms); |
689 | 695 | ebitmap_destroy(&p->policycaps); |
696 | + ebitmap_destroy(&p->permissive_map); | |
690 | 697 | |
691 | 698 | return; |
692 | 699 | } |
... | ... | @@ -1568,6 +1575,10 @@ |
1568 | 1575 | |
1569 | 1576 | if (p->policyvers >= POLICYDB_VERSION_POLCAP && |
1570 | 1577 | ebitmap_read(&p->policycaps, fp) != 0) |
1578 | + goto bad; | |
1579 | + | |
1580 | + if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE && | |
1581 | + ebitmap_read(&p->permissive_map, fp) != 0) | |
1571 | 1582 | goto bad; |
1572 | 1583 | |
1573 | 1584 | info = policydb_lookup_compat(p->policyvers); |
security/selinux/ss/policydb.h
security/selinux/ss/services.c
... | ... | @@ -417,6 +417,31 @@ |
417 | 417 | return -EINVAL; |
418 | 418 | } |
419 | 419 | |
420 | +/* | |
421 | + * Given a sid find if the type has the permissive flag set | |
422 | + */ | |
423 | +int security_permissive_sid(u32 sid) | |
424 | +{ | |
425 | + struct context *context; | |
426 | + u32 type; | |
427 | + int rc; | |
428 | + | |
429 | + POLICY_RDLOCK; | |
430 | + | |
431 | + context = sidtab_search(&sidtab, sid); | |
432 | + BUG_ON(!context); | |
433 | + | |
434 | + type = context->type; | |
435 | + /* | |
436 | + * we are intentionally using type here, not type-1, the 0th bit may | |
437 | + * someday indicate that we are globally setting permissive in policy. | |
438 | + */ | |
439 | + rc = ebitmap_get_bit(&policydb.permissive_map, type); | |
440 | + | |
441 | + POLICY_RDUNLOCK; | |
442 | + return rc; | |
443 | +} | |
444 | + | |
420 | 445 | static int security_validtrans_handle_fail(struct context *ocontext, |
421 | 446 | struct context *ncontext, |
422 | 447 | struct context *tcontext, |