Permissive domain in userspace object manager
authorKaiGai Kohei <kaigai@ak.jp.nec.com>
Wed, 1 Apr 2009 01:07:57 +0000 (10:07 +0900)
committerJames Morris <jmorris@namei.org>
Wed, 1 Apr 2009 22:23:45 +0000 (09:23 +1100)
This patch enables applications to handle permissive domain correctly.

Since the v2.6.26 kernel, SELinux has supported an idea of permissive
domain which allows certain processes to work as if permissive mode,
even if the global setting is enforcing mode.
However, we don't have an application program interface to inform
what domains are permissive one, and what domains are not.
It means applications focuses on SELinux (XACE/SELinux, SE-PostgreSQL
and so on) cannot handle permissive domain correctly.

This patch add the sixth field (flags) on the reply of the /selinux/access
interface which is used to make an access control decision from userspace.
If the first bit of the flags field is positive, it means the required
access control decision is on permissive domain, so application should
allow any required actions, as the kernel doing.

This patch also has a side benefit. The av_decision.flags is set at
context_struct_compute_av(). It enables to check required permissions
without read_lock(&policy_rwlock).

Signed-off-by: KaiGai Kohei <kaigai@ak.jp.nec.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
Acked-by: Eric Paris <eparis@redhat.com>
--
 security/selinux/avc.c              |    2 +-
 security/selinux/include/security.h |    4 +++-
 security/selinux/selinuxfs.c        |    4 ++--
 security/selinux/ss/services.c      |   30 +++++-------------------------
 4 files changed, 11 insertions(+), 29 deletions(-)
Signed-off-by: James Morris <jmorris@namei.org>
security/selinux/avc.c
security/selinux/include/security.h
security/selinux/selinuxfs.c
security/selinux/ss/services.c

index 7f9b5fac87793a19faf3d310a4e04f8a158bb476..b2ab608598325bcea26430f6ebd1eac30a67ad61 100644 (file)
@@ -927,7 +927,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
        if (denied) {
                if (flags & AVC_STRICT)
                        rc = -EACCES;
-               else if (!selinux_enforcing || security_permissive_sid(ssid))
+               else if (!selinux_enforcing || (avd->flags & AVD_FLAGS_PERMISSIVE))
                        avc_update_node(AVC_CALLBACK_GRANT, requested, ssid,
                                        tsid, tclass, avd->seqno);
                else
index 5c3434f7626fdd5cbe81ff0120ad3f092713fd95..a7be3f01fb08143c303d555006b42f327fb1e729 100644 (file)
@@ -91,9 +91,11 @@ struct av_decision {
        u32 auditallow;
        u32 auditdeny;
        u32 seqno;
+       u32 flags;
 };
 
-int security_permissive_sid(u32 sid);
+/* definitions of av_decision.flags */
+#define AVD_FLAGS_PERMISSIVE   0x0001
 
 int security_compute_av(u32 ssid, u32 tsid,
        u16 tclass, u32 requested,
index 2d5136ec3d5451c945f89e59b2f9ea4433bfa6a4..8d4007fbe0e96c4476bdacfce3416b3bd4f574ee 100644 (file)
@@ -527,10 +527,10 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size)
                goto out2;
 
        length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT,
-                         "%x %x %x %x %u",
+                         "%x %x %x %x %u %x",
                          avd.allowed, 0xffffffff,
                          avd.auditallow, avd.auditdeny,
-                         avd.seqno);
+                         avd.seqno, avd.flags);
 out2:
        kfree(tcon);
 out:
index deeec6c013aef6dee9d664e3fe46b0a892d9f27e..500e6f78e1159e1d568355ce74a113b4b49859c1 100644 (file)
@@ -410,6 +410,7 @@ static int context_struct_compute_av(struct context *scontext,
        avd->auditallow = 0;
        avd->auditdeny = 0xffffffff;
        avd->seqno = latest_granting;
+       avd->flags = 0;
 
        /*
         * Check for all the invalid cases.
@@ -528,31 +529,6 @@ inval_class:
        return 0;
 }
 
-/*
- * Given a sid find if the type has the permissive flag set
- */
-int security_permissive_sid(u32 sid)
-{
-       struct context *context;
-       u32 type;
-       int rc;
-
-       read_lock(&policy_rwlock);
-
-       context = sidtab_search(&sidtab, sid);
-       BUG_ON(!context);
-
-       type = context->type;
-       /*
-        * we are intentionally using type here, not type-1, the 0th bit may
-        * someday indicate that we are globally setting permissive in policy.
-        */
-       rc = ebitmap_get_bit(&policydb.permissive_map, type);
-
-       read_unlock(&policy_rwlock);
-       return rc;
-}
-
 static int security_validtrans_handle_fail(struct context *ocontext,
                                           struct context *ncontext,
                                           struct context *tcontext,
@@ -767,6 +743,10 @@ int security_compute_av(u32 ssid,
 
        rc = context_struct_compute_av(scontext, tcontext, tclass,
                                       requested, avd);
+
+       /* permissive domain? */
+       if (ebitmap_get_bit(&policydb.permissive_map, scontext->type))
+           avd->flags |= AVD_FLAGS_PERMISSIVE;
 out:
        read_unlock(&policy_rwlock);
        return rc;