diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-17 19:13:15 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-17 19:13:15 -0800 |
commit | 5807fcaa9bf7dd87241df739161c119cf78a6bc4 (patch) | |
tree | 4ed1e647a0ae0f315db3b9066c9235020c439649 /security/selinux/selinuxfs.c | |
parent | 2d663b55816e5c1d211a77fff90687053fe78aac (diff) | |
parent | acb2cfdb316ddc3fac8183c0f71edd1680713b10 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris:
- EVM gains support for loading an x509 cert from the kernel
(EVM_LOAD_X509), into the EVM trusted kernel keyring.
- Smack implements 'file receive' process-based permission checking for
sockets, rather than just depending on inode checks.
- Misc enhancments for TPM & TPM2.
- Cleanups and bugfixes for SELinux, Keys, and IMA.
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (41 commits)
selinux: Inode label revalidation performance fix
KEYS: refcount bug fix
ima: ima_write_policy() limit locking
IMA: policy can be updated zero times
selinux: rate-limit netlink message warnings in selinux_nlmsg_perm()
selinux: export validatetrans decisions
gfs2: Invalid security labels of inodes when they go invalid
selinux: Revalidate invalid inode security labels
security: Add hook to invalidate inode security labels
selinux: Add accessor functions for inode->i_security
security: Make inode argument of inode_getsecid non-const
security: Make inode argument of inode_getsecurity non-const
selinux: Remove unused variable in selinux_inode_init_security
keys, trusted: seal with a TPM2 authorization policy
keys, trusted: select hash algorithm for TPM2 chips
keys, trusted: fix: *do not* allow duplicate key options
tpm_ibmvtpm: properly handle interrupted packet receptions
tpm_tis: Tighten IRQ auto-probing
tpm_tis: Refactor the interrupt setup
tpm_tis: Get rid of the duplicate IRQ probing code
...
Diffstat (limited to 'security/selinux/selinuxfs.c')
-rw-r--r-- | security/selinux/selinuxfs.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 73c60baa90a4..732c1c77dccd 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c @@ -116,6 +116,7 @@ enum sel_inos { SEL_DENY_UNKNOWN, /* export unknown deny handling to userspace */ SEL_STATUS, /* export current status using mmap() */ 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 */ }; @@ -632,6 +633,83 @@ static const struct file_operations sel_checkreqprot_ops = { .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 */ @@ -1727,6 +1805,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_STATUS] = {"status", &sel_handle_status_ops, S_IRUGO}, [SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUGO}, + [SEL_VALIDATE_TRANS] = {"validatetrans", &sel_transition_ops, + S_IWUGO}, /* last one */ {""} }; ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); |