#define POLICYDB_VERSION_BOUNDARY 24
#define POLICYDB_VERSION_FILENAME_TRANS 25
#define POLICYDB_VERSION_ROLETRANS 26
+#define POLICYDB_VERSION_NEW_OBJECT_DEFAULTS 27
/* Range of policy versions we understand*/
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
#ifdef CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX
#define POLICYDB_VERSION_MAX CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX_VALUE
#else
-#define POLICYDB_VERSION_MAX POLICYDB_VERSION_ROLETRANS
+#define POLICYDB_VERSION_MAX POLICYDB_VERSION_NEW_OBJECT_DEFAULTS
#endif
/* Mask for just the mount related flags */
return rc;
}
+/*
+ * Sets both levels in the MLS range of 'dst' to the high level of 'src'.
+ */
+static inline int mls_context_cpy_high(struct context *dst, struct context *src)
+{
+ int rc;
+
+ dst->range.level[0].sens = src->range.level[1].sens;
+ rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[1].cat);
+ if (rc)
+ goto out;
+
+ dst->range.level[1].sens = src->range.level[1].sens;
+ rc = ebitmap_cpy(&dst->range.level[1].cat, &src->range.level[1].cat);
+ if (rc)
+ ebitmap_destroy(&dst->range.level[0].cat);
+out:
+ return rc;
+}
+
static inline int mls_context_cmp(struct context *c1, struct context *c2)
{
return ((c1->range.level[0].sens == c2->range.level[0].sens) &&
{
struct range_trans rtr;
struct mls_range *r;
+ struct class_datum *cladatum;
+ int default_range = 0;
if (!policydb.mls_enabled)
return 0;
r = hashtab_search(policydb.range_tr, &rtr);
if (r)
return mls_range_set(newcontext, r);
+
+ if (tclass && tclass <= policydb.p_classes.nprim) {
+ cladatum = policydb.class_val_to_struct[tclass - 1];
+ if (cladatum)
+ default_range = cladatum->default_range;
+ }
+
+ switch (default_range) {
+ case DEFAULT_SOURCE_LOW:
+ return mls_context_cpy_low(newcontext, scontext);
+ case DEFAULT_SOURCE_HIGH:
+ return mls_context_cpy_high(newcontext, scontext);
+ case DEFAULT_SOURCE_LOW_HIGH:
+ return mls_context_cpy(newcontext, scontext);
+ case DEFAULT_TARGET_LOW:
+ return mls_context_cpy_low(newcontext, tcontext);
+ case DEFAULT_TARGET_HIGH:
+ return mls_context_cpy_high(newcontext, tcontext);
+ case DEFAULT_TARGET_LOW_HIGH:
+ return mls_context_cpy(newcontext, tcontext);
+ }
+
/* Fallthrough */
case AVTAB_CHANGE:
if ((tclass == policydb.process_class) || (sock == true))
.sym_num = SYM_NUM,
.ocon_num = OCON_NUM,
},
+ {
+ .version = POLICYDB_VERSION_NEW_OBJECT_DEFAULTS,
+ .sym_num = SYM_NUM,
+ .ocon_num = OCON_NUM,
+ },
};
static struct policydb_compat_info *policydb_lookup_compat(int version)
goto bad;
}
+ if (p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) {
+ rc = next_entry(buf, fp, sizeof(u32) * 3);
+ if (rc)
+ goto bad;
+
+ cladatum->default_user = le32_to_cpu(buf[0]);
+ cladatum->default_role = le32_to_cpu(buf[1]);
+ cladatum->default_range = le32_to_cpu(buf[2]);
+ }
+
rc = hashtab_insert(h, key, cladatum);
if (rc)
goto bad;
if (rc)
return rc;
+ if (p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) {
+ buf[0] = cpu_to_le32(cladatum->default_user);
+ buf[1] = cpu_to_le32(cladatum->default_role);
+ buf[2] = cpu_to_le32(cladatum->default_range);
+
+ rc = put_entry(buf, sizeof(uint32_t), 3, fp);
+ if (rc)
+ return rc;
+ }
+
return 0;
}
struct symtab permissions; /* class-specific permission symbol table */
struct constraint_node *constraints; /* constraints on class permissions */
struct constraint_node *validatetrans; /* special transition rules */
+ /* Options how a new object user and role should be decided */
+#define DEFAULT_SOURCE 1
+#define DEFAULT_TARGET 2
+ char default_user;
+ char default_role;
+/* Options how a new object range should be decided */
+#define DEFAULT_SOURCE_LOW 1
+#define DEFAULT_SOURCE_HIGH 2
+#define DEFAULT_SOURCE_LOW_HIGH 3
+#define DEFAULT_TARGET_LOW 4
+#define DEFAULT_TARGET_HIGH 5
+#define DEFAULT_TARGET_LOW_HIGH 6
+ char default_range;
};
/* Role attributes */
u32 *out_sid,
bool kern)
{
+ struct class_datum *cladatum = NULL;
struct context *scontext = NULL, *tcontext = NULL, newcontext;
struct role_trans *roletr = NULL;
struct avtab_key avkey;
goto out_unlock;
}
+ if (tclass && tclass <= policydb.p_classes.nprim)
+ cladatum = policydb.class_val_to_struct[tclass - 1];
+
/* Set the user identity. */
switch (specified) {
case AVTAB_TRANSITION:
case AVTAB_CHANGE:
- /* Use the process user identity. */
- newcontext.user = scontext->user;
+ if (cladatum && cladatum->default_user == DEFAULT_TARGET) {
+ newcontext.user = tcontext->user;
+ } else {
+ /* notice this gets both DEFAULT_SOURCE and unset */
+ /* Use the process user identity. */
+ newcontext.user = scontext->user;
+ }
break;
case AVTAB_MEMBER:
/* Use the related object owner. */
break;
}
- /* Set the role and type to default values. */
- if ((tclass == policydb.process_class) || (sock == true)) {
- /* Use the current role and type of process. */
+ /* Set the role to default values. */
+ if (cladatum && cladatum->default_role == DEFAULT_SOURCE) {
newcontext.role = scontext->role;
+ } else if (cladatum && cladatum->default_role == DEFAULT_TARGET) {
+ newcontext.role = tcontext->role;
+ } else {
+ if ((tclass == policydb.process_class) || (sock == true))
+ newcontext.role = scontext->role;
+ else
+ newcontext.role = OBJECT_R_VAL;
+ }
+
+ /* Set the type to default values. */
+ if ((tclass == policydb.process_class) || (sock == true)) {
+ /* Use the type of process. */
newcontext.type = scontext->type;
} else {
- /* Use the well-defined object role. */
- newcontext.role = OBJECT_R_VAL;
/* Use the type of the related object. */
newcontext.type = tcontext->type;
}