Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[pandora-kernel.git] / security / selinux / ss / services.c
index a03cfaf..3e7544d 100644 (file)
@@ -201,6 +201,21 @@ static u16 unmap_class(u16 tclass)
        return tclass;
 }
 
+/*
+ * Get kernel value for class from its policy value
+ */
+static u16 map_class(u16 pol_value)
+{
+       u16 i;
+
+       for (i = 1; i < current_mapping_size; i++) {
+               if (current_mapping[i].value == pol_value)
+                       return i;
+       }
+
+       return pol_value;
+}
+
 static void map_decision(u16 tclass, struct av_decision *avd,
                         int allow_unknown)
 {
@@ -1343,10 +1358,27 @@ out:
        return -EACCES;
 }
 
+static void filename_compute_type(struct policydb *p, struct context *newcontext,
+                                 u32 scon, u32 tcon, u16 tclass,
+                                 const struct qstr *qstr)
+{
+       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)) {
+                       newcontext->type = ft->otype;
+                       return;
+               }
+       }
+}
+
 static int security_compute_sid(u32 ssid,
                                u32 tsid,
                                u16 orig_tclass,
                                u32 specified,
+                               const struct qstr *qstr,
                                u32 *out_sid,
                                bool kern)
 {
@@ -1357,6 +1389,7 @@ static int security_compute_sid(u32 ssid,
        struct avtab_node *node;
        u16 tclass;
        int rc = 0;
+       bool sock;
 
        if (!ss_initialized) {
                switch (orig_tclass) {
@@ -1374,10 +1407,13 @@ static int security_compute_sid(u32 ssid,
 
        read_lock(&policy_rwlock);
 
-       if (kern)
+       if (kern) {
                tclass = unmap_class(orig_tclass);
-       else
+               sock = security_is_socket_class(orig_tclass);
+       } else {
                tclass = orig_tclass;
+               sock = security_is_socket_class(map_class(tclass));
+       }
 
        scontext = sidtab_search(&sidtab, ssid);
        if (!scontext) {
@@ -1408,7 +1444,7 @@ static int security_compute_sid(u32 ssid,
        }
 
        /* Set the role and type to default values. */
-       if (tclass == policydb.process_class) {
+       if ((tclass == policydb.process_class) || (sock == true)) {
                /* Use the current role and type of process. */
                newcontext.role = scontext->role;
                newcontext.type = scontext->type;
@@ -1442,6 +1478,11 @@ static int security_compute_sid(u32 ssid,
                newcontext.type = avdatum->data;
        }
 
+       /* if we have a qstr this is a file trans check so check those rules */
+       if (qstr)
+               filename_compute_type(&policydb, &newcontext, scontext->type,
+                                     tcontext->type, tclass, qstr);
+
        /* Check for class-specific changes. */
        if  (tclass == policydb.process_class) {
                if (specified & AVTAB_TRANSITION) {
@@ -1460,7 +1501,8 @@ static int security_compute_sid(u32 ssid,
 
        /* Set the MLS attributes.
           This is done last because it may allocate memory. */
-       rc = mls_compute_sid(scontext, tcontext, tclass, specified, &newcontext);
+       rc = mls_compute_sid(scontext, tcontext, tclass, specified,
+                            &newcontext, sock);
        if (rc)
                goto out_unlock;
 
@@ -1495,22 +1537,17 @@ out:
  * if insufficient memory is available, or %0 if the new SID was
  * computed successfully.
  */
-int security_transition_sid(u32 ssid,
-                           u32 tsid,
-                           u16 tclass,
-                           u32 *out_sid)
+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,
-                                   out_sid, true);
+                                   qstr, 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, u32 *out_sid)
 {
        return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION,
-                                   out_sid, false);
+                                   NULL, out_sid, false);
 }
 
 /**
@@ -1531,8 +1568,8 @@ int security_member_sid(u32 ssid,
                        u16 tclass,
                        u32 *out_sid)
 {
-       return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid,
-                                   false);
+       return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, NULL,
+                                   out_sid, false);
 }
 
 /**
@@ -1553,8 +1590,8 @@ int security_change_sid(u32 ssid,
                        u16 tclass,
                        u32 *out_sid)
 {
-       return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid,
-                                   false);
+       return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, NULL,
+                                   out_sid, false);
 }
 
 /* Clone the SID into the new SID table. */