aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/hooks.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-09-08 15:41:25 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-08 15:41:25 -0400
commitb793c005ceabf6db0b17494b0ec67ade6796bb34 (patch)
tree080c884f04254403ec9564742f591a9fd9b7e95a /security/selinux/hooks.c
parent6f0a2fc1feb19bd142961a39dc118e7e55418b3f (diff)
parent07f081fb5057b2ea98baeca3a47bf0eb33e94aa1 (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris: "Highlights: - PKCS#7 support added to support signed kexec, also utilized for module signing. See comments in 3f1e1bea. ** NOTE: this requires linking against the OpenSSL library, which must be installed, e.g. the openssl-devel on Fedora ** - Smack - add IPv6 host labeling; ignore labels on kernel threads - support smack labeling mounts which use binary mount data - SELinux: - add ioctl whitelisting (see http://kernsec.org/files/lss2015/vanderstoep.pdf) - fix mprotect PROT_EXEC regression caused by mm change - Seccomp: - add ptrace options for suspend/resume" * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (57 commits) PKCS#7: Add OIDs for sha224, sha284 and sha512 hash algos and use them Documentation/Changes: Now need OpenSSL devel packages for module signing scripts: add extract-cert and sign-file to .gitignore modsign: Handle signing key in source tree modsign: Use if_changed rule for extracting cert from module signing key Move certificate handling to its own directory sign-file: Fix warning about BIO_reset() return value PKCS#7: Add MODULE_LICENSE() to test module Smack - Fix build error with bringup unconfigured sign-file: Document dependency on OpenSSL devel libraries PKCS#7: Appropriately restrict authenticated attributes and content type KEYS: Add a name for PKEY_ID_PKCS7 PKCS#7: Improve and export the X.509 ASN.1 time object decoder modsign: Use extract-cert to process CONFIG_SYSTEM_TRUSTED_KEYS extract-cert: Cope with multiple X.509 certificates in a single file sign-file: Generate CMS message as signature instead of PKCS#7 PKCS#7: Support CMS messages also [RFC5652] X.509: Change recorded SKID & AKID to not include Subject or Issuer PKCS#7: Check content type and versions MAINTAINERS: The keyrings mailing list has moved ...
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r--security/selinux/hooks.c147
1 files changed, 97 insertions, 50 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index cdf4c589a391..e4369d86e588 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -254,10 +254,21 @@ static void inode_free_security(struct inode *inode)
254 struct inode_security_struct *isec = inode->i_security; 254 struct inode_security_struct *isec = inode->i_security;
255 struct superblock_security_struct *sbsec = inode->i_sb->s_security; 255 struct superblock_security_struct *sbsec = inode->i_sb->s_security;
256 256
257 spin_lock(&sbsec->isec_lock); 257 /*
258 if (!list_empty(&isec->list)) 258 * As not all inode security structures are in a list, we check for
259 * empty list outside of the lock to make sure that we won't waste
260 * time taking a lock doing nothing.
261 *
262 * The list_del_init() function can be safely called more than once.
263 * It should not be possible for this function to be called with
264 * concurrent list_add(), but for better safety against future changes
265 * in the code, we use list_empty_careful() here.
266 */
267 if (!list_empty_careful(&isec->list)) {
268 spin_lock(&sbsec->isec_lock);
259 list_del_init(&isec->list); 269 list_del_init(&isec->list);
260 spin_unlock(&sbsec->isec_lock); 270 spin_unlock(&sbsec->isec_lock);
271 }
261 272
262 /* 273 /*
263 * The inode may still be referenced in a path walk and 274 * The inode may still be referenced in a path walk and
@@ -1698,6 +1709,32 @@ out:
1698 return rc; 1709 return rc;
1699} 1710}
1700 1711
1712/*
1713 * Determine the label for an inode that might be unioned.
1714 */
1715static int selinux_determine_inode_label(const struct inode *dir,
1716 const struct qstr *name,
1717 u16 tclass,
1718 u32 *_new_isid)
1719{
1720 const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
1721 const struct inode_security_struct *dsec = dir->i_security;
1722 const struct task_security_struct *tsec = current_security();
1723
1724 if ((sbsec->flags & SE_SBINITIALIZED) &&
1725 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
1726 *_new_isid = sbsec->mntpoint_sid;
1727 } else if ((sbsec->flags & SBLABEL_MNT) &&
1728 tsec->create_sid) {
1729 *_new_isid = tsec->create_sid;
1730 } else {
1731 return security_transition_sid(tsec->sid, dsec->sid, tclass,
1732 name, _new_isid);
1733 }
1734
1735 return 0;
1736}
1737
1701/* Check whether a task can create a file. */ 1738/* Check whether a task can create a file. */
1702static int may_create(struct inode *dir, 1739static int may_create(struct inode *dir,
1703 struct dentry *dentry, 1740 struct dentry *dentry,
@@ -1714,7 +1751,6 @@ static int may_create(struct inode *dir,
1714 sbsec = dir->i_sb->s_security; 1751 sbsec = dir->i_sb->s_security;
1715 1752
1716 sid = tsec->sid; 1753 sid = tsec->sid;
1717 newsid = tsec->create_sid;
1718 1754
1719 ad.type = LSM_AUDIT_DATA_DENTRY; 1755 ad.type = LSM_AUDIT_DATA_DENTRY;
1720 ad.u.dentry = dentry; 1756 ad.u.dentry = dentry;
@@ -1725,12 +1761,10 @@ static int may_create(struct inode *dir,
1725 if (rc) 1761 if (rc)
1726 return rc; 1762 return rc;
1727 1763
1728 if (!newsid || !(sbsec->flags & SBLABEL_MNT)) { 1764 rc = selinux_determine_inode_label(dir, &dentry->d_name, tclass,
1729 rc = security_transition_sid(sid, dsec->sid, tclass, 1765 &newsid);
1730 &dentry->d_name, &newsid); 1766 if (rc)
1731 if (rc) 1767 return rc;
1732 return rc;
1733 }
1734 1768
1735 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad); 1769 rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
1736 if (rc) 1770 if (rc)
@@ -2704,32 +2738,14 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
2704 struct qstr *name, void **ctx, 2738 struct qstr *name, void **ctx,
2705 u32 *ctxlen) 2739 u32 *ctxlen)
2706{ 2740{
2707 const struct cred *cred = current_cred();
2708 struct task_security_struct *tsec;
2709 struct inode_security_struct *dsec;
2710 struct superblock_security_struct *sbsec;
2711 struct inode *dir = d_backing_inode(dentry->d_parent);
2712 u32 newsid; 2741 u32 newsid;
2713 int rc; 2742 int rc;
2714 2743
2715 tsec = cred->security; 2744 rc = selinux_determine_inode_label(d_inode(dentry->d_parent), name,
2716 dsec = dir->i_security; 2745 inode_mode_to_security_class(mode),
2717 sbsec = dir->i_sb->s_security; 2746 &newsid);
2718 2747 if (rc)
2719 if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { 2748 return rc;
2720 newsid = tsec->create_sid;
2721 } else {
2722 rc = security_transition_sid(tsec->sid, dsec->sid,
2723 inode_mode_to_security_class(mode),
2724 name,
2725 &newsid);
2726 if (rc) {
2727 printk(KERN_WARNING
2728 "%s: security_transition_sid failed, rc=%d\n",
2729 __func__, -rc);
2730 return rc;
2731 }
2732 }
2733 2749
2734 return security_sid_to_context(newsid, (char **)ctx, ctxlen); 2750 return security_sid_to_context(newsid, (char **)ctx, ctxlen);
2735} 2751}
@@ -2752,22 +2768,12 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
2752 sid = tsec->sid; 2768 sid = tsec->sid;
2753 newsid = tsec->create_sid; 2769 newsid = tsec->create_sid;
2754 2770
2755 if ((sbsec->flags & SE_SBINITIALIZED) && 2771 rc = selinux_determine_inode_label(
2756 (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) 2772 dir, qstr,
2757 newsid = sbsec->mntpoint_sid; 2773 inode_mode_to_security_class(inode->i_mode),
2758 else if (!newsid || !(sbsec->flags & SBLABEL_MNT)) { 2774 &newsid);
2759 rc = security_transition_sid(sid, dsec->sid, 2775 if (rc)
2760 inode_mode_to_security_class(inode->i_mode), 2776 return rc;
2761 qstr, &newsid);
2762 if (rc) {
2763 printk(KERN_WARNING "%s: "
2764 "security_transition_sid failed, rc=%d (dev=%s "
2765 "ino=%ld)\n",
2766 __func__,
2767 -rc, inode->i_sb->s_id, inode->i_ino);
2768 return rc;
2769 }
2770 }
2771 2777
2772 /* Possibly defer initialization to selinux_complete_init. */ 2778 /* Possibly defer initialization to selinux_complete_init. */
2773 if (sbsec->flags & SE_SBINITIALIZED) { 2779 if (sbsec->flags & SE_SBINITIALIZED) {
@@ -3228,6 +3234,46 @@ static void selinux_file_free_security(struct file *file)
3228 file_free_security(file); 3234 file_free_security(file);
3229} 3235}
3230 3236
3237/*
3238 * Check whether a task has the ioctl permission and cmd
3239 * operation to an inode.
3240 */
3241int ioctl_has_perm(const struct cred *cred, struct file *file,
3242 u32 requested, u16 cmd)
3243{
3244 struct common_audit_data ad;
3245 struct file_security_struct *fsec = file->f_security;
3246 struct inode *inode = file_inode(file);
3247 struct inode_security_struct *isec = inode->i_security;
3248 struct lsm_ioctlop_audit ioctl;
3249 u32 ssid = cred_sid(cred);
3250 int rc;
3251 u8 driver = cmd >> 8;
3252 u8 xperm = cmd & 0xff;
3253
3254 ad.type = LSM_AUDIT_DATA_IOCTL_OP;
3255 ad.u.op = &ioctl;
3256 ad.u.op->cmd = cmd;
3257 ad.u.op->path = file->f_path;
3258
3259 if (ssid != fsec->sid) {
3260 rc = avc_has_perm(ssid, fsec->sid,
3261 SECCLASS_FD,
3262 FD__USE,
3263 &ad);
3264 if (rc)
3265 goto out;
3266 }
3267
3268 if (unlikely(IS_PRIVATE(inode)))
3269 return 0;
3270
3271 rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass,
3272 requested, driver, xperm, &ad);
3273out:
3274 return rc;
3275}
3276
3231static int selinux_file_ioctl(struct file *file, unsigned int cmd, 3277static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3232 unsigned long arg) 3278 unsigned long arg)
3233{ 3279{
@@ -3270,7 +3316,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
3270 * to the file's ioctl() function. 3316 * to the file's ioctl() function.
3271 */ 3317 */
3272 default: 3318 default:
3273 error = file_has_perm(cred, file, FILE__IOCTL); 3319 error = ioctl_has_perm(cred, file, FILE__IOCTL, (u16) cmd);
3274 } 3320 }
3275 return error; 3321 return error;
3276} 3322}
@@ -4520,6 +4566,7 @@ static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority
4520 4566
4521 sksec->peer_sid = SECINITSID_UNLABELED; 4567 sksec->peer_sid = SECINITSID_UNLABELED;
4522 sksec->sid = SECINITSID_UNLABELED; 4568 sksec->sid = SECINITSID_UNLABELED;
4569 sksec->sclass = SECCLASS_SOCKET;
4523 selinux_netlbl_sk_security_reset(sksec); 4570 selinux_netlbl_sk_security_reset(sksec);
4524 sk->sk_security = sksec; 4571 sk->sk_security = sksec;
4525 4572