提交 f9df6458 编写于 作者: A Andrew Perepechko 提交者: Paul Moore

selinux: export validatetrans decisions

Make validatetrans decisions available through selinuxfs.
"/validatetrans" is added to selinuxfs for this purpose.
This functionality is needed by file system servers
implemented in userspace or kernelspace without the VFS
layer.

Writing "$oldcontext $newcontext $tclass $taskcontext"
to /validatetrans is expected to return 0 if the transition
is allowed and -EPERM otherwise.
Signed-off-by: NAndrew Perepechko <anserper@ya.ru>
CC: andrew.perepechko@seagate.com
Acked-by: NStephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: NPaul Moore <pmoore@redhat.com>
上级 f39814f6
...@@ -21,7 +21,7 @@ struct security_class_mapping secclass_map[] = { ...@@ -21,7 +21,7 @@ struct security_class_mapping secclass_map[] = {
{ "compute_av", "compute_create", "compute_member", { "compute_av", "compute_create", "compute_member",
"check_context", "load_policy", "compute_relabel", "check_context", "load_policy", "compute_relabel",
"compute_user", "setenforce", "setbool", "setsecparam", "compute_user", "setenforce", "setbool", "setsecparam",
"setcheckreqprot", "read_policy", NULL } }, "setcheckreqprot", "read_policy", "validate_trans", NULL } },
{ "process", { "process",
{ "fork", "transition", "sigchld", "sigkill", { "fork", "transition", "sigchld", "sigkill",
"sigstop", "signull", "signal", "ptrace", "getsched", "setsched", "sigstop", "signull", "signal", "ptrace", "getsched", "setsched",
......
...@@ -187,6 +187,9 @@ int security_node_sid(u16 domain, void *addr, u32 addrlen, ...@@ -187,6 +187,9 @@ int security_node_sid(u16 domain, void *addr, u32 addrlen,
int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
u16 tclass); u16 tclass);
int security_validate_transition_user(u32 oldsid, u32 newsid, u32 tasksid,
u16 tclass);
int security_bounded_transition(u32 oldsid, u32 newsid); int security_bounded_transition(u32 oldsid, u32 newsid);
int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid); int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
......
...@@ -116,6 +116,7 @@ enum sel_inos { ...@@ -116,6 +116,7 @@ enum sel_inos {
SEL_DENY_UNKNOWN, /* export unknown deny handling to userspace */ SEL_DENY_UNKNOWN, /* export unknown deny handling to userspace */
SEL_STATUS, /* export current status using mmap() */ SEL_STATUS, /* export current status using mmap() */
SEL_POLICY, /* allow userspace to read the in kernel policy */ SEL_POLICY, /* allow userspace to read the in kernel policy */
SEL_VALIDATE_TRANS, /* compute validatetrans decision */
SEL_INO_NEXT, /* The next inode number to use */ SEL_INO_NEXT, /* The next inode number to use */
}; };
...@@ -653,6 +654,83 @@ static const struct file_operations sel_checkreqprot_ops = { ...@@ -653,6 +654,83 @@ static const struct file_operations sel_checkreqprot_ops = {
.llseek = generic_file_llseek, .llseek = generic_file_llseek,
}; };
static ssize_t sel_write_validatetrans(struct file *file,
const char __user *buf,
size_t count, loff_t *ppos)
{
char *oldcon = NULL, *newcon = NULL, *taskcon = NULL;
char *req = NULL;
u32 osid, nsid, tsid;
u16 tclass;
int rc;
rc = task_has_security(current, SECURITY__VALIDATE_TRANS);
if (rc)
goto out;
rc = -ENOMEM;
if (count >= PAGE_SIZE)
goto out;
/* No partial writes. */
rc = -EINVAL;
if (*ppos != 0)
goto out;
rc = -ENOMEM;
req = kzalloc(count + 1, GFP_KERNEL);
if (!req)
goto out;
rc = -EFAULT;
if (copy_from_user(req, buf, count))
goto out;
rc = -ENOMEM;
oldcon = kzalloc(count + 1, GFP_KERNEL);
if (!oldcon)
goto out;
newcon = kzalloc(count + 1, GFP_KERNEL);
if (!newcon)
goto out;
taskcon = kzalloc(count + 1, GFP_KERNEL);
if (!taskcon)
goto out;
rc = -EINVAL;
if (sscanf(req, "%s %s %hu %s", oldcon, newcon, &tclass, taskcon) != 4)
goto out;
rc = security_context_str_to_sid(oldcon, &osid, GFP_KERNEL);
if (rc)
goto out;
rc = security_context_str_to_sid(newcon, &nsid, GFP_KERNEL);
if (rc)
goto out;
rc = security_context_str_to_sid(taskcon, &tsid, GFP_KERNEL);
if (rc)
goto out;
rc = security_validate_transition_user(osid, nsid, tsid, tclass);
if (!rc)
rc = count;
out:
kfree(req);
kfree(oldcon);
kfree(newcon);
kfree(taskcon);
return rc;
}
static const struct file_operations sel_transition_ops = {
.write = sel_write_validatetrans,
.llseek = generic_file_llseek,
};
/* /*
* Remaining nodes use transaction based IO methods like nfsd/nfsctl.c * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
*/ */
...@@ -1759,6 +1837,8 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) ...@@ -1759,6 +1837,8 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)
[SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO}, [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO},
[SEL_STATUS] = {"status", &sel_handle_status_ops, S_IRUGO}, [SEL_STATUS] = {"status", &sel_handle_status_ops, S_IRUGO},
[SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUGO}, [SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUGO},
[SEL_VALIDATE_TRANS] = {"validatetrans", &sel_transition_ops,
S_IWUGO},
/* last one */ {""} /* last one */ {""}
}; };
ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
......
...@@ -778,8 +778,8 @@ out: ...@@ -778,8 +778,8 @@ out:
return -EPERM; return -EPERM;
} }
int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, static int security_compute_validatetrans(u32 oldsid, u32 newsid, u32 tasksid,
u16 orig_tclass) u16 orig_tclass, bool user)
{ {
struct context *ocontext; struct context *ocontext;
struct context *ncontext; struct context *ncontext;
...@@ -794,11 +794,12 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, ...@@ -794,11 +794,12 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
read_lock(&policy_rwlock); read_lock(&policy_rwlock);
tclass = unmap_class(orig_tclass); if (!user)
tclass = unmap_class(orig_tclass);
else
tclass = orig_tclass;
if (!tclass || tclass > policydb.p_classes.nprim) { if (!tclass || tclass > policydb.p_classes.nprim) {
printk(KERN_ERR "SELinux: %s: unrecognized class %d\n",
__func__, tclass);
rc = -EINVAL; rc = -EINVAL;
goto out; goto out;
} }
...@@ -832,8 +833,13 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, ...@@ -832,8 +833,13 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
while (constraint) { while (constraint) {
if (!constraint_expr_eval(ocontext, ncontext, tcontext, if (!constraint_expr_eval(ocontext, ncontext, tcontext,
constraint->expr)) { constraint->expr)) {
rc = security_validtrans_handle_fail(ocontext, ncontext, if (user)
tcontext, tclass); rc = -EPERM;
else
rc = security_validtrans_handle_fail(ocontext,
ncontext,
tcontext,
tclass);
goto out; goto out;
} }
constraint = constraint->next; constraint = constraint->next;
...@@ -844,6 +850,20 @@ out: ...@@ -844,6 +850,20 @@ out:
return rc; return rc;
} }
int security_validate_transition_user(u32 oldsid, u32 newsid, u32 tasksid,
u16 tclass)
{
return security_compute_validatetrans(oldsid, newsid, tasksid,
tclass, true);
}
int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid,
u16 orig_tclass)
{
return security_compute_validatetrans(oldsid, newsid, tasksid,
orig_tclass, false);
}
/* /*
* security_bounded_transition - check whether the given * security_bounded_transition - check whether the given
* transition is directed to bounded, or not. * transition is directed to bounded, or not.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册