diff -ruNp linux-2.6-nsa-20050215/security/selinux/ss/mls.c linux-2.6-20050216/security/selinux/ss/mls.c --- linux-2.6-nsa-20050215/security/selinux/ss/mls.c 2005-01-27 16:48:31.000000000 -0600 +++ linux-2.6-20050216/security/selinux/ss/mls.c 2005-02-16 09:36:40.584230477 -0600 @@ -374,32 +374,23 @@ static inline int mls_scopy_context(stru } /* - * Copy the MLS level into the context. + * Copies the MLS range `range' into `context'. */ -int mls_level_cpy_and_set(struct context *scontext, struct mls_level *nlevel, - struct context *ncontext) +static inline int mls_range_set(struct context *context, + struct mls_range *range) { - int rc; + int l, rc = 0; - /* copy in the current clearance */ - ncontext->range.level[1].sens = scontext->range.level[1].sens; - rc = ebitmap_cpy(&ncontext->range.level[1].cat, - &scontext->range.level[1].cat); - if (rc) - return rc; - - /* copy in the new level */ - ncontext->range.level[0].sens = nlevel->sens; - rc = ebitmap_cpy(&ncontext->range.level[0].cat, &nlevel->cat); - if (rc) - return rc; - - /* check validity of new context */ - rc = mls_context_isvalid(&policydb, ncontext); - if (!rc) - return -EINVAL; + /* Copy the MLS range into the context */ + for (l = 0; l < 2; l++) { + context->range.level[l].sens = range->level[l].sens; + rc = ebitmap_cpy(&context->range.level[l].cat, + &range->level[l].cat); + if (rc) + break; + } - return 0; + return rc; } int mls_setup_user_range(struct context *fromcon, struct user_datum *user, @@ -497,6 +488,20 @@ int mls_compute_sid(struct context *scon switch (specified) { case AVTAB_TRANSITION: + if (tclass == SECCLASS_PROCESS) { + struct range_trans *rangetr; + /* Look for a range transition rule. */ + for (rangetr = policydb.range_tr; rangetr; + rangetr = rangetr->next) { + if (rangetr->dom == scontext->type && + rangetr->type == tcontext->type) { + /* Set the range from the rule */ + return mls_range_set(newcontext, + &rangetr->range); + } + } + } + /* Fallthrough */ case AVTAB_CHANGE: if (tclass == SECCLASS_PROCESS) /* Use the process MLS attributes. */ diff -ruNp linux-2.6-nsa-20050215/security/selinux/ss/mls.h linux-2.6-20050216/security/selinux/ss/mls.h --- linux-2.6-nsa-20050215/security/selinux/ss/mls.h 2005-01-27 16:48:31.000000000 -0600 +++ linux-2.6-20050216/security/selinux/ss/mls.h 2005-02-16 09:36:40.589229175 -0600 @@ -38,8 +38,5 @@ int mls_compute_sid(struct context *scon int mls_setup_user_range(struct context *fromcon, struct user_datum *user, struct context *usercon); -int mls_level_cpy_and_set(struct context *scontext, struct mls_level *nlevel, - struct context *ncontext); - #endif /* _SS_MLS_H */ diff -ruNp linux-2.6-nsa-20050215/security/selinux/ss/policydb.c linux-2.6-20050216/security/selinux/ss/policydb.c --- linux-2.6-nsa-20050215/security/selinux/ss/policydb.c 2005-02-15 10:30:46.000000000 -0600 +++ linux-2.6-20050216/security/selinux/ss/policydb.c 2005-02-16 09:36:40.598226832 -0600 @@ -1395,6 +1395,7 @@ int policydb_read(struct policydb *p, vo u32 buf[8], len, len2, config, nprim, nel, nel2; char *policydb_str; struct policydb_compat_info *info; + struct range_trans *rt, *lrt; config = 0; @@ -1800,6 +1801,35 @@ int policydb_read(struct policydb *p, vo } } + if (p->policyvers >= POLICYDB_VERSION_MLS) { + rc = next_entry(buf, fp, sizeof(u32)); + if (rc < 0) + goto bad; + nel = le32_to_cpu(buf[0]); + lrt = NULL; + for (i = 0; i < nel; i++) { + rt = kmalloc(sizeof(*rt), GFP_KERNEL); + if (!rt) { + rc = -ENOMEM; + goto bad; + } + memset(rt, 0, sizeof(*rt)); + if (lrt) + lrt->next = rt; + else + p->range_tr = rt; + rc = next_entry(buf, fp, (sizeof(u32) * 2)); + if (rc < 0) + goto bad; + rt->dom = le32_to_cpu(buf[0]); + rt->type = le32_to_cpu(buf[1]); + rc = mls_read_range_helper(&rt->range, fp); + if (rc) + goto bad; + lrt = rt; + } + } + rc = 0; out: return rc; diff -ruNp linux-2.6-nsa-20050215/security/selinux/ss/policydb.h linux-2.6-20050216/security/selinux/ss/policydb.h --- linux-2.6-nsa-20050215/security/selinux/ss/policydb.h 2005-01-27 16:48:31.000000000 -0600 +++ linux-2.6-20050216/security/selinux/ss/policydb.h 2005-02-16 09:36:40.604225271 -0600 @@ -105,6 +105,13 @@ struct cat_datum { unsigned char isalias; /* is this category an alias for another? */ }; +struct range_trans { + u32 dom; /* current process domain */ + u32 type; /* program executable type */ + struct mls_range range; /* new range */ + struct range_trans *next; +}; + /* Boolean data type */ struct cond_bool_datum { __u32 value; /* internal type value */ @@ -227,6 +234,9 @@ struct policydb { fixed labeling behavior. */ struct genfs *genfs; + /* range transitions */ + struct range_trans *range_tr; + unsigned int policyvers; }; diff -ruNp linux-2.6-nsa-20050215/security/selinux/ss/services.c linux-2.6-20050216/security/selinux/ss/services.c --- linux-2.6-nsa-20050215/security/selinux/ss/services.c 2005-01-27 16:48:31.000000000 -0600 +++ linux-2.6-20050216/security/selinux/ss/services.c 2005-02-16 09:36:40.612223188 -0600 @@ -844,13 +888,6 @@ static int security_compute_sid(u32 ssid } } } - - if (!type_change && !roletr) { - /* No change in process role or type. */ - *out_sid = ssid; - goto out_unlock; - - } break; default: break;