Signed-off-by: KaiGai Kohei -- security/selinux/selinuxfs.c | 24 ++++++++++++++++++++++++ 1 files changed, 24 insertions(+), 0 deletions(-) diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index d3c8b98..10accc0 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -122,6 +122,7 @@ enum sel_inos { SEL_COMPAT_NET, /* whether to use old compat network packet controls */ SEL_REJECT_UNKNOWN, /* export unknown reject handling to userspace */ SEL_DENY_UNKNOWN, /* export unknown deny handling to userspace */ + SEL_PERMISSIVE, /* check whether permissive domain or not */ SEL_INO_NEXT, /* The next inode number to use */ }; @@ -513,6 +514,7 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size); static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size); static ssize_t sel_write_user(struct file *file, char *buf, size_t size); static ssize_t sel_write_member(struct file *file, char *buf, size_t size); +static ssize_t sel_write_permissive(struct file *file, char *buf, size_t size); static ssize_t (*write_op[])(struct file *, char *, size_t) = { [SEL_ACCESS] = sel_write_access, @@ -521,6 +523,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = { [SEL_USER] = sel_write_user, [SEL_MEMBER] = sel_write_member, [SEL_CONTEXT] = sel_write_context, + [SEL_PERMISSIVE] = sel_write_permissive, }; static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) @@ -841,6 +844,26 @@ out: return length; } +static ssize_t sel_write_permissive(struct file *file, char *buf, size_t size) +{ + u32 sid; + ssize_t rc; + + /* + * MEMO: Is it correct to check security:{check_context} here? + * Or, we should add something like security:{check_permissive}? + */ + rc = task_has_security(current, SECURITY__CHECK_CONTEXT); + if (rc) + return rc; + + rc = security_context_to_sid(buf, size, &sid); + if (rc < 0) + return rc; + + return security_permissive_sid(sid); +} + static struct inode *sel_make_inode(struct super_block *sb, int mode) { struct inode *ret = new_inode(sb); @@ -1668,6 +1691,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) [SEL_COMPAT_NET] = {"compat_net", &sel_compat_net_ops, S_IRUGO|S_IWUSR}, [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO}, [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO}, + [SEL_PERMISSIVE] = {"permissive", &transaction_ops, S_IRUGO|S_IWUGO}, /* last one */ {""} }; ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);