aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2008-03-30 21:17:33 -0400
committerJames Morris <jmorris@namei.org>2008-04-18 06:26:11 -0400
commit64dbf07474d011540ca479a2e87fe998f570d6e3 (patch)
tree364ae3f3a29f06246dd2097674586fe508c4445f /security
parent0356357c5158c71d4cbf20196b2f784435dd916c (diff)
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>
Diffstat (limited to 'security')
-rw-r--r--security/selinux/Kconfig2
-rw-r--r--security/selinux/avc.c9
-rw-r--r--security/selinux/include/security.h5
-rw-r--r--security/selinux/ss/policydb.c11
-rw-r--r--security/selinux/ss/policydb.h2
-rw-r--r--security/selinux/ss/services.c25
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
145config SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE 145config 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
73int security_permissive_sid(u32 sid);
74
72int security_compute_av(u32 ssid, u32 tsid, 75int 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
198out: 204out:
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 */
423int 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
420static int security_validtrans_handle_fail(struct context *ocontext, 445static int security_validtrans_handle_fail(struct context *ocontext,
421 struct context *ncontext, 446 struct context *ncontext,
422 struct context *tcontext, 447 struct context *tcontext,