diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-08 15:41:25 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-08 15:41:25 -0400 |
commit | b793c005ceabf6db0b17494b0ec67ade6796bb34 (patch) | |
tree | 080c884f04254403ec9564742f591a9fd9b7e95a /security/selinux/hooks.c | |
parent | 6f0a2fc1feb19bd142961a39dc118e7e55418b3f (diff) | |
parent | 07f081fb5057b2ea98baeca3a47bf0eb33e94aa1 (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.c | 147 |
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 | */ | ||
1715 | static 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. */ |
1702 | static int may_create(struct inode *dir, | 1739 | static 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 | */ | ||
3241 | int 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); | ||
3273 | out: | ||
3274 | return rc; | ||
3275 | } | ||
3276 | |||
3231 | static int selinux_file_ioctl(struct file *file, unsigned int cmd, | 3277 | static 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 | ||