selinux: add type_transition with name extension support for selinuxfs
Kohei Kaigai [Fri, 1 Apr 2011 14:39:26 +0000 (15:39 +0100)]
The attached patch allows /selinux/create takes optional 4th argument
to support TYPE_TRANSITION with name extension for userspace object
managers.
If 4th argument is not supplied, it shall perform as existing kernel.
In fact, the regression test of SE-PostgreSQL works well on the patched
kernel.

Thanks,

Signed-off-by: KaiGai Kohei <kohei.kaigai@eu.nec.com>
[manually verify fuzz was not an issue, and it wasn't: eparis]
Signed-off-by: Eric Paris <eparis@redhat.com>

security/selinux/include/security.h
security/selinux/selinuxfs.c
security/selinux/ss/services.c

index bfc5218..2cf6708 100644 (file)
@@ -112,8 +112,8 @@ void security_compute_av_user(u32 ssid, u32 tsid,
 int security_transition_sid(u32 ssid, u32 tsid, u16 tclass,
                            const struct qstr *qstr, u32 *out_sid);
 
-int security_transition_sid_user(u32 ssid, u32 tsid,
-                                u16 tclass, u32 *out_sid);
+int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass,
+                                const char *objname, u32 *out_sid);
 
 int security_member_sid(u32 ssid, u32 tsid,
        u16 tclass, u32 *out_sid);
index ea39cb7..973f5a4 100644 (file)
@@ -753,11 +753,13 @@ out:
 static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
 {
        char *scon = NULL, *tcon = NULL;
+       char *namebuf = NULL, *objname = NULL;
        u32 ssid, tsid, newsid;
        u16 tclass;
        ssize_t length;
        char *newcon = NULL;
        u32 len;
+       int nargs;
 
        length = task_has_security(current, SECURITY__COMPUTE_CREATE);
        if (length)
@@ -773,9 +775,17 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
        if (!tcon)
                goto out;
 
+       length = -ENOMEM;
+       namebuf = kzalloc(size + 1, GFP_KERNEL);
+       if (!namebuf)
+               goto out;
+
        length = -EINVAL;
-       if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
+       nargs = sscanf(buf, "%s %s %hu %s", scon, tcon, &tclass, namebuf);
+       if (nargs < 3 || nargs > 4)
                goto out;
+       if (nargs == 4)
+               objname = namebuf;
 
        length = security_context_to_sid(scon, strlen(scon) + 1, &ssid);
        if (length)
@@ -785,7 +795,8 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
        if (length)
                goto out;
 
-       length = security_transition_sid_user(ssid, tsid, tclass, &newsid);
+       length = security_transition_sid_user(ssid, tsid, tclass,
+                                             objname, &newsid);
        if (length)
                goto out;
 
@@ -804,6 +815,7 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
        length = len;
 out:
        kfree(newcon);
+       kfree(namebuf);
        kfree(tcon);
        kfree(scon);
        return length;
index 03f7a47..39d7321 100644 (file)
@@ -1360,14 +1360,14 @@ out:
 
 static void filename_compute_type(struct policydb *p, struct context *newcontext,
                                  u32 scon, u32 tcon, u16 tclass,
-                                 const struct qstr *qstr)
+                                 const char *objname)
 {
        struct filename_trans *ft;
        for (ft = p->filename_trans; ft; ft = ft->next) {
                if (ft->stype == scon &&
                    ft->ttype == tcon &&
                    ft->tclass == tclass &&
-                   !strcmp(ft->name, qstr->name)) {
+                   !strcmp(ft->name, objname)) {
                        newcontext->type = ft->otype;
                        return;
                }
@@ -1378,7 +1378,7 @@ static int security_compute_sid(u32 ssid,
                                u32 tsid,
                                u16 orig_tclass,
                                u32 specified,
-                               const struct qstr *qstr,
+                               const char *objname,
                                u32 *out_sid,
                                bool kern)
 {
@@ -1479,9 +1479,9 @@ static int security_compute_sid(u32 ssid,
        }
 
        /* if we have a qstr this is a file trans check so check those rules */
-       if (qstr)
+       if (objname)
                filename_compute_type(&policydb, &newcontext, scontext->type,
-                                     tcontext->type, tclass, qstr);
+                                     tcontext->type, tclass, objname);
 
        /* Check for class-specific changes. */
        if (specified & AVTAB_TRANSITION) {
@@ -1539,13 +1539,14 @@ int security_transition_sid(u32 ssid, u32 tsid, u16 tclass,
                            const struct qstr *qstr, u32 *out_sid)
 {
        return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION,
-                                   qstr, out_sid, true);
+                                   qstr ? qstr->name : NULL, out_sid, true);
 }
 
-int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass, u32 *out_sid)
+int security_transition_sid_user(u32 ssid, u32 tsid, u16 tclass,
+                                const char *objname, u32 *out_sid)
 {
        return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION,
-                                   NULL, out_sid, false);
+                                   objname, out_sid, false);
 }
 
 /**