mirror of
https://github.com/FEX-Emu/linux.git
synced 2024-12-13 11:51:32 +00:00
Merge branch 'master' of git://git.infradead.org/users/eparis/selinux into next
This commit is contained in:
commit
aeda4ac3ef
@ -71,7 +71,7 @@ void *flex_array_get(struct flex_array *fa, unsigned int element_nr);
|
|||||||
int flex_array_shrink(struct flex_array *fa);
|
int flex_array_shrink(struct flex_array *fa);
|
||||||
|
|
||||||
#define flex_array_put_ptr(fa, nr, src, gfp) \
|
#define flex_array_put_ptr(fa, nr, src, gfp) \
|
||||||
flex_array_put(fa, nr, &(void *)(src), gfp)
|
flex_array_put(fa, nr, (void *)&(src), gfp)
|
||||||
|
|
||||||
void *flex_array_get_ptr(struct flex_array *fa, unsigned int element_nr);
|
void *flex_array_get_ptr(struct flex_array *fa, unsigned int element_nr);
|
||||||
|
|
||||||
|
@ -2525,7 +2525,10 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
|
|||||||
sid = tsec->sid;
|
sid = tsec->sid;
|
||||||
newsid = tsec->create_sid;
|
newsid = tsec->create_sid;
|
||||||
|
|
||||||
if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
|
if ((sbsec->flags & SE_SBINITIALIZED) &&
|
||||||
|
(sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
|
||||||
|
newsid = sbsec->mntpoint_sid;
|
||||||
|
else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) {
|
||||||
rc = security_transition_sid(sid, dsec->sid,
|
rc = security_transition_sid(sid, dsec->sid,
|
||||||
inode_mode_to_security_class(inode->i_mode),
|
inode_mode_to_security_class(inode->i_mode),
|
||||||
&newsid);
|
&newsid);
|
||||||
|
@ -65,6 +65,8 @@ static struct nlmsg_perm nlmsg_route_perms[] =
|
|||||||
{ RTM_NEWADDRLABEL, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
{ RTM_NEWADDRLABEL, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||||
{ RTM_DELADDRLABEL, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
{ RTM_DELADDRLABEL, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||||
{ RTM_GETADDRLABEL, NETLINK_ROUTE_SOCKET__NLMSG_READ },
|
{ RTM_GETADDRLABEL, NETLINK_ROUTE_SOCKET__NLMSG_READ },
|
||||||
|
{ RTM_GETDCB, NETLINK_ROUTE_SOCKET__NLMSG_READ },
|
||||||
|
{ RTM_SETDCB, NETLINK_ROUTE_SOCKET__NLMSG_WRITE },
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct nlmsg_perm nlmsg_firewall_perms[] =
|
static struct nlmsg_perm nlmsg_firewall_perms[] =
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -193,6 +193,7 @@ int cond_index_bool(void *key, void *datum, void *datap)
|
|||||||
{
|
{
|
||||||
struct policydb *p;
|
struct policydb *p;
|
||||||
struct cond_bool_datum *booldatum;
|
struct cond_bool_datum *booldatum;
|
||||||
|
struct flex_array *fa;
|
||||||
|
|
||||||
booldatum = datum;
|
booldatum = datum;
|
||||||
p = datap;
|
p = datap;
|
||||||
@ -200,7 +201,10 @@ int cond_index_bool(void *key, void *datum, void *datap)
|
|||||||
if (!booldatum->value || booldatum->value > p->p_bools.nprim)
|
if (!booldatum->value || booldatum->value > p->p_bools.nprim)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
p->p_bool_val_to_name[booldatum->value - 1] = key;
|
fa = p->sym_val_to_name[SYM_BOOLS];
|
||||||
|
if (flex_array_put_ptr(fa, booldatum->value - 1, key,
|
||||||
|
GFP_KERNEL | __GFP_ZERO))
|
||||||
|
BUG();
|
||||||
p->bool_val_to_struct[booldatum->value - 1] = booldatum;
|
p->bool_val_to_struct[booldatum->value - 1] = booldatum;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -45,7 +45,7 @@ int mls_compute_context_len(struct context *context)
|
|||||||
len = 1; /* for the beginning ":" */
|
len = 1; /* for the beginning ":" */
|
||||||
for (l = 0; l < 2; l++) {
|
for (l = 0; l < 2; l++) {
|
||||||
int index_sens = context->range.level[l].sens;
|
int index_sens = context->range.level[l].sens;
|
||||||
len += strlen(policydb.p_sens_val_to_name[index_sens - 1]);
|
len += strlen(sym_name(&policydb, SYM_LEVELS, index_sens - 1));
|
||||||
|
|
||||||
/* categories */
|
/* categories */
|
||||||
head = -2;
|
head = -2;
|
||||||
@ -55,17 +55,17 @@ int mls_compute_context_len(struct context *context)
|
|||||||
if (i - prev > 1) {
|
if (i - prev > 1) {
|
||||||
/* one or more negative bits are skipped */
|
/* one or more negative bits are skipped */
|
||||||
if (head != prev) {
|
if (head != prev) {
|
||||||
nm = policydb.p_cat_val_to_name[prev];
|
nm = sym_name(&policydb, SYM_CATS, prev);
|
||||||
len += strlen(nm) + 1;
|
len += strlen(nm) + 1;
|
||||||
}
|
}
|
||||||
nm = policydb.p_cat_val_to_name[i];
|
nm = sym_name(&policydb, SYM_CATS, i);
|
||||||
len += strlen(nm) + 1;
|
len += strlen(nm) + 1;
|
||||||
head = i;
|
head = i;
|
||||||
}
|
}
|
||||||
prev = i;
|
prev = i;
|
||||||
}
|
}
|
||||||
if (prev != head) {
|
if (prev != head) {
|
||||||
nm = policydb.p_cat_val_to_name[prev];
|
nm = sym_name(&policydb, SYM_CATS, prev);
|
||||||
len += strlen(nm) + 1;
|
len += strlen(nm) + 1;
|
||||||
}
|
}
|
||||||
if (l == 0) {
|
if (l == 0) {
|
||||||
@ -102,8 +102,8 @@ void mls_sid_to_context(struct context *context,
|
|||||||
scontextp++;
|
scontextp++;
|
||||||
|
|
||||||
for (l = 0; l < 2; l++) {
|
for (l = 0; l < 2; l++) {
|
||||||
strcpy(scontextp,
|
strcpy(scontextp, sym_name(&policydb, SYM_LEVELS,
|
||||||
policydb.p_sens_val_to_name[context->range.level[l].sens - 1]);
|
context->range.level[l].sens - 1));
|
||||||
scontextp += strlen(scontextp);
|
scontextp += strlen(scontextp);
|
||||||
|
|
||||||
/* categories */
|
/* categories */
|
||||||
@ -118,7 +118,7 @@ void mls_sid_to_context(struct context *context,
|
|||||||
*scontextp++ = '.';
|
*scontextp++ = '.';
|
||||||
else
|
else
|
||||||
*scontextp++ = ',';
|
*scontextp++ = ',';
|
||||||
nm = policydb.p_cat_val_to_name[prev];
|
nm = sym_name(&policydb, SYM_CATS, prev);
|
||||||
strcpy(scontextp, nm);
|
strcpy(scontextp, nm);
|
||||||
scontextp += strlen(nm);
|
scontextp += strlen(nm);
|
||||||
}
|
}
|
||||||
@ -126,7 +126,7 @@ void mls_sid_to_context(struct context *context,
|
|||||||
*scontextp++ = ':';
|
*scontextp++ = ':';
|
||||||
else
|
else
|
||||||
*scontextp++ = ',';
|
*scontextp++ = ',';
|
||||||
nm = policydb.p_cat_val_to_name[i];
|
nm = sym_name(&policydb, SYM_CATS, i);
|
||||||
strcpy(scontextp, nm);
|
strcpy(scontextp, nm);
|
||||||
scontextp += strlen(nm);
|
scontextp += strlen(nm);
|
||||||
head = i;
|
head = i;
|
||||||
@ -139,7 +139,7 @@ void mls_sid_to_context(struct context *context,
|
|||||||
*scontextp++ = '.';
|
*scontextp++ = '.';
|
||||||
else
|
else
|
||||||
*scontextp++ = ',';
|
*scontextp++ = ',';
|
||||||
nm = policydb.p_cat_val_to_name[prev];
|
nm = sym_name(&policydb, SYM_CATS, prev);
|
||||||
strcpy(scontextp, nm);
|
strcpy(scontextp, nm);
|
||||||
scontextp += strlen(nm);
|
scontextp += strlen(nm);
|
||||||
}
|
}
|
||||||
@ -166,7 +166,7 @@ int mls_level_isvalid(struct policydb *p, struct mls_level *l)
|
|||||||
if (!l->sens || l->sens > p->p_levels.nprim)
|
if (!l->sens || l->sens > p->p_levels.nprim)
|
||||||
return 0;
|
return 0;
|
||||||
levdatum = hashtab_search(p->p_levels.table,
|
levdatum = hashtab_search(p->p_levels.table,
|
||||||
p->p_sens_val_to_name[l->sens - 1]);
|
sym_name(p, SYM_LEVELS, l->sens - 1));
|
||||||
if (!levdatum)
|
if (!levdatum)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -482,7 +482,8 @@ int mls_convert_context(struct policydb *oldp,
|
|||||||
|
|
||||||
for (l = 0; l < 2; l++) {
|
for (l = 0; l < 2; l++) {
|
||||||
levdatum = hashtab_search(newp->p_levels.table,
|
levdatum = hashtab_search(newp->p_levels.table,
|
||||||
oldp->p_sens_val_to_name[c->range.level[l].sens - 1]);
|
sym_name(oldp, SYM_LEVELS,
|
||||||
|
c->range.level[l].sens - 1));
|
||||||
|
|
||||||
if (!levdatum)
|
if (!levdatum)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -493,7 +494,7 @@ int mls_convert_context(struct policydb *oldp,
|
|||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
catdatum = hashtab_search(newp->p_cats.table,
|
catdatum = hashtab_search(newp->p_cats.table,
|
||||||
oldp->p_cat_val_to_name[i]);
|
sym_name(oldp, SYM_CATS, i));
|
||||||
if (!catdatum)
|
if (!catdatum)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
|
rc = ebitmap_set_bit(&bitmap, catdatum->value - 1, 1);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -203,21 +203,13 @@ struct policydb {
|
|||||||
#define p_cats symtab[SYM_CATS]
|
#define p_cats symtab[SYM_CATS]
|
||||||
|
|
||||||
/* symbol names indexed by (value - 1) */
|
/* symbol names indexed by (value - 1) */
|
||||||
char **sym_val_to_name[SYM_NUM];
|
struct flex_array *sym_val_to_name[SYM_NUM];
|
||||||
#define p_common_val_to_name sym_val_to_name[SYM_COMMONS]
|
|
||||||
#define p_class_val_to_name sym_val_to_name[SYM_CLASSES]
|
|
||||||
#define p_role_val_to_name sym_val_to_name[SYM_ROLES]
|
|
||||||
#define p_type_val_to_name sym_val_to_name[SYM_TYPES]
|
|
||||||
#define p_user_val_to_name sym_val_to_name[SYM_USERS]
|
|
||||||
#define p_bool_val_to_name sym_val_to_name[SYM_BOOLS]
|
|
||||||
#define p_sens_val_to_name sym_val_to_name[SYM_LEVELS]
|
|
||||||
#define p_cat_val_to_name sym_val_to_name[SYM_CATS]
|
|
||||||
|
|
||||||
/* class, role, and user attributes indexed by (value - 1) */
|
/* class, role, and user attributes indexed by (value - 1) */
|
||||||
struct class_datum **class_val_to_struct;
|
struct class_datum **class_val_to_struct;
|
||||||
struct role_datum **role_val_to_struct;
|
struct role_datum **role_val_to_struct;
|
||||||
struct user_datum **user_val_to_struct;
|
struct user_datum **user_val_to_struct;
|
||||||
struct type_datum **type_val_to_struct;
|
struct flex_array *type_val_to_struct_array;
|
||||||
|
|
||||||
/* type enforcement access vectors and transitions */
|
/* type enforcement access vectors and transitions */
|
||||||
struct avtab te_avtab;
|
struct avtab te_avtab;
|
||||||
@ -321,6 +313,13 @@ static inline int put_entry(void *buf, size_t bytes, int num, struct policy_file
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline char *sym_name(struct policydb *p, unsigned int sym_num, unsigned int element_nr)
|
||||||
|
{
|
||||||
|
struct flex_array *fa = p->sym_val_to_name[sym_num];
|
||||||
|
|
||||||
|
return flex_array_get_ptr(fa, element_nr);
|
||||||
|
}
|
||||||
|
|
||||||
extern u16 string_to_security_class(struct policydb *p, const char *name);
|
extern u16 string_to_security_class(struct policydb *p, const char *name);
|
||||||
extern u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name);
|
extern u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name);
|
||||||
|
|
||||||
|
@ -464,7 +464,7 @@ static void security_dump_masked_av(struct context *scontext,
|
|||||||
if (!permissions)
|
if (!permissions)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
tclass_name = policydb.p_class_val_to_name[tclass - 1];
|
tclass_name = sym_name(&policydb, SYM_CLASSES, tclass - 1);
|
||||||
tclass_dat = policydb.class_val_to_struct[tclass - 1];
|
tclass_dat = policydb.class_val_to_struct[tclass - 1];
|
||||||
common_dat = tclass_dat->comdatum;
|
common_dat = tclass_dat->comdatum;
|
||||||
|
|
||||||
@ -530,12 +530,18 @@ static void type_attribute_bounds_av(struct context *scontext,
|
|||||||
struct context lo_scontext;
|
struct context lo_scontext;
|
||||||
struct context lo_tcontext;
|
struct context lo_tcontext;
|
||||||
struct av_decision lo_avd;
|
struct av_decision lo_avd;
|
||||||
struct type_datum *source
|
struct type_datum *source;
|
||||||
= policydb.type_val_to_struct[scontext->type - 1];
|
struct type_datum *target;
|
||||||
struct type_datum *target
|
|
||||||
= policydb.type_val_to_struct[tcontext->type - 1];
|
|
||||||
u32 masked = 0;
|
u32 masked = 0;
|
||||||
|
|
||||||
|
source = flex_array_get_ptr(policydb.type_val_to_struct_array,
|
||||||
|
scontext->type - 1);
|
||||||
|
BUG_ON(!source);
|
||||||
|
|
||||||
|
target = flex_array_get_ptr(policydb.type_val_to_struct_array,
|
||||||
|
tcontext->type - 1);
|
||||||
|
BUG_ON(!target);
|
||||||
|
|
||||||
if (source->bounds) {
|
if (source->bounds) {
|
||||||
memset(&lo_avd, 0, sizeof(lo_avd));
|
memset(&lo_avd, 0, sizeof(lo_avd));
|
||||||
|
|
||||||
@ -701,16 +707,16 @@ static int security_validtrans_handle_fail(struct context *ocontext,
|
|||||||
char *o = NULL, *n = NULL, *t = NULL;
|
char *o = NULL, *n = NULL, *t = NULL;
|
||||||
u32 olen, nlen, tlen;
|
u32 olen, nlen, tlen;
|
||||||
|
|
||||||
if (context_struct_to_string(ocontext, &o, &olen) < 0)
|
if (context_struct_to_string(ocontext, &o, &olen))
|
||||||
goto out;
|
goto out;
|
||||||
if (context_struct_to_string(ncontext, &n, &nlen) < 0)
|
if (context_struct_to_string(ncontext, &n, &nlen))
|
||||||
goto out;
|
goto out;
|
||||||
if (context_struct_to_string(tcontext, &t, &tlen) < 0)
|
if (context_struct_to_string(tcontext, &t, &tlen))
|
||||||
goto out;
|
goto out;
|
||||||
audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
|
audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
|
||||||
"security_validate_transition: denied for"
|
"security_validate_transition: denied for"
|
||||||
" oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
|
" oldcontext=%s newcontext=%s taskcontext=%s tclass=%s",
|
||||||
o, n, t, policydb.p_class_val_to_name[tclass-1]);
|
o, n, t, sym_name(&policydb, SYM_CLASSES, tclass-1));
|
||||||
out:
|
out:
|
||||||
kfree(o);
|
kfree(o);
|
||||||
kfree(n);
|
kfree(n);
|
||||||
@ -801,10 +807,11 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
|
|||||||
struct context *old_context, *new_context;
|
struct context *old_context, *new_context;
|
||||||
struct type_datum *type;
|
struct type_datum *type;
|
||||||
int index;
|
int index;
|
||||||
int rc = -EINVAL;
|
int rc;
|
||||||
|
|
||||||
read_lock(&policy_rwlock);
|
read_lock(&policy_rwlock);
|
||||||
|
|
||||||
|
rc = -EINVAL;
|
||||||
old_context = sidtab_search(&sidtab, old_sid);
|
old_context = sidtab_search(&sidtab, old_sid);
|
||||||
if (!old_context) {
|
if (!old_context) {
|
||||||
printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
|
printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
|
||||||
@ -812,6 +819,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = -EINVAL;
|
||||||
new_context = sidtab_search(&sidtab, new_sid);
|
new_context = sidtab_search(&sidtab, new_sid);
|
||||||
if (!new_context) {
|
if (!new_context) {
|
||||||
printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
|
printk(KERN_ERR "SELinux: %s: unrecognized SID %u\n",
|
||||||
@ -819,28 +827,27 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = 0;
|
||||||
/* type/domain unchanged */
|
/* type/domain unchanged */
|
||||||
if (old_context->type == new_context->type) {
|
if (old_context->type == new_context->type)
|
||||||
rc = 0;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
index = new_context->type;
|
index = new_context->type;
|
||||||
while (true) {
|
while (true) {
|
||||||
type = policydb.type_val_to_struct[index - 1];
|
type = flex_array_get_ptr(policydb.type_val_to_struct_array,
|
||||||
|
index - 1);
|
||||||
BUG_ON(!type);
|
BUG_ON(!type);
|
||||||
|
|
||||||
/* not bounded anymore */
|
/* not bounded anymore */
|
||||||
if (!type->bounds) {
|
rc = -EPERM;
|
||||||
rc = -EPERM;
|
if (!type->bounds)
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/* @newsid is bounded by @oldsid */
|
/* @newsid is bounded by @oldsid */
|
||||||
if (type->bounds == old_context->type) {
|
rc = 0;
|
||||||
rc = 0;
|
if (type->bounds == old_context->type)
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
index = type->bounds;
|
index = type->bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1005,9 +1012,9 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Compute the size of the context. */
|
/* Compute the size of the context. */
|
||||||
*scontext_len += strlen(policydb.p_user_val_to_name[context->user - 1]) + 1;
|
*scontext_len += strlen(sym_name(&policydb, SYM_USERS, context->user - 1)) + 1;
|
||||||
*scontext_len += strlen(policydb.p_role_val_to_name[context->role - 1]) + 1;
|
*scontext_len += strlen(sym_name(&policydb, SYM_ROLES, context->role - 1)) + 1;
|
||||||
*scontext_len += strlen(policydb.p_type_val_to_name[context->type - 1]) + 1;
|
*scontext_len += strlen(sym_name(&policydb, SYM_TYPES, context->type - 1)) + 1;
|
||||||
*scontext_len += mls_compute_context_len(context);
|
*scontext_len += mls_compute_context_len(context);
|
||||||
|
|
||||||
if (!scontext)
|
if (!scontext)
|
||||||
@ -1023,12 +1030,12 @@ static int context_struct_to_string(struct context *context, char **scontext, u3
|
|||||||
* Copy the user name, role name and type name into the context.
|
* Copy the user name, role name and type name into the context.
|
||||||
*/
|
*/
|
||||||
sprintf(scontextp, "%s:%s:%s",
|
sprintf(scontextp, "%s:%s:%s",
|
||||||
policydb.p_user_val_to_name[context->user - 1],
|
sym_name(&policydb, SYM_USERS, context->user - 1),
|
||||||
policydb.p_role_val_to_name[context->role - 1],
|
sym_name(&policydb, SYM_ROLES, context->role - 1),
|
||||||
policydb.p_type_val_to_name[context->type - 1]);
|
sym_name(&policydb, SYM_TYPES, context->type - 1));
|
||||||
scontextp += strlen(policydb.p_user_val_to_name[context->user - 1]) +
|
scontextp += strlen(sym_name(&policydb, SYM_USERS, context->user - 1)) +
|
||||||
1 + strlen(policydb.p_role_val_to_name[context->role - 1]) +
|
1 + strlen(sym_name(&policydb, SYM_ROLES, context->role - 1)) +
|
||||||
1 + strlen(policydb.p_type_val_to_name[context->type - 1]);
|
1 + strlen(sym_name(&policydb, SYM_TYPES, context->type - 1));
|
||||||
|
|
||||||
mls_sid_to_context(context, &scontextp);
|
mls_sid_to_context(context, &scontextp);
|
||||||
|
|
||||||
@ -1187,16 +1194,13 @@ static int string_to_context_struct(struct policydb *pol,
|
|||||||
if (rc)
|
if (rc)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if ((p - scontext) < scontext_len) {
|
rc = -EINVAL;
|
||||||
rc = -EINVAL;
|
if ((p - scontext) < scontext_len)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
/* Check the validity of the new context. */
|
/* Check the validity of the new context. */
|
||||||
if (!policydb_context_isvalid(pol, ctx)) {
|
if (!policydb_context_isvalid(pol, ctx))
|
||||||
rc = -EINVAL;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
rc = 0;
|
rc = 0;
|
||||||
out:
|
out:
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -1235,27 +1239,26 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len,
|
|||||||
|
|
||||||
if (force) {
|
if (force) {
|
||||||
/* Save another copy for storing in uninterpreted form */
|
/* Save another copy for storing in uninterpreted form */
|
||||||
|
rc = -ENOMEM;
|
||||||
str = kstrdup(scontext2, gfp_flags);
|
str = kstrdup(scontext2, gfp_flags);
|
||||||
if (!str) {
|
if (!str)
|
||||||
kfree(scontext2);
|
goto out;
|
||||||
return -ENOMEM;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
read_lock(&policy_rwlock);
|
read_lock(&policy_rwlock);
|
||||||
rc = string_to_context_struct(&policydb, &sidtab,
|
rc = string_to_context_struct(&policydb, &sidtab, scontext2,
|
||||||
scontext2, scontext_len,
|
scontext_len, &context, def_sid);
|
||||||
&context, def_sid);
|
|
||||||
if (rc == -EINVAL && force) {
|
if (rc == -EINVAL && force) {
|
||||||
context.str = str;
|
context.str = str;
|
||||||
context.len = scontext_len;
|
context.len = scontext_len;
|
||||||
str = NULL;
|
str = NULL;
|
||||||
} else if (rc)
|
} else if (rc)
|
||||||
goto out;
|
goto out_unlock;
|
||||||
rc = sidtab_context_to_sid(&sidtab, &context, sid);
|
rc = sidtab_context_to_sid(&sidtab, &context, sid);
|
||||||
context_destroy(&context);
|
context_destroy(&context);
|
||||||
out:
|
out_unlock:
|
||||||
read_unlock(&policy_rwlock);
|
read_unlock(&policy_rwlock);
|
||||||
|
out:
|
||||||
kfree(scontext2);
|
kfree(scontext2);
|
||||||
kfree(str);
|
kfree(str);
|
||||||
return rc;
|
return rc;
|
||||||
@ -1319,18 +1322,18 @@ static int compute_sid_handle_invalid_context(
|
|||||||
char *s = NULL, *t = NULL, *n = NULL;
|
char *s = NULL, *t = NULL, *n = NULL;
|
||||||
u32 slen, tlen, nlen;
|
u32 slen, tlen, nlen;
|
||||||
|
|
||||||
if (context_struct_to_string(scontext, &s, &slen) < 0)
|
if (context_struct_to_string(scontext, &s, &slen))
|
||||||
goto out;
|
goto out;
|
||||||
if (context_struct_to_string(tcontext, &t, &tlen) < 0)
|
if (context_struct_to_string(tcontext, &t, &tlen))
|
||||||
goto out;
|
goto out;
|
||||||
if (context_struct_to_string(newcontext, &n, &nlen) < 0)
|
if (context_struct_to_string(newcontext, &n, &nlen))
|
||||||
goto out;
|
goto out;
|
||||||
audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
|
audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
|
||||||
"security_compute_sid: invalid context %s"
|
"security_compute_sid: invalid context %s"
|
||||||
" for scontext=%s"
|
" for scontext=%s"
|
||||||
" tcontext=%s"
|
" tcontext=%s"
|
||||||
" tclass=%s",
|
" tclass=%s",
|
||||||
n, s, t, policydb.p_class_val_to_name[tclass-1]);
|
n, s, t, sym_name(&policydb, SYM_CLASSES, tclass-1));
|
||||||
out:
|
out:
|
||||||
kfree(s);
|
kfree(s);
|
||||||
kfree(t);
|
kfree(t);
|
||||||
@ -1569,22 +1572,17 @@ static int clone_sid(u32 sid,
|
|||||||
|
|
||||||
static inline int convert_context_handle_invalid_context(struct context *context)
|
static inline int convert_context_handle_invalid_context(struct context *context)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
char *s;
|
||||||
|
u32 len;
|
||||||
|
|
||||||
if (selinux_enforcing) {
|
if (selinux_enforcing)
|
||||||
rc = -EINVAL;
|
return -EINVAL;
|
||||||
} else {
|
|
||||||
char *s;
|
|
||||||
u32 len;
|
|
||||||
|
|
||||||
if (!context_struct_to_string(context, &s, &len)) {
|
if (!context_struct_to_string(context, &s, &len)) {
|
||||||
printk(KERN_WARNING
|
printk(KERN_WARNING "SELinux: Context %s would be invalid if enforcing\n", s);
|
||||||
"SELinux: Context %s would be invalid if enforcing\n",
|
kfree(s);
|
||||||
s);
|
|
||||||
kfree(s);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return rc;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct convert_context_args {
|
struct convert_context_args {
|
||||||
@ -1621,17 +1619,17 @@ static int convert_context(u32 key,
|
|||||||
|
|
||||||
if (c->str) {
|
if (c->str) {
|
||||||
struct context ctx;
|
struct context ctx;
|
||||||
|
|
||||||
|
rc = -ENOMEM;
|
||||||
s = kstrdup(c->str, GFP_KERNEL);
|
s = kstrdup(c->str, GFP_KERNEL);
|
||||||
if (!s) {
|
if (!s)
|
||||||
rc = -ENOMEM;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
rc = string_to_context_struct(args->newp, NULL, s,
|
rc = string_to_context_struct(args->newp, NULL, s,
|
||||||
c->len, &ctx, SECSID_NULL);
|
c->len, &ctx, SECSID_NULL);
|
||||||
kfree(s);
|
kfree(s);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
printk(KERN_INFO
|
printk(KERN_INFO "SELinux: Context %s became valid (mapped).\n",
|
||||||
"SELinux: Context %s became valid (mapped).\n",
|
|
||||||
c->str);
|
c->str);
|
||||||
/* Replace string with mapped representation. */
|
/* Replace string with mapped representation. */
|
||||||
kfree(c->str);
|
kfree(c->str);
|
||||||
@ -1643,8 +1641,7 @@ static int convert_context(u32 key,
|
|||||||
goto out;
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
/* Other error condition, e.g. ENOMEM. */
|
/* Other error condition, e.g. ENOMEM. */
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR "SELinux: Unable to map context %s, rc = %d.\n",
|
||||||
"SELinux: Unable to map context %s, rc = %d.\n",
|
|
||||||
c->str, -rc);
|
c->str, -rc);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -1654,25 +1651,26 @@ static int convert_context(u32 key,
|
|||||||
if (rc)
|
if (rc)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
rc = -EINVAL;
|
|
||||||
|
|
||||||
/* Convert the user. */
|
/* Convert the user. */
|
||||||
|
rc = -EINVAL;
|
||||||
usrdatum = hashtab_search(args->newp->p_users.table,
|
usrdatum = hashtab_search(args->newp->p_users.table,
|
||||||
args->oldp->p_user_val_to_name[c->user - 1]);
|
sym_name(args->oldp, SYM_USERS, c->user - 1));
|
||||||
if (!usrdatum)
|
if (!usrdatum)
|
||||||
goto bad;
|
goto bad;
|
||||||
c->user = usrdatum->value;
|
c->user = usrdatum->value;
|
||||||
|
|
||||||
/* Convert the role. */
|
/* Convert the role. */
|
||||||
|
rc = -EINVAL;
|
||||||
role = hashtab_search(args->newp->p_roles.table,
|
role = hashtab_search(args->newp->p_roles.table,
|
||||||
args->oldp->p_role_val_to_name[c->role - 1]);
|
sym_name(args->oldp, SYM_ROLES, c->role - 1));
|
||||||
if (!role)
|
if (!role)
|
||||||
goto bad;
|
goto bad;
|
||||||
c->role = role->value;
|
c->role = role->value;
|
||||||
|
|
||||||
/* Convert the type. */
|
/* Convert the type. */
|
||||||
|
rc = -EINVAL;
|
||||||
typdatum = hashtab_search(args->newp->p_types.table,
|
typdatum = hashtab_search(args->newp->p_types.table,
|
||||||
args->oldp->p_type_val_to_name[c->type - 1]);
|
sym_name(args->oldp, SYM_TYPES, c->type - 1));
|
||||||
if (!typdatum)
|
if (!typdatum)
|
||||||
goto bad;
|
goto bad;
|
||||||
c->type = typdatum->value;
|
c->type = typdatum->value;
|
||||||
@ -1700,6 +1698,7 @@ static int convert_context(u32 key,
|
|||||||
oc = args->newp->ocontexts[OCON_ISID];
|
oc = args->newp->ocontexts[OCON_ISID];
|
||||||
while (oc && oc->sid[0] != SECINITSID_UNLABELED)
|
while (oc && oc->sid[0] != SECINITSID_UNLABELED)
|
||||||
oc = oc->next;
|
oc = oc->next;
|
||||||
|
rc = -EINVAL;
|
||||||
if (!oc) {
|
if (!oc) {
|
||||||
printk(KERN_ERR "SELinux: unable to look up"
|
printk(KERN_ERR "SELinux: unable to look up"
|
||||||
" the initial SIDs list\n");
|
" the initial SIDs list\n");
|
||||||
@ -1719,19 +1718,20 @@ static int convert_context(u32 key,
|
|||||||
}
|
}
|
||||||
|
|
||||||
context_destroy(&oldc);
|
context_destroy(&oldc);
|
||||||
|
|
||||||
rc = 0;
|
rc = 0;
|
||||||
out:
|
out:
|
||||||
return rc;
|
return rc;
|
||||||
bad:
|
bad:
|
||||||
/* Map old representation to string and save it. */
|
/* Map old representation to string and save it. */
|
||||||
if (context_struct_to_string(&oldc, &s, &len))
|
rc = context_struct_to_string(&oldc, &s, &len);
|
||||||
return -ENOMEM;
|
if (rc)
|
||||||
|
return rc;
|
||||||
context_destroy(&oldc);
|
context_destroy(&oldc);
|
||||||
context_destroy(c);
|
context_destroy(c);
|
||||||
c->str = s;
|
c->str = s;
|
||||||
c->len = len;
|
c->len = len;
|
||||||
printk(KERN_INFO
|
printk(KERN_INFO "SELinux: Context %s became invalid (unmapped).\n",
|
||||||
"SELinux: Context %s became invalid (unmapped).\n",
|
|
||||||
c->str);
|
c->str);
|
||||||
rc = 0;
|
rc = 0;
|
||||||
goto out;
|
goto out;
|
||||||
@ -2012,7 +2012,7 @@ int security_node_sid(u16 domain,
|
|||||||
u32 addrlen,
|
u32 addrlen,
|
||||||
u32 *out_sid)
|
u32 *out_sid)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc;
|
||||||
struct ocontext *c;
|
struct ocontext *c;
|
||||||
|
|
||||||
read_lock(&policy_rwlock);
|
read_lock(&policy_rwlock);
|
||||||
@ -2021,10 +2021,9 @@ int security_node_sid(u16 domain,
|
|||||||
case AF_INET: {
|
case AF_INET: {
|
||||||
u32 addr;
|
u32 addr;
|
||||||
|
|
||||||
if (addrlen != sizeof(u32)) {
|
rc = -EINVAL;
|
||||||
rc = -EINVAL;
|
if (addrlen != sizeof(u32))
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
addr = *((u32 *)addrp);
|
addr = *((u32 *)addrp);
|
||||||
|
|
||||||
@ -2038,10 +2037,9 @@ int security_node_sid(u16 domain,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
if (addrlen != sizeof(u64) * 2) {
|
rc = -EINVAL;
|
||||||
rc = -EINVAL;
|
if (addrlen != sizeof(u64) * 2)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
c = policydb.ocontexts[OCON_NODE6];
|
c = policydb.ocontexts[OCON_NODE6];
|
||||||
while (c) {
|
while (c) {
|
||||||
if (match_ipv6_addrmask(addrp, c->u.node6.addr,
|
if (match_ipv6_addrmask(addrp, c->u.node6.addr,
|
||||||
@ -2052,6 +2050,7 @@ int security_node_sid(u16 domain,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
rc = 0;
|
||||||
*out_sid = SECINITSID_NODE;
|
*out_sid = SECINITSID_NODE;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -2069,6 +2068,7 @@ int security_node_sid(u16 domain,
|
|||||||
*out_sid = SECINITSID_NODE;
|
*out_sid = SECINITSID_NODE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = 0;
|
||||||
out:
|
out:
|
||||||
read_unlock(&policy_rwlock);
|
read_unlock(&policy_rwlock);
|
||||||
return rc;
|
return rc;
|
||||||
@ -2113,24 +2113,22 @@ int security_get_user_sids(u32 fromsid,
|
|||||||
|
|
||||||
context_init(&usercon);
|
context_init(&usercon);
|
||||||
|
|
||||||
|
rc = -EINVAL;
|
||||||
fromcon = sidtab_search(&sidtab, fromsid);
|
fromcon = sidtab_search(&sidtab, fromsid);
|
||||||
if (!fromcon) {
|
if (!fromcon)
|
||||||
rc = -EINVAL;
|
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
|
||||||
|
|
||||||
|
rc = -EINVAL;
|
||||||
user = hashtab_search(policydb.p_users.table, username);
|
user = hashtab_search(policydb.p_users.table, username);
|
||||||
if (!user) {
|
if (!user)
|
||||||
rc = -EINVAL;
|
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
|
||||||
usercon.user = user->value;
|
usercon.user = user->value;
|
||||||
|
|
||||||
|
rc = -ENOMEM;
|
||||||
mysids = kcalloc(maxnel, sizeof(*mysids), GFP_ATOMIC);
|
mysids = kcalloc(maxnel, sizeof(*mysids), GFP_ATOMIC);
|
||||||
if (!mysids) {
|
if (!mysids)
|
||||||
rc = -ENOMEM;
|
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
|
||||||
|
|
||||||
ebitmap_for_each_positive_bit(&user->roles, rnode, i) {
|
ebitmap_for_each_positive_bit(&user->roles, rnode, i) {
|
||||||
role = policydb.role_val_to_struct[i];
|
role = policydb.role_val_to_struct[i];
|
||||||
@ -2147,12 +2145,11 @@ int security_get_user_sids(u32 fromsid,
|
|||||||
if (mynel < maxnel) {
|
if (mynel < maxnel) {
|
||||||
mysids[mynel++] = sid;
|
mysids[mynel++] = sid;
|
||||||
} else {
|
} else {
|
||||||
|
rc = -ENOMEM;
|
||||||
maxnel += SIDS_NEL;
|
maxnel += SIDS_NEL;
|
||||||
mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC);
|
mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC);
|
||||||
if (!mysids2) {
|
if (!mysids2)
|
||||||
rc = -ENOMEM;
|
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
|
||||||
memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
|
memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
|
||||||
kfree(mysids);
|
kfree(mysids);
|
||||||
mysids = mysids2;
|
mysids = mysids2;
|
||||||
@ -2160,7 +2157,7 @@ int security_get_user_sids(u32 fromsid,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
rc = 0;
|
||||||
out_unlock:
|
out_unlock:
|
||||||
read_unlock(&policy_rwlock);
|
read_unlock(&policy_rwlock);
|
||||||
if (rc || !mynel) {
|
if (rc || !mynel) {
|
||||||
@ -2168,9 +2165,9 @@ out_unlock:
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = -ENOMEM;
|
||||||
mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL);
|
mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL);
|
||||||
if (!mysids2) {
|
if (!mysids2) {
|
||||||
rc = -ENOMEM;
|
|
||||||
kfree(mysids);
|
kfree(mysids);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -2211,7 +2208,7 @@ int security_genfs_sid(const char *fstype,
|
|||||||
u16 sclass;
|
u16 sclass;
|
||||||
struct genfs *genfs;
|
struct genfs *genfs;
|
||||||
struct ocontext *c;
|
struct ocontext *c;
|
||||||
int rc = 0, cmp = 0;
|
int rc, cmp = 0;
|
||||||
|
|
||||||
while (path[0] == '/' && path[1] == '/')
|
while (path[0] == '/' && path[1] == '/')
|
||||||
path++;
|
path++;
|
||||||
@ -2219,6 +2216,7 @@ int security_genfs_sid(const char *fstype,
|
|||||||
read_lock(&policy_rwlock);
|
read_lock(&policy_rwlock);
|
||||||
|
|
||||||
sclass = unmap_class(orig_sclass);
|
sclass = unmap_class(orig_sclass);
|
||||||
|
*sid = SECINITSID_UNLABELED;
|
||||||
|
|
||||||
for (genfs = policydb.genfs; genfs; genfs = genfs->next) {
|
for (genfs = policydb.genfs; genfs; genfs = genfs->next) {
|
||||||
cmp = strcmp(fstype, genfs->fstype);
|
cmp = strcmp(fstype, genfs->fstype);
|
||||||
@ -2226,11 +2224,9 @@ int security_genfs_sid(const char *fstype,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!genfs || cmp) {
|
rc = -ENOENT;
|
||||||
*sid = SECINITSID_UNLABELED;
|
if (!genfs || cmp)
|
||||||
rc = -ENOENT;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
for (c = genfs->head; c; c = c->next) {
|
for (c = genfs->head; c; c = c->next) {
|
||||||
len = strlen(c->u.name);
|
len = strlen(c->u.name);
|
||||||
@ -2239,21 +2235,18 @@ int security_genfs_sid(const char *fstype,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!c) {
|
rc = -ENOENT;
|
||||||
*sid = SECINITSID_UNLABELED;
|
if (!c)
|
||||||
rc = -ENOENT;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
if (!c->sid[0]) {
|
if (!c->sid[0]) {
|
||||||
rc = sidtab_context_to_sid(&sidtab,
|
rc = sidtab_context_to_sid(&sidtab, &c->context[0], &c->sid[0]);
|
||||||
&c->context[0],
|
|
||||||
&c->sid[0]);
|
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
*sid = c->sid[0];
|
*sid = c->sid[0];
|
||||||
|
rc = 0;
|
||||||
out:
|
out:
|
||||||
read_unlock(&policy_rwlock);
|
read_unlock(&policy_rwlock);
|
||||||
return rc;
|
return rc;
|
||||||
@ -2285,8 +2278,7 @@ int security_fs_use(
|
|||||||
if (c) {
|
if (c) {
|
||||||
*behavior = c->v.behavior;
|
*behavior = c->v.behavior;
|
||||||
if (!c->sid[0]) {
|
if (!c->sid[0]) {
|
||||||
rc = sidtab_context_to_sid(&sidtab,
|
rc = sidtab_context_to_sid(&sidtab, &c->context[0],
|
||||||
&c->context[0],
|
|
||||||
&c->sid[0]);
|
&c->sid[0]);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out;
|
goto out;
|
||||||
@ -2309,34 +2301,39 @@ out:
|
|||||||
|
|
||||||
int security_get_bools(int *len, char ***names, int **values)
|
int security_get_bools(int *len, char ***names, int **values)
|
||||||
{
|
{
|
||||||
int i, rc = -ENOMEM;
|
int i, rc;
|
||||||
|
|
||||||
read_lock(&policy_rwlock);
|
read_lock(&policy_rwlock);
|
||||||
*names = NULL;
|
*names = NULL;
|
||||||
*values = NULL;
|
*values = NULL;
|
||||||
|
|
||||||
|
rc = 0;
|
||||||
*len = policydb.p_bools.nprim;
|
*len = policydb.p_bools.nprim;
|
||||||
if (!*len) {
|
if (!*len)
|
||||||
rc = 0;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
*names = kcalloc(*len, sizeof(char *), GFP_ATOMIC);
|
rc = -ENOMEM;
|
||||||
|
*names = kcalloc(*len, sizeof(char *), GFP_ATOMIC);
|
||||||
if (!*names)
|
if (!*names)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
*values = kcalloc(*len, sizeof(int), GFP_ATOMIC);
|
rc = -ENOMEM;
|
||||||
|
*values = kcalloc(*len, sizeof(int), GFP_ATOMIC);
|
||||||
if (!*values)
|
if (!*values)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
for (i = 0; i < *len; i++) {
|
for (i = 0; i < *len; i++) {
|
||||||
size_t name_len;
|
size_t name_len;
|
||||||
|
|
||||||
(*values)[i] = policydb.bool_val_to_struct[i]->state;
|
(*values)[i] = policydb.bool_val_to_struct[i]->state;
|
||||||
name_len = strlen(policydb.p_bool_val_to_name[i]) + 1;
|
name_len = strlen(sym_name(&policydb, SYM_BOOLS, i)) + 1;
|
||||||
(*names)[i] = kmalloc(sizeof(char) * name_len, GFP_ATOMIC);
|
|
||||||
|
rc = -ENOMEM;
|
||||||
|
(*names)[i] = kmalloc(sizeof(char) * name_len, GFP_ATOMIC);
|
||||||
if (!(*names)[i])
|
if (!(*names)[i])
|
||||||
goto err;
|
goto err;
|
||||||
strncpy((*names)[i], policydb.p_bool_val_to_name[i], name_len);
|
|
||||||
|
strncpy((*names)[i], sym_name(&policydb, SYM_BOOLS, i), name_len);
|
||||||
(*names)[i][name_len - 1] = 0;
|
(*names)[i][name_len - 1] = 0;
|
||||||
}
|
}
|
||||||
rc = 0;
|
rc = 0;
|
||||||
@ -2355,24 +2352,23 @@ err:
|
|||||||
|
|
||||||
int security_set_bools(int len, int *values)
|
int security_set_bools(int len, int *values)
|
||||||
{
|
{
|
||||||
int i, rc = 0;
|
int i, rc;
|
||||||
int lenp, seqno = 0;
|
int lenp, seqno = 0;
|
||||||
struct cond_node *cur;
|
struct cond_node *cur;
|
||||||
|
|
||||||
write_lock_irq(&policy_rwlock);
|
write_lock_irq(&policy_rwlock);
|
||||||
|
|
||||||
|
rc = -EFAULT;
|
||||||
lenp = policydb.p_bools.nprim;
|
lenp = policydb.p_bools.nprim;
|
||||||
if (len != lenp) {
|
if (len != lenp)
|
||||||
rc = -EFAULT;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
if (!!values[i] != policydb.bool_val_to_struct[i]->state) {
|
if (!!values[i] != policydb.bool_val_to_struct[i]->state) {
|
||||||
audit_log(current->audit_context, GFP_ATOMIC,
|
audit_log(current->audit_context, GFP_ATOMIC,
|
||||||
AUDIT_MAC_CONFIG_CHANGE,
|
AUDIT_MAC_CONFIG_CHANGE,
|
||||||
"bool=%s val=%d old_val=%d auid=%u ses=%u",
|
"bool=%s val=%d old_val=%d auid=%u ses=%u",
|
||||||
policydb.p_bool_val_to_name[i],
|
sym_name(&policydb, SYM_BOOLS, i),
|
||||||
!!values[i],
|
!!values[i],
|
||||||
policydb.bool_val_to_struct[i]->state,
|
policydb.bool_val_to_struct[i]->state,
|
||||||
audit_get_loginuid(current),
|
audit_get_loginuid(current),
|
||||||
@ -2391,7 +2387,7 @@ int security_set_bools(int len, int *values)
|
|||||||
}
|
}
|
||||||
|
|
||||||
seqno = ++latest_granting;
|
seqno = ++latest_granting;
|
||||||
|
rc = 0;
|
||||||
out:
|
out:
|
||||||
write_unlock_irq(&policy_rwlock);
|
write_unlock_irq(&policy_rwlock);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
@ -2405,16 +2401,15 @@ out:
|
|||||||
|
|
||||||
int security_get_bool_value(int bool)
|
int security_get_bool_value(int bool)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
read_lock(&policy_rwlock);
|
read_lock(&policy_rwlock);
|
||||||
|
|
||||||
|
rc = -EFAULT;
|
||||||
len = policydb.p_bools.nprim;
|
len = policydb.p_bools.nprim;
|
||||||
if (bool >= len) {
|
if (bool >= len)
|
||||||
rc = -EFAULT;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
rc = policydb.bool_val_to_struct[bool]->state;
|
rc = policydb.bool_val_to_struct[bool]->state;
|
||||||
out:
|
out:
|
||||||
@ -2464,8 +2459,9 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
|
|||||||
struct context newcon;
|
struct context newcon;
|
||||||
char *s;
|
char *s;
|
||||||
u32 len;
|
u32 len;
|
||||||
int rc = 0;
|
int rc;
|
||||||
|
|
||||||
|
rc = 0;
|
||||||
if (!ss_initialized || !policydb.mls_enabled) {
|
if (!ss_initialized || !policydb.mls_enabled) {
|
||||||
*new_sid = sid;
|
*new_sid = sid;
|
||||||
goto out;
|
goto out;
|
||||||
@ -2474,19 +2470,20 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
|
|||||||
context_init(&newcon);
|
context_init(&newcon);
|
||||||
|
|
||||||
read_lock(&policy_rwlock);
|
read_lock(&policy_rwlock);
|
||||||
|
|
||||||
|
rc = -EINVAL;
|
||||||
context1 = sidtab_search(&sidtab, sid);
|
context1 = sidtab_search(&sidtab, sid);
|
||||||
if (!context1) {
|
if (!context1) {
|
||||||
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
|
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
|
||||||
__func__, sid);
|
__func__, sid);
|
||||||
rc = -EINVAL;
|
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = -EINVAL;
|
||||||
context2 = sidtab_search(&sidtab, mls_sid);
|
context2 = sidtab_search(&sidtab, mls_sid);
|
||||||
if (!context2) {
|
if (!context2) {
|
||||||
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
|
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
|
||||||
__func__, mls_sid);
|
__func__, mls_sid);
|
||||||
rc = -EINVAL;
|
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2500,20 +2497,17 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid)
|
|||||||
/* Check the validity of the new context. */
|
/* Check the validity of the new context. */
|
||||||
if (!policydb_context_isvalid(&policydb, &newcon)) {
|
if (!policydb_context_isvalid(&policydb, &newcon)) {
|
||||||
rc = convert_context_handle_invalid_context(&newcon);
|
rc = convert_context_handle_invalid_context(&newcon);
|
||||||
if (rc)
|
if (rc) {
|
||||||
goto bad;
|
if (!context_struct_to_string(&newcon, &s, &len)) {
|
||||||
|
audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
|
||||||
|
"security_sid_mls_copy: invalid context %s", s);
|
||||||
|
kfree(s);
|
||||||
|
}
|
||||||
|
goto out_unlock;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sidtab_context_to_sid(&sidtab, &newcon, new_sid);
|
rc = sidtab_context_to_sid(&sidtab, &newcon, new_sid);
|
||||||
goto out_unlock;
|
|
||||||
|
|
||||||
bad:
|
|
||||||
if (!context_struct_to_string(&newcon, &s, &len)) {
|
|
||||||
audit_log(current->audit_context, GFP_ATOMIC, AUDIT_SELINUX_ERR,
|
|
||||||
"security_sid_mls_copy: invalid context %s", s);
|
|
||||||
kfree(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
read_unlock(&policy_rwlock);
|
read_unlock(&policy_rwlock);
|
||||||
context_destroy(&newcon);
|
context_destroy(&newcon);
|
||||||
@ -2549,6 +2543,8 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
|
|||||||
struct context *nlbl_ctx;
|
struct context *nlbl_ctx;
|
||||||
struct context *xfrm_ctx;
|
struct context *xfrm_ctx;
|
||||||
|
|
||||||
|
*peer_sid = SECSID_NULL;
|
||||||
|
|
||||||
/* handle the common (which also happens to be the set of easy) cases
|
/* handle the common (which also happens to be the set of easy) cases
|
||||||
* right away, these two if statements catch everything involving a
|
* right away, these two if statements catch everything involving a
|
||||||
* single or absent peer SID/label */
|
* single or absent peer SID/label */
|
||||||
@ -2567,40 +2563,37 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
|
|||||||
/* we don't need to check ss_initialized here since the only way both
|
/* we don't need to check ss_initialized here since the only way both
|
||||||
* nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the
|
* nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the
|
||||||
* security server was initialized and ss_initialized was true */
|
* security server was initialized and ss_initialized was true */
|
||||||
if (!policydb.mls_enabled) {
|
if (!policydb.mls_enabled)
|
||||||
*peer_sid = SECSID_NULL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
read_lock(&policy_rwlock);
|
read_lock(&policy_rwlock);
|
||||||
|
|
||||||
|
rc = -EINVAL;
|
||||||
nlbl_ctx = sidtab_search(&sidtab, nlbl_sid);
|
nlbl_ctx = sidtab_search(&sidtab, nlbl_sid);
|
||||||
if (!nlbl_ctx) {
|
if (!nlbl_ctx) {
|
||||||
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
|
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
|
||||||
__func__, nlbl_sid);
|
__func__, nlbl_sid);
|
||||||
rc = -EINVAL;
|
goto out;
|
||||||
goto out_slowpath;
|
|
||||||
}
|
}
|
||||||
|
rc = -EINVAL;
|
||||||
xfrm_ctx = sidtab_search(&sidtab, xfrm_sid);
|
xfrm_ctx = sidtab_search(&sidtab, xfrm_sid);
|
||||||
if (!xfrm_ctx) {
|
if (!xfrm_ctx) {
|
||||||
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
|
printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n",
|
||||||
__func__, xfrm_sid);
|
__func__, xfrm_sid);
|
||||||
rc = -EINVAL;
|
goto out;
|
||||||
goto out_slowpath;
|
|
||||||
}
|
}
|
||||||
rc = (mls_context_cmp(nlbl_ctx, xfrm_ctx) ? 0 : -EACCES);
|
rc = (mls_context_cmp(nlbl_ctx, xfrm_ctx) ? 0 : -EACCES);
|
||||||
|
if (rc)
|
||||||
|
goto out;
|
||||||
|
|
||||||
out_slowpath:
|
/* at present NetLabel SIDs/labels really only carry MLS
|
||||||
|
* information so if the MLS portion of the NetLabel SID
|
||||||
|
* matches the MLS portion of the labeled XFRM SID/label
|
||||||
|
* then pass along the XFRM SID as it is the most
|
||||||
|
* expressive */
|
||||||
|
*peer_sid = xfrm_sid;
|
||||||
|
out:
|
||||||
read_unlock(&policy_rwlock);
|
read_unlock(&policy_rwlock);
|
||||||
if (rc == 0)
|
|
||||||
/* at present NetLabel SIDs/labels really only carry MLS
|
|
||||||
* information so if the MLS portion of the NetLabel SID
|
|
||||||
* matches the MLS portion of the labeled XFRM SID/label
|
|
||||||
* then pass along the XFRM SID as it is the most
|
|
||||||
* expressive */
|
|
||||||
*peer_sid = xfrm_sid;
|
|
||||||
else
|
|
||||||
*peer_sid = SECSID_NULL;
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2619,10 +2612,11 @@ static int get_classes_callback(void *k, void *d, void *args)
|
|||||||
|
|
||||||
int security_get_classes(char ***classes, int *nclasses)
|
int security_get_classes(char ***classes, int *nclasses)
|
||||||
{
|
{
|
||||||
int rc = -ENOMEM;
|
int rc;
|
||||||
|
|
||||||
read_lock(&policy_rwlock);
|
read_lock(&policy_rwlock);
|
||||||
|
|
||||||
|
rc = -ENOMEM;
|
||||||
*nclasses = policydb.p_classes.nprim;
|
*nclasses = policydb.p_classes.nprim;
|
||||||
*classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC);
|
*classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC);
|
||||||
if (!*classes)
|
if (!*classes)
|
||||||
@ -2630,7 +2624,7 @@ int security_get_classes(char ***classes, int *nclasses)
|
|||||||
|
|
||||||
rc = hashtab_map(policydb.p_classes.table, get_classes_callback,
|
rc = hashtab_map(policydb.p_classes.table, get_classes_callback,
|
||||||
*classes);
|
*classes);
|
||||||
if (rc < 0) {
|
if (rc) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < *nclasses; i++)
|
for (i = 0; i < *nclasses; i++)
|
||||||
kfree((*classes)[i]);
|
kfree((*classes)[i]);
|
||||||
@ -2657,19 +2651,20 @@ static int get_permissions_callback(void *k, void *d, void *args)
|
|||||||
|
|
||||||
int security_get_permissions(char *class, char ***perms, int *nperms)
|
int security_get_permissions(char *class, char ***perms, int *nperms)
|
||||||
{
|
{
|
||||||
int rc = -ENOMEM, i;
|
int rc, i;
|
||||||
struct class_datum *match;
|
struct class_datum *match;
|
||||||
|
|
||||||
read_lock(&policy_rwlock);
|
read_lock(&policy_rwlock);
|
||||||
|
|
||||||
|
rc = -EINVAL;
|
||||||
match = hashtab_search(policydb.p_classes.table, class);
|
match = hashtab_search(policydb.p_classes.table, class);
|
||||||
if (!match) {
|
if (!match) {
|
||||||
printk(KERN_ERR "SELinux: %s: unrecognized class %s\n",
|
printk(KERN_ERR "SELinux: %s: unrecognized class %s\n",
|
||||||
__func__, class);
|
__func__, class);
|
||||||
rc = -EINVAL;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = -ENOMEM;
|
||||||
*nperms = match->permissions.nprim;
|
*nperms = match->permissions.nprim;
|
||||||
*perms = kcalloc(*nperms, sizeof(**perms), GFP_ATOMIC);
|
*perms = kcalloc(*nperms, sizeof(**perms), GFP_ATOMIC);
|
||||||
if (!*perms)
|
if (!*perms)
|
||||||
@ -2678,13 +2673,13 @@ int security_get_permissions(char *class, char ***perms, int *nperms)
|
|||||||
if (match->comdatum) {
|
if (match->comdatum) {
|
||||||
rc = hashtab_map(match->comdatum->permissions.table,
|
rc = hashtab_map(match->comdatum->permissions.table,
|
||||||
get_permissions_callback, *perms);
|
get_permissions_callback, *perms);
|
||||||
if (rc < 0)
|
if (rc)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = hashtab_map(match->permissions.table, get_permissions_callback,
|
rc = hashtab_map(match->permissions.table, get_permissions_callback,
|
||||||
*perms);
|
*perms);
|
||||||
if (rc < 0)
|
if (rc)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
@ -2796,36 +2791,39 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
|
|||||||
switch (field) {
|
switch (field) {
|
||||||
case AUDIT_SUBJ_USER:
|
case AUDIT_SUBJ_USER:
|
||||||
case AUDIT_OBJ_USER:
|
case AUDIT_OBJ_USER:
|
||||||
|
rc = -EINVAL;
|
||||||
userdatum = hashtab_search(policydb.p_users.table, rulestr);
|
userdatum = hashtab_search(policydb.p_users.table, rulestr);
|
||||||
if (!userdatum)
|
if (!userdatum)
|
||||||
rc = -EINVAL;
|
goto out;
|
||||||
else
|
tmprule->au_ctxt.user = userdatum->value;
|
||||||
tmprule->au_ctxt.user = userdatum->value;
|
|
||||||
break;
|
break;
|
||||||
case AUDIT_SUBJ_ROLE:
|
case AUDIT_SUBJ_ROLE:
|
||||||
case AUDIT_OBJ_ROLE:
|
case AUDIT_OBJ_ROLE:
|
||||||
|
rc = -EINVAL;
|
||||||
roledatum = hashtab_search(policydb.p_roles.table, rulestr);
|
roledatum = hashtab_search(policydb.p_roles.table, rulestr);
|
||||||
if (!roledatum)
|
if (!roledatum)
|
||||||
rc = -EINVAL;
|
goto out;
|
||||||
else
|
tmprule->au_ctxt.role = roledatum->value;
|
||||||
tmprule->au_ctxt.role = roledatum->value;
|
|
||||||
break;
|
break;
|
||||||
case AUDIT_SUBJ_TYPE:
|
case AUDIT_SUBJ_TYPE:
|
||||||
case AUDIT_OBJ_TYPE:
|
case AUDIT_OBJ_TYPE:
|
||||||
|
rc = -EINVAL;
|
||||||
typedatum = hashtab_search(policydb.p_types.table, rulestr);
|
typedatum = hashtab_search(policydb.p_types.table, rulestr);
|
||||||
if (!typedatum)
|
if (!typedatum)
|
||||||
rc = -EINVAL;
|
goto out;
|
||||||
else
|
tmprule->au_ctxt.type = typedatum->value;
|
||||||
tmprule->au_ctxt.type = typedatum->value;
|
|
||||||
break;
|
break;
|
||||||
case AUDIT_SUBJ_SEN:
|
case AUDIT_SUBJ_SEN:
|
||||||
case AUDIT_SUBJ_CLR:
|
case AUDIT_SUBJ_CLR:
|
||||||
case AUDIT_OBJ_LEV_LOW:
|
case AUDIT_OBJ_LEV_LOW:
|
||||||
case AUDIT_OBJ_LEV_HIGH:
|
case AUDIT_OBJ_LEV_HIGH:
|
||||||
rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC);
|
rc = mls_from_string(rulestr, &tmprule->au_ctxt, GFP_ATOMIC);
|
||||||
|
if (rc)
|
||||||
|
goto out;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
rc = 0;
|
||||||
|
out:
|
||||||
read_unlock(&policy_rwlock);
|
read_unlock(&policy_rwlock);
|
||||||
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
@ -3050,7 +3048,7 @@ static void security_netlbl_cache_add(struct netlbl_lsm_secattr *secattr,
|
|||||||
int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
|
int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
|
||||||
u32 *sid)
|
u32 *sid)
|
||||||
{
|
{
|
||||||
int rc = -EIDRM;
|
int rc;
|
||||||
struct context *ctx;
|
struct context *ctx;
|
||||||
struct context ctx_new;
|
struct context ctx_new;
|
||||||
|
|
||||||
@ -3061,16 +3059,15 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
|
|||||||
|
|
||||||
read_lock(&policy_rwlock);
|
read_lock(&policy_rwlock);
|
||||||
|
|
||||||
if (secattr->flags & NETLBL_SECATTR_CACHE) {
|
if (secattr->flags & NETLBL_SECATTR_CACHE)
|
||||||
*sid = *(u32 *)secattr->cache->data;
|
*sid = *(u32 *)secattr->cache->data;
|
||||||
rc = 0;
|
else if (secattr->flags & NETLBL_SECATTR_SECID)
|
||||||
} else if (secattr->flags & NETLBL_SECATTR_SECID) {
|
|
||||||
*sid = secattr->attr.secid;
|
*sid = secattr->attr.secid;
|
||||||
rc = 0;
|
else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
|
||||||
} else if (secattr->flags & NETLBL_SECATTR_MLS_LVL) {
|
rc = -EIDRM;
|
||||||
ctx = sidtab_search(&sidtab, SECINITSID_NETMSG);
|
ctx = sidtab_search(&sidtab, SECINITSID_NETMSG);
|
||||||
if (ctx == NULL)
|
if (ctx == NULL)
|
||||||
goto netlbl_secattr_to_sid_return;
|
goto out;
|
||||||
|
|
||||||
context_init(&ctx_new);
|
context_init(&ctx_new);
|
||||||
ctx_new.user = ctx->user;
|
ctx_new.user = ctx->user;
|
||||||
@ -3078,34 +3075,35 @@ int security_netlbl_secattr_to_sid(struct netlbl_lsm_secattr *secattr,
|
|||||||
ctx_new.type = ctx->type;
|
ctx_new.type = ctx->type;
|
||||||
mls_import_netlbl_lvl(&ctx_new, secattr);
|
mls_import_netlbl_lvl(&ctx_new, secattr);
|
||||||
if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
|
if (secattr->flags & NETLBL_SECATTR_MLS_CAT) {
|
||||||
if (ebitmap_netlbl_import(&ctx_new.range.level[0].cat,
|
rc = ebitmap_netlbl_import(&ctx_new.range.level[0].cat,
|
||||||
secattr->attr.mls.cat) != 0)
|
secattr->attr.mls.cat);
|
||||||
goto netlbl_secattr_to_sid_return;
|
if (rc)
|
||||||
|
goto out;
|
||||||
memcpy(&ctx_new.range.level[1].cat,
|
memcpy(&ctx_new.range.level[1].cat,
|
||||||
&ctx_new.range.level[0].cat,
|
&ctx_new.range.level[0].cat,
|
||||||
sizeof(ctx_new.range.level[0].cat));
|
sizeof(ctx_new.range.level[0].cat));
|
||||||
}
|
}
|
||||||
if (mls_context_isvalid(&policydb, &ctx_new) != 1)
|
rc = -EIDRM;
|
||||||
goto netlbl_secattr_to_sid_return_cleanup;
|
if (!mls_context_isvalid(&policydb, &ctx_new))
|
||||||
|
goto out_free;
|
||||||
|
|
||||||
rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid);
|
rc = sidtab_context_to_sid(&sidtab, &ctx_new, sid);
|
||||||
if (rc != 0)
|
if (rc)
|
||||||
goto netlbl_secattr_to_sid_return_cleanup;
|
goto out_free;
|
||||||
|
|
||||||
security_netlbl_cache_add(secattr, *sid);
|
security_netlbl_cache_add(secattr, *sid);
|
||||||
|
|
||||||
ebitmap_destroy(&ctx_new.range.level[0].cat);
|
ebitmap_destroy(&ctx_new.range.level[0].cat);
|
||||||
} else {
|
} else
|
||||||
*sid = SECSID_NULL;
|
*sid = SECSID_NULL;
|
||||||
rc = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
netlbl_secattr_to_sid_return:
|
read_unlock(&policy_rwlock);
|
||||||
|
return 0;
|
||||||
|
out_free:
|
||||||
|
ebitmap_destroy(&ctx_new.range.level[0].cat);
|
||||||
|
out:
|
||||||
read_unlock(&policy_rwlock);
|
read_unlock(&policy_rwlock);
|
||||||
return rc;
|
return rc;
|
||||||
netlbl_secattr_to_sid_return_cleanup:
|
|
||||||
ebitmap_destroy(&ctx_new.range.level[0].cat);
|
|
||||||
goto netlbl_secattr_to_sid_return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -3127,28 +3125,23 @@ int security_netlbl_sid_to_secattr(u32 sid, struct netlbl_lsm_secattr *secattr)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
read_lock(&policy_rwlock);
|
read_lock(&policy_rwlock);
|
||||||
|
|
||||||
|
rc = -ENOENT;
|
||||||
ctx = sidtab_search(&sidtab, sid);
|
ctx = sidtab_search(&sidtab, sid);
|
||||||
if (ctx == NULL) {
|
if (ctx == NULL)
|
||||||
rc = -ENOENT;
|
goto out;
|
||||||
goto netlbl_sid_to_secattr_failure;
|
|
||||||
}
|
rc = -ENOMEM;
|
||||||
secattr->domain = kstrdup(policydb.p_type_val_to_name[ctx->type - 1],
|
secattr->domain = kstrdup(sym_name(&policydb, SYM_TYPES, ctx->type - 1),
|
||||||
GFP_ATOMIC);
|
GFP_ATOMIC);
|
||||||
if (secattr->domain == NULL) {
|
if (secattr->domain == NULL)
|
||||||
rc = -ENOMEM;
|
goto out;
|
||||||
goto netlbl_sid_to_secattr_failure;
|
|
||||||
}
|
|
||||||
secattr->attr.secid = sid;
|
secattr->attr.secid = sid;
|
||||||
secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;
|
secattr->flags |= NETLBL_SECATTR_DOMAIN_CPY | NETLBL_SECATTR_SECID;
|
||||||
mls_export_netlbl_lvl(ctx, secattr);
|
mls_export_netlbl_lvl(ctx, secattr);
|
||||||
rc = mls_export_netlbl_cat(ctx, secattr);
|
rc = mls_export_netlbl_cat(ctx, secattr);
|
||||||
if (rc != 0)
|
out:
|
||||||
goto netlbl_sid_to_secattr_failure;
|
|
||||||
read_unlock(&policy_rwlock);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
netlbl_sid_to_secattr_failure:
|
|
||||||
read_unlock(&policy_rwlock);
|
read_unlock(&policy_rwlock);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@ -147,6 +147,17 @@ out:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sidtab_update_cache(struct sidtab *s, struct sidtab_node *n, int loc)
|
||||||
|
{
|
||||||
|
BUG_ON(loc >= SIDTAB_CACHE_LEN);
|
||||||
|
|
||||||
|
while (loc > 0) {
|
||||||
|
s->cache[loc] = s->cache[loc - 1];
|
||||||
|
loc--;
|
||||||
|
}
|
||||||
|
s->cache[0] = n;
|
||||||
|
}
|
||||||
|
|
||||||
static inline u32 sidtab_search_context(struct sidtab *s,
|
static inline u32 sidtab_search_context(struct sidtab *s,
|
||||||
struct context *context)
|
struct context *context)
|
||||||
{
|
{
|
||||||
@ -156,14 +167,33 @@ static inline u32 sidtab_search_context(struct sidtab *s,
|
|||||||
for (i = 0; i < SIDTAB_SIZE; i++) {
|
for (i = 0; i < SIDTAB_SIZE; i++) {
|
||||||
cur = s->htable[i];
|
cur = s->htable[i];
|
||||||
while (cur) {
|
while (cur) {
|
||||||
if (context_cmp(&cur->context, context))
|
if (context_cmp(&cur->context, context)) {
|
||||||
|
sidtab_update_cache(s, cur, SIDTAB_CACHE_LEN - 1);
|
||||||
return cur->sid;
|
return cur->sid;
|
||||||
|
}
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline u32 sidtab_search_cache(struct sidtab *s, struct context *context)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct sidtab_node *node;
|
||||||
|
|
||||||
|
for (i = 0; i < SIDTAB_CACHE_LEN; i++) {
|
||||||
|
node = s->cache[i];
|
||||||
|
if (unlikely(!node))
|
||||||
|
return 0;
|
||||||
|
if (context_cmp(&node->context, context)) {
|
||||||
|
sidtab_update_cache(s, node, i);
|
||||||
|
return node->sid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int sidtab_context_to_sid(struct sidtab *s,
|
int sidtab_context_to_sid(struct sidtab *s,
|
||||||
struct context *context,
|
struct context *context,
|
||||||
u32 *out_sid)
|
u32 *out_sid)
|
||||||
@ -174,7 +204,9 @@ int sidtab_context_to_sid(struct sidtab *s,
|
|||||||
|
|
||||||
*out_sid = SECSID_NULL;
|
*out_sid = SECSID_NULL;
|
||||||
|
|
||||||
sid = sidtab_search_context(s, context);
|
sid = sidtab_search_cache(s, context);
|
||||||
|
if (!sid)
|
||||||
|
sid = sidtab_search_context(s, context);
|
||||||
if (!sid) {
|
if (!sid) {
|
||||||
spin_lock_irqsave(&s->lock, flags);
|
spin_lock_irqsave(&s->lock, flags);
|
||||||
/* Rescan now that we hold the lock. */
|
/* Rescan now that we hold the lock. */
|
||||||
@ -259,12 +291,15 @@ void sidtab_destroy(struct sidtab *s)
|
|||||||
void sidtab_set(struct sidtab *dst, struct sidtab *src)
|
void sidtab_set(struct sidtab *dst, struct sidtab *src)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
int i;
|
||||||
|
|
||||||
spin_lock_irqsave(&src->lock, flags);
|
spin_lock_irqsave(&src->lock, flags);
|
||||||
dst->htable = src->htable;
|
dst->htable = src->htable;
|
||||||
dst->nel = src->nel;
|
dst->nel = src->nel;
|
||||||
dst->next_sid = src->next_sid;
|
dst->next_sid = src->next_sid;
|
||||||
dst->shutdown = 0;
|
dst->shutdown = 0;
|
||||||
|
for (i = 0; i < SIDTAB_CACHE_LEN; i++)
|
||||||
|
dst->cache[i] = NULL;
|
||||||
spin_unlock_irqrestore(&src->lock, flags);
|
spin_unlock_irqrestore(&src->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,8 @@ struct sidtab {
|
|||||||
unsigned int nel; /* number of elements */
|
unsigned int nel; /* number of elements */
|
||||||
unsigned int next_sid; /* next SID to allocate */
|
unsigned int next_sid; /* next SID to allocate */
|
||||||
unsigned char shutdown;
|
unsigned char shutdown;
|
||||||
|
#define SIDTAB_CACHE_LEN 3
|
||||||
|
struct sidtab_node *cache[SIDTAB_CACHE_LEN];
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user