diff options
-rw-r--r-- | security/selinux/Kconfig | 2 | ||||
-rw-r--r-- | security/selinux/avc.c | 9 | ||||
-rw-r--r-- | security/selinux/include/security.h | 5 | ||||
-rw-r--r-- | security/selinux/ss/policydb.c | 11 | ||||
-rw-r--r-- | security/selinux/ss/policydb.h | 2 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 25 |
6 files changed, 48 insertions, 6 deletions
diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig index 2b517d618672..a436d1cfa88b 100644 --- a/security/selinux/Kconfig +++ b/security/selinux/Kconfig | |||
@@ -145,7 +145,7 @@ config SECURITY_SELINUX_POLICYDB_VERSION_MAX | |||
145 | config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE | 145 | config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE |
146 | int "NSA SELinux maximum supported policy format version value" | 146 | int "NSA SELinux maximum supported policy format version value" |
147 | depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX | 147 | depends on SECURITY_SELINUX_POLICYDB_VERSION_MAX |
148 | range 15 22 | 148 | range 15 23 |
149 | default 19 | 149 | default 19 |
150 | help | 150 | help |
151 | This option sets the value for the maximum policy format version | 151 | This option sets the value for the maximum policy format version |
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index cb3f0ce0b00a..a4fc6e6d038a 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -893,12 +893,13 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
893 | denied = requested & ~(p_ae->avd.allowed); | 893 | denied = requested & ~(p_ae->avd.allowed); |
894 | 894 | ||
895 | if (denied) { | 895 | if (denied) { |
896 | if (selinux_enforcing || (flags & AVC_STRICT)) | 896 | if (flags & AVC_STRICT) |
897 | rc = -EACCES; | 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 | else | 901 | else |
899 | if (node) | 902 | rc = -EACCES; |
900 | avc_update_node(AVC_CALLBACK_GRANT,requested, | ||
901 | ssid,tsid,tclass); | ||
902 | } | 903 | } |
903 | 904 | ||
904 | rcu_read_unlock(); | 905 | rcu_read_unlock(); |
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index 315b4ec1e12a..dd70aa084637 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
@@ -26,13 +26,14 @@ | |||
26 | #define POLICYDB_VERSION_AVTAB 20 | 26 | #define POLICYDB_VERSION_AVTAB 20 |
27 | #define POLICYDB_VERSION_RANGETRANS 21 | 27 | #define POLICYDB_VERSION_RANGETRANS 21 |
28 | #define POLICYDB_VERSION_POLCAP 22 | 28 | #define POLICYDB_VERSION_POLCAP 22 |
29 | #define POLICYDB_VERSION_PERMISSIVE 23 | ||
29 | 30 | ||
30 | /* Range of policy versions we understand*/ | 31 | /* Range of policy versions we understand*/ |
31 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE | 32 | #define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE |
32 | #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX | 33 | #ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX |
33 | #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE | 34 | #define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE |
34 | #else | 35 | #else |
35 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_POLCAP | 36 | #define POLICYDB_VERSION_MAX POLICYDB_VERSION_PERMISSIVE |
36 | #endif | 37 | #endif |
37 | 38 | ||
38 | #define CONTEXT_MNT 0x01 | 39 | #define CONTEXT_MNT 0x01 |
@@ -69,6 +70,8 @@ struct av_decision { | |||
69 | u32 seqno; | 70 | u32 seqno; |
70 | }; | 71 | }; |
71 | 72 | ||
73 | int security_permissive_sid(u32 sid); | ||
74 | |||
72 | int security_compute_av(u32 ssid, u32 tsid, | 75 | int security_compute_av(u32 ssid, u32 tsid, |
73 | u16 tclass, u32 requested, | 76 | u16 tclass, u32 requested, |
74 | struct av_decision *avd); | 77 | struct av_decision *avd); |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 325551cd7fc7..6bdb0ff6a927 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -111,6 +111,11 @@ static struct policydb_compat_info policydb_compat[] = { | |||
111 | .version = POLICYDB_VERSION_POLCAP, | 111 | .version = POLICYDB_VERSION_POLCAP, |
112 | .sym_num = SYM_NUM, | 112 | .sym_num = SYM_NUM, |
113 | .ocon_num = OCON_NUM, | 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 @@ static int policydb_init(struct policydb *p) | |||
194 | goto out_free_symtab; | 199 | goto out_free_symtab; |
195 | 200 | ||
196 | ebitmap_init(&p->policycaps); | 201 | ebitmap_init(&p->policycaps); |
202 | ebitmap_init(&p->permissive_map); | ||
197 | 203 | ||
198 | out: | 204 | out: |
199 | return rc; | 205 | return rc; |
@@ -687,6 +693,7 @@ void policydb_destroy(struct policydb *p) | |||
687 | kfree(p->type_attr_map); | 693 | kfree(p->type_attr_map); |
688 | kfree(p->undefined_perms); | 694 | kfree(p->undefined_perms); |
689 | ebitmap_destroy(&p->policycaps); | 695 | ebitmap_destroy(&p->policycaps); |
696 | ebitmap_destroy(&p->permissive_map); | ||
690 | 697 | ||
691 | return; | 698 | return; |
692 | } | 699 | } |
@@ -1570,6 +1577,10 @@ int policydb_read(struct policydb *p, void *fp) | |||
1570 | ebitmap_read(&p->policycaps, fp) != 0) | 1577 | ebitmap_read(&p->policycaps, fp) != 0) |
1571 | goto bad; | 1578 | goto bad; |
1572 | 1579 | ||
1580 | if (p->policyvers >= POLICYDB_VERSION_PERMISSIVE && | ||
1581 | ebitmap_read(&p->permissive_map, fp) != 0) | ||
1582 | goto bad; | ||
1583 | |||
1573 | info = policydb_lookup_compat(p->policyvers); | 1584 | info = policydb_lookup_compat(p->policyvers); |
1574 | if (!info) { | 1585 | if (!info) { |
1575 | printk(KERN_ERR "SELinux: unable to find policy compat info " | 1586 | printk(KERN_ERR "SELinux: unable to find policy compat info " |
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index c4ce996e202c..ba593a3da877 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h | |||
@@ -243,6 +243,8 @@ struct policydb { | |||
243 | 243 | ||
244 | struct ebitmap policycaps; | 244 | struct ebitmap policycaps; |
245 | 245 | ||
246 | struct ebitmap permissive_map; | ||
247 | |||
246 | unsigned int policyvers; | 248 | unsigned int policyvers; |
247 | 249 | ||
248 | unsigned int reject_unknown : 1; | 250 | unsigned int reject_unknown : 1; |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index face5795c760..eefa89ce77a7 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -417,6 +417,31 @@ inval_class: | |||
417 | return -EINVAL; | 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 | static int security_validtrans_handle_fail(struct context *ocontext, | 445 | static int security_validtrans_handle_fail(struct context *ocontext, |
421 | struct context *ncontext, | 446 | struct context *ncontext, |
422 | struct context *tcontext, | 447 | struct context *tcontext, |