diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 829 |
1 files changed, 448 insertions, 381 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8d8b69c5664..e276eb46853 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -13,8 +13,8 @@ | |||
13 | * Eric Paris <eparis@redhat.com> | 13 | * Eric Paris <eparis@redhat.com> |
14 | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. | 14 | * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. |
15 | * <dgoeddel@trustedcs.com> | 15 | * <dgoeddel@trustedcs.com> |
16 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. | 16 | * Copyright (C) 2006, 2007, 2009 Hewlett-Packard Development Company, L.P. |
17 | * Paul Moore <paul.moore@hp.com> | 17 | * Paul Moore <paul.moore@hp.com> |
18 | * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. | 18 | * Copyright (C) 2007 Hitachi Software Engineering Co., Ltd. |
19 | * Yuichi Nakamura <ynakam@hitachisoft.jp> | 19 | * Yuichi Nakamura <ynakam@hitachisoft.jp> |
20 | * | 20 | * |
@@ -76,6 +76,7 @@ | |||
76 | #include <linux/selinux.h> | 76 | #include <linux/selinux.h> |
77 | #include <linux/mutex.h> | 77 | #include <linux/mutex.h> |
78 | #include <linux/posix-timers.h> | 78 | #include <linux/posix-timers.h> |
79 | #include <linux/syslog.h> | ||
79 | 80 | ||
80 | #include "avc.h" | 81 | #include "avc.h" |
81 | #include "objsec.h" | 82 | #include "objsec.h" |
@@ -86,12 +87,8 @@ | |||
86 | #include "netlabel.h" | 87 | #include "netlabel.h" |
87 | #include "audit.h" | 88 | #include "audit.h" |
88 | 89 | ||
89 | #define XATTR_SELINUX_SUFFIX "selinux" | ||
90 | #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX | ||
91 | |||
92 | #define NUM_SEL_MNT_OPTS 5 | 90 | #define NUM_SEL_MNT_OPTS 5 |
93 | 91 | ||
94 | extern unsigned int policydb_loaded_version; | ||
95 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); | 92 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); |
96 | extern struct security_operations *security_ops; | 93 | extern struct security_operations *security_ops; |
97 | 94 | ||
@@ -126,18 +123,6 @@ __setup("selinux=", selinux_enabled_setup); | |||
126 | int selinux_enabled = 1; | 123 | int selinux_enabled = 1; |
127 | #endif | 124 | #endif |
128 | 125 | ||
129 | |||
130 | /* | ||
131 | * Minimal support for a secondary security module, | ||
132 | * just to allow the use of the capability module. | ||
133 | */ | ||
134 | static struct security_operations *secondary_ops; | ||
135 | |||
136 | /* Lists of inode and superblock security structures initialized | ||
137 | before the policy was loaded. */ | ||
138 | static LIST_HEAD(superblock_security_head); | ||
139 | static DEFINE_SPINLOCK(sb_security_lock); | ||
140 | |||
141 | static struct kmem_cache *sel_inode_cache; | 126 | static struct kmem_cache *sel_inode_cache; |
142 | 127 | ||
143 | /** | 128 | /** |
@@ -200,7 +185,7 @@ static inline u32 task_sid(const struct task_struct *task) | |||
200 | */ | 185 | */ |
201 | static inline u32 current_sid(void) | 186 | static inline u32 current_sid(void) |
202 | { | 187 | { |
203 | const struct task_security_struct *tsec = current_cred()->security; | 188 | const struct task_security_struct *tsec = current_security(); |
204 | 189 | ||
205 | return tsec->sid; | 190 | return tsec->sid; |
206 | } | 191 | } |
@@ -273,7 +258,6 @@ static int superblock_alloc_security(struct super_block *sb) | |||
273 | return -ENOMEM; | 258 | return -ENOMEM; |
274 | 259 | ||
275 | mutex_init(&sbsec->lock); | 260 | mutex_init(&sbsec->lock); |
276 | INIT_LIST_HEAD(&sbsec->list); | ||
277 | INIT_LIST_HEAD(&sbsec->isec_head); | 261 | INIT_LIST_HEAD(&sbsec->isec_head); |
278 | spin_lock_init(&sbsec->isec_lock); | 262 | spin_lock_init(&sbsec->isec_lock); |
279 | sbsec->sb = sb; | 263 | sbsec->sb = sb; |
@@ -288,49 +272,17 @@ static int superblock_alloc_security(struct super_block *sb) | |||
288 | static void superblock_free_security(struct super_block *sb) | 272 | static void superblock_free_security(struct super_block *sb) |
289 | { | 273 | { |
290 | struct superblock_security_struct *sbsec = sb->s_security; | 274 | struct superblock_security_struct *sbsec = sb->s_security; |
291 | |||
292 | spin_lock(&sb_security_lock); | ||
293 | if (!list_empty(&sbsec->list)) | ||
294 | list_del_init(&sbsec->list); | ||
295 | spin_unlock(&sb_security_lock); | ||
296 | |||
297 | sb->s_security = NULL; | 275 | sb->s_security = NULL; |
298 | kfree(sbsec); | 276 | kfree(sbsec); |
299 | } | 277 | } |
300 | 278 | ||
301 | static int sk_alloc_security(struct sock *sk, int family, gfp_t priority) | ||
302 | { | ||
303 | struct sk_security_struct *ssec; | ||
304 | |||
305 | ssec = kzalloc(sizeof(*ssec), priority); | ||
306 | if (!ssec) | ||
307 | return -ENOMEM; | ||
308 | |||
309 | ssec->peer_sid = SECINITSID_UNLABELED; | ||
310 | ssec->sid = SECINITSID_UNLABELED; | ||
311 | sk->sk_security = ssec; | ||
312 | |||
313 | selinux_netlbl_sk_security_reset(ssec); | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static void sk_free_security(struct sock *sk) | ||
319 | { | ||
320 | struct sk_security_struct *ssec = sk->sk_security; | ||
321 | |||
322 | sk->sk_security = NULL; | ||
323 | selinux_netlbl_sk_security_free(ssec); | ||
324 | kfree(ssec); | ||
325 | } | ||
326 | |||
327 | /* The security server must be initialized before | 279 | /* The security server must be initialized before |
328 | any labeling or access decisions can be provided. */ | 280 | any labeling or access decisions can be provided. */ |
329 | extern int ss_initialized; | 281 | extern int ss_initialized; |
330 | 282 | ||
331 | /* The file system's label must be initialized prior to use. */ | 283 | /* The file system's label must be initialized prior to use. */ |
332 | 284 | ||
333 | static char *labeling_behaviors[6] = { | 285 | static const char *labeling_behaviors[6] = { |
334 | "uses xattr", | 286 | "uses xattr", |
335 | "uses transition SIDs", | 287 | "uses transition SIDs", |
336 | "uses task SIDs", | 288 | "uses task SIDs", |
@@ -448,6 +400,10 @@ static int sb_finish_set_opts(struct super_block *sb) | |||
448 | sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) | 400 | sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) |
449 | sbsec->flags &= ~SE_SBLABELSUPP; | 401 | sbsec->flags &= ~SE_SBLABELSUPP; |
450 | 402 | ||
403 | /* Special handling for sysfs. Is genfs but also has setxattr handler*/ | ||
404 | if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0) | ||
405 | sbsec->flags |= SE_SBLABELSUPP; | ||
406 | |||
451 | /* Initialize the root inode. */ | 407 | /* Initialize the root inode. */ |
452 | rc = inode_doinit_with_dentry(root_inode, root); | 408 | rc = inode_doinit_with_dentry(root_inode, root); |
453 | 409 | ||
@@ -615,10 +571,6 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
615 | /* Defer initialization until selinux_complete_init, | 571 | /* Defer initialization until selinux_complete_init, |
616 | after the initial policy is loaded and the security | 572 | after the initial policy is loaded and the security |
617 | server is ready to handle calls. */ | 573 | server is ready to handle calls. */ |
618 | spin_lock(&sb_security_lock); | ||
619 | if (list_empty(&sbsec->list)) | ||
620 | list_add(&sbsec->list, &superblock_security_head); | ||
621 | spin_unlock(&sb_security_lock); | ||
622 | goto out; | 574 | goto out; |
623 | } | 575 | } |
624 | rc = -EINVAL; | 576 | rc = -EINVAL; |
@@ -809,16 +761,10 @@ static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, | |||
809 | 761 | ||
810 | /* | 762 | /* |
811 | * if the parent was able to be mounted it clearly had no special lsm | 763 | * if the parent was able to be mounted it clearly had no special lsm |
812 | * mount options. thus we can safely put this sb on the list and deal | 764 | * mount options. thus we can safely deal with this superblock later |
813 | * with it later | ||
814 | */ | 765 | */ |
815 | if (!ss_initialized) { | 766 | if (!ss_initialized) |
816 | spin_lock(&sb_security_lock); | ||
817 | if (list_empty(&newsbsec->list)) | ||
818 | list_add(&newsbsec->list, &superblock_security_head); | ||
819 | spin_unlock(&sb_security_lock); | ||
820 | return; | 767 | return; |
821 | } | ||
822 | 768 | ||
823 | /* how can we clone if the old one wasn't set up?? */ | 769 | /* how can we clone if the old one wasn't set up?? */ |
824 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); | 770 | BUG_ON(!(oldsbsec->flags & SE_SBINITIALIZED)); |
@@ -1479,14 +1425,14 @@ static int task_has_capability(struct task_struct *tsk, | |||
1479 | const struct cred *cred, | 1425 | const struct cred *cred, |
1480 | int cap, int audit) | 1426 | int cap, int audit) |
1481 | { | 1427 | { |
1482 | struct avc_audit_data ad; | 1428 | struct common_audit_data ad; |
1483 | struct av_decision avd; | 1429 | struct av_decision avd; |
1484 | u16 sclass; | 1430 | u16 sclass; |
1485 | u32 sid = cred_sid(cred); | 1431 | u32 sid = cred_sid(cred); |
1486 | u32 av = CAP_TO_MASK(cap); | 1432 | u32 av = CAP_TO_MASK(cap); |
1487 | int rc; | 1433 | int rc; |
1488 | 1434 | ||
1489 | AVC_AUDIT_DATA_INIT(&ad, CAP); | 1435 | COMMON_AUDIT_DATA_INIT(&ad, CAP); |
1490 | ad.tsk = tsk; | 1436 | ad.tsk = tsk; |
1491 | ad.u.cap = cap; | 1437 | ad.u.cap = cap; |
1492 | 1438 | ||
@@ -1525,12 +1471,14 @@ static int task_has_system(struct task_struct *tsk, | |||
1525 | static int inode_has_perm(const struct cred *cred, | 1471 | static int inode_has_perm(const struct cred *cred, |
1526 | struct inode *inode, | 1472 | struct inode *inode, |
1527 | u32 perms, | 1473 | u32 perms, |
1528 | struct avc_audit_data *adp) | 1474 | struct common_audit_data *adp) |
1529 | { | 1475 | { |
1530 | struct inode_security_struct *isec; | 1476 | struct inode_security_struct *isec; |
1531 | struct avc_audit_data ad; | 1477 | struct common_audit_data ad; |
1532 | u32 sid; | 1478 | u32 sid; |
1533 | 1479 | ||
1480 | validate_creds(cred); | ||
1481 | |||
1534 | if (unlikely(IS_PRIVATE(inode))) | 1482 | if (unlikely(IS_PRIVATE(inode))) |
1535 | return 0; | 1483 | return 0; |
1536 | 1484 | ||
@@ -1539,7 +1487,7 @@ static int inode_has_perm(const struct cred *cred, | |||
1539 | 1487 | ||
1540 | if (!adp) { | 1488 | if (!adp) { |
1541 | adp = &ad; | 1489 | adp = &ad; |
1542 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1490 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1543 | ad.u.fs.inode = inode; | 1491 | ad.u.fs.inode = inode; |
1544 | } | 1492 | } |
1545 | 1493 | ||
@@ -1555,9 +1503,9 @@ static inline int dentry_has_perm(const struct cred *cred, | |||
1555 | u32 av) | 1503 | u32 av) |
1556 | { | 1504 | { |
1557 | struct inode *inode = dentry->d_inode; | 1505 | struct inode *inode = dentry->d_inode; |
1558 | struct avc_audit_data ad; | 1506 | struct common_audit_data ad; |
1559 | 1507 | ||
1560 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1508 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1561 | ad.u.fs.path.mnt = mnt; | 1509 | ad.u.fs.path.mnt = mnt; |
1562 | ad.u.fs.path.dentry = dentry; | 1510 | ad.u.fs.path.dentry = dentry; |
1563 | return inode_has_perm(cred, inode, av, &ad); | 1511 | return inode_has_perm(cred, inode, av, &ad); |
@@ -1577,11 +1525,11 @@ static int file_has_perm(const struct cred *cred, | |||
1577 | { | 1525 | { |
1578 | struct file_security_struct *fsec = file->f_security; | 1526 | struct file_security_struct *fsec = file->f_security; |
1579 | struct inode *inode = file->f_path.dentry->d_inode; | 1527 | struct inode *inode = file->f_path.dentry->d_inode; |
1580 | struct avc_audit_data ad; | 1528 | struct common_audit_data ad; |
1581 | u32 sid = cred_sid(cred); | 1529 | u32 sid = cred_sid(cred); |
1582 | int rc; | 1530 | int rc; |
1583 | 1531 | ||
1584 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1532 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1585 | ad.u.fs.path = file->f_path; | 1533 | ad.u.fs.path = file->f_path; |
1586 | 1534 | ||
1587 | if (sid != fsec->sid) { | 1535 | if (sid != fsec->sid) { |
@@ -1607,12 +1555,11 @@ static int may_create(struct inode *dir, | |||
1607 | struct dentry *dentry, | 1555 | struct dentry *dentry, |
1608 | u16 tclass) | 1556 | u16 tclass) |
1609 | { | 1557 | { |
1610 | const struct cred *cred = current_cred(); | 1558 | const struct task_security_struct *tsec = current_security(); |
1611 | const struct task_security_struct *tsec = cred->security; | ||
1612 | struct inode_security_struct *dsec; | 1559 | struct inode_security_struct *dsec; |
1613 | struct superblock_security_struct *sbsec; | 1560 | struct superblock_security_struct *sbsec; |
1614 | u32 sid, newsid; | 1561 | u32 sid, newsid; |
1615 | struct avc_audit_data ad; | 1562 | struct common_audit_data ad; |
1616 | int rc; | 1563 | int rc; |
1617 | 1564 | ||
1618 | dsec = dir->i_security; | 1565 | dsec = dir->i_security; |
@@ -1621,7 +1568,7 @@ static int may_create(struct inode *dir, | |||
1621 | sid = tsec->sid; | 1568 | sid = tsec->sid; |
1622 | newsid = tsec->create_sid; | 1569 | newsid = tsec->create_sid; |
1623 | 1570 | ||
1624 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1571 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1625 | ad.u.fs.path.dentry = dentry; | 1572 | ad.u.fs.path.dentry = dentry; |
1626 | 1573 | ||
1627 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, | 1574 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, |
@@ -1665,7 +1612,7 @@ static int may_link(struct inode *dir, | |||
1665 | 1612 | ||
1666 | { | 1613 | { |
1667 | struct inode_security_struct *dsec, *isec; | 1614 | struct inode_security_struct *dsec, *isec; |
1668 | struct avc_audit_data ad; | 1615 | struct common_audit_data ad; |
1669 | u32 sid = current_sid(); | 1616 | u32 sid = current_sid(); |
1670 | u32 av; | 1617 | u32 av; |
1671 | int rc; | 1618 | int rc; |
@@ -1673,7 +1620,7 @@ static int may_link(struct inode *dir, | |||
1673 | dsec = dir->i_security; | 1620 | dsec = dir->i_security; |
1674 | isec = dentry->d_inode->i_security; | 1621 | isec = dentry->d_inode->i_security; |
1675 | 1622 | ||
1676 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1623 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1677 | ad.u.fs.path.dentry = dentry; | 1624 | ad.u.fs.path.dentry = dentry; |
1678 | 1625 | ||
1679 | av = DIR__SEARCH; | 1626 | av = DIR__SEARCH; |
@@ -1708,7 +1655,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1708 | struct dentry *new_dentry) | 1655 | struct dentry *new_dentry) |
1709 | { | 1656 | { |
1710 | struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; | 1657 | struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; |
1711 | struct avc_audit_data ad; | 1658 | struct common_audit_data ad; |
1712 | u32 sid = current_sid(); | 1659 | u32 sid = current_sid(); |
1713 | u32 av; | 1660 | u32 av; |
1714 | int old_is_dir, new_is_dir; | 1661 | int old_is_dir, new_is_dir; |
@@ -1719,7 +1666,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1719 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); | 1666 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); |
1720 | new_dsec = new_dir->i_security; | 1667 | new_dsec = new_dir->i_security; |
1721 | 1668 | ||
1722 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1669 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1723 | 1670 | ||
1724 | ad.u.fs.path.dentry = old_dentry; | 1671 | ad.u.fs.path.dentry = old_dentry; |
1725 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, | 1672 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, |
@@ -1761,7 +1708,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1761 | static int superblock_has_perm(const struct cred *cred, | 1708 | static int superblock_has_perm(const struct cred *cred, |
1762 | struct super_block *sb, | 1709 | struct super_block *sb, |
1763 | u32 perms, | 1710 | u32 perms, |
1764 | struct avc_audit_data *ad) | 1711 | struct common_audit_data *ad) |
1765 | { | 1712 | { |
1766 | struct superblock_security_struct *sbsec; | 1713 | struct superblock_security_struct *sbsec; |
1767 | u32 sid = cred_sid(cred); | 1714 | u32 sid = cred_sid(cred); |
@@ -1829,38 +1776,20 @@ static inline u32 open_file_to_av(struct file *file) | |||
1829 | { | 1776 | { |
1830 | u32 av = file_to_av(file); | 1777 | u32 av = file_to_av(file); |
1831 | 1778 | ||
1832 | if (selinux_policycap_openperm) { | 1779 | if (selinux_policycap_openperm) |
1833 | mode_t mode = file->f_path.dentry->d_inode->i_mode; | 1780 | av |= FILE__OPEN; |
1834 | /* | 1781 | |
1835 | * lnk files and socks do not really have an 'open' | ||
1836 | */ | ||
1837 | if (S_ISREG(mode)) | ||
1838 | av |= FILE__OPEN; | ||
1839 | else if (S_ISCHR(mode)) | ||
1840 | av |= CHR_FILE__OPEN; | ||
1841 | else if (S_ISBLK(mode)) | ||
1842 | av |= BLK_FILE__OPEN; | ||
1843 | else if (S_ISFIFO(mode)) | ||
1844 | av |= FIFO_FILE__OPEN; | ||
1845 | else if (S_ISDIR(mode)) | ||
1846 | av |= DIR__OPEN; | ||
1847 | else if (S_ISSOCK(mode)) | ||
1848 | av |= SOCK_FILE__OPEN; | ||
1849 | else | ||
1850 | printk(KERN_ERR "SELinux: WARNING: inside %s with " | ||
1851 | "unknown mode:%o\n", __func__, mode); | ||
1852 | } | ||
1853 | return av; | 1782 | return av; |
1854 | } | 1783 | } |
1855 | 1784 | ||
1856 | /* Hook functions begin here. */ | 1785 | /* Hook functions begin here. */ |
1857 | 1786 | ||
1858 | static int selinux_ptrace_may_access(struct task_struct *child, | 1787 | static int selinux_ptrace_access_check(struct task_struct *child, |
1859 | unsigned int mode) | 1788 | unsigned int mode) |
1860 | { | 1789 | { |
1861 | int rc; | 1790 | int rc; |
1862 | 1791 | ||
1863 | rc = cap_ptrace_may_access(child, mode); | 1792 | rc = cap_ptrace_access_check(child, mode); |
1864 | if (rc) | 1793 | if (rc) |
1865 | return rc; | 1794 | return rc; |
1866 | 1795 | ||
@@ -2048,25 +1977,22 @@ static int selinux_syslog(int type) | |||
2048 | { | 1977 | { |
2049 | int rc; | 1978 | int rc; |
2050 | 1979 | ||
2051 | rc = cap_syslog(type); | ||
2052 | if (rc) | ||
2053 | return rc; | ||
2054 | |||
2055 | switch (type) { | 1980 | switch (type) { |
2056 | case 3: /* Read last kernel messages */ | 1981 | case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */ |
2057 | case 10: /* Return size of the log buffer */ | 1982 | case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */ |
2058 | rc = task_has_system(current, SYSTEM__SYSLOG_READ); | 1983 | rc = task_has_system(current, SYSTEM__SYSLOG_READ); |
2059 | break; | 1984 | break; |
2060 | case 6: /* Disable logging to console */ | 1985 | case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */ |
2061 | case 7: /* Enable logging to console */ | 1986 | case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */ |
2062 | case 8: /* Set level of messages printed to console */ | 1987 | /* Set level of messages printed to console */ |
1988 | case SYSLOG_ACTION_CONSOLE_LEVEL: | ||
2063 | rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE); | 1989 | rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE); |
2064 | break; | 1990 | break; |
2065 | case 0: /* Close log */ | 1991 | case SYSLOG_ACTION_CLOSE: /* Close log */ |
2066 | case 1: /* Open log */ | 1992 | case SYSLOG_ACTION_OPEN: /* Open log */ |
2067 | case 2: /* Read from log */ | 1993 | case SYSLOG_ACTION_READ: /* Read from log */ |
2068 | case 4: /* Read/clear last kernel messages */ | 1994 | case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */ |
2069 | case 5: /* Clear ring buffer */ | 1995 | case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */ |
2070 | default: | 1996 | default: |
2071 | rc = task_has_system(current, SYSTEM__SYSLOG_MOD); | 1997 | rc = task_has_system(current, SYSTEM__SYSLOG_MOD); |
2072 | break; | 1998 | break; |
@@ -2101,7 +2027,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2101 | const struct task_security_struct *old_tsec; | 2027 | const struct task_security_struct *old_tsec; |
2102 | struct task_security_struct *new_tsec; | 2028 | struct task_security_struct *new_tsec; |
2103 | struct inode_security_struct *isec; | 2029 | struct inode_security_struct *isec; |
2104 | struct avc_audit_data ad; | 2030 | struct common_audit_data ad; |
2105 | struct inode *inode = bprm->file->f_path.dentry->d_inode; | 2031 | struct inode *inode = bprm->file->f_path.dentry->d_inode; |
2106 | int rc; | 2032 | int rc; |
2107 | 2033 | ||
@@ -2139,7 +2065,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2139 | return rc; | 2065 | return rc; |
2140 | } | 2066 | } |
2141 | 2067 | ||
2142 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2068 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2143 | ad.u.fs.path = bprm->file->f_path; | 2069 | ad.u.fs.path = bprm->file->f_path; |
2144 | 2070 | ||
2145 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) | 2071 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) |
@@ -2205,8 +2131,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2205 | 2131 | ||
2206 | static int selinux_bprm_secureexec(struct linux_binprm *bprm) | 2132 | static int selinux_bprm_secureexec(struct linux_binprm *bprm) |
2207 | { | 2133 | { |
2208 | const struct cred *cred = current_cred(); | 2134 | const struct task_security_struct *tsec = current_security(); |
2209 | const struct task_security_struct *tsec = cred->security; | ||
2210 | u32 sid, osid; | 2135 | u32 sid, osid; |
2211 | int atsecure = 0; | 2136 | int atsecure = 0; |
2212 | 2137 | ||
@@ -2232,7 +2157,7 @@ extern struct dentry *selinux_null; | |||
2232 | static inline void flush_unauthorized_files(const struct cred *cred, | 2157 | static inline void flush_unauthorized_files(const struct cred *cred, |
2233 | struct files_struct *files) | 2158 | struct files_struct *files) |
2234 | { | 2159 | { |
2235 | struct avc_audit_data ad; | 2160 | struct common_audit_data ad; |
2236 | struct file *file, *devnull = NULL; | 2161 | struct file *file, *devnull = NULL; |
2237 | struct tty_struct *tty; | 2162 | struct tty_struct *tty; |
2238 | struct fdtable *fdt; | 2163 | struct fdtable *fdt; |
@@ -2241,8 +2166,9 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2241 | 2166 | ||
2242 | tty = get_current_tty(); | 2167 | tty = get_current_tty(); |
2243 | if (tty) { | 2168 | if (tty) { |
2244 | file_list_lock(); | 2169 | spin_lock(&tty_files_lock); |
2245 | if (!list_empty(&tty->tty_files)) { | 2170 | if (!list_empty(&tty->tty_files)) { |
2171 | struct tty_file_private *file_priv; | ||
2246 | struct inode *inode; | 2172 | struct inode *inode; |
2247 | 2173 | ||
2248 | /* Revalidate access to controlling tty. | 2174 | /* Revalidate access to controlling tty. |
@@ -2250,14 +2176,16 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2250 | than using file_has_perm, as this particular open | 2176 | than using file_has_perm, as this particular open |
2251 | file may belong to another process and we are only | 2177 | file may belong to another process and we are only |
2252 | interested in the inode-based check here. */ | 2178 | interested in the inode-based check here. */ |
2253 | file = list_first_entry(&tty->tty_files, struct file, f_u.fu_list); | 2179 | file_priv = list_first_entry(&tty->tty_files, |
2180 | struct tty_file_private, list); | ||
2181 | file = file_priv->file; | ||
2254 | inode = file->f_path.dentry->d_inode; | 2182 | inode = file->f_path.dentry->d_inode; |
2255 | if (inode_has_perm(cred, inode, | 2183 | if (inode_has_perm(cred, inode, |
2256 | FILE__READ | FILE__WRITE, NULL)) { | 2184 | FILE__READ | FILE__WRITE, NULL)) { |
2257 | drop_tty = 1; | 2185 | drop_tty = 1; |
2258 | } | 2186 | } |
2259 | } | 2187 | } |
2260 | file_list_unlock(); | 2188 | spin_unlock(&tty_files_lock); |
2261 | tty_kref_put(tty); | 2189 | tty_kref_put(tty); |
2262 | } | 2190 | } |
2263 | /* Reset controlling tty. */ | 2191 | /* Reset controlling tty. */ |
@@ -2266,7 +2194,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2266 | 2194 | ||
2267 | /* Revalidate access to inherited open files. */ | 2195 | /* Revalidate access to inherited open files. */ |
2268 | 2196 | ||
2269 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2197 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2270 | 2198 | ||
2271 | spin_lock(&files->file_lock); | 2199 | spin_lock(&files->file_lock); |
2272 | for (;;) { | 2200 | for (;;) { |
@@ -2355,12 +2283,15 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm) | |||
2355 | rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, | 2283 | rc = avc_has_perm(new_tsec->osid, new_tsec->sid, SECCLASS_PROCESS, |
2356 | PROCESS__RLIMITINH, NULL); | 2284 | PROCESS__RLIMITINH, NULL); |
2357 | if (rc) { | 2285 | if (rc) { |
2286 | /* protect against do_prlimit() */ | ||
2287 | task_lock(current); | ||
2358 | for (i = 0; i < RLIM_NLIMITS; i++) { | 2288 | for (i = 0; i < RLIM_NLIMITS; i++) { |
2359 | rlim = current->signal->rlim + i; | 2289 | rlim = current->signal->rlim + i; |
2360 | initrlim = init_task.signal->rlim + i; | 2290 | initrlim = init_task.signal->rlim + i; |
2361 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); | 2291 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); |
2362 | } | 2292 | } |
2363 | update_rlimit_cpu(rlim->rlim_cur); | 2293 | task_unlock(current); |
2294 | update_rlimit_cpu(current, rlimit(RLIMIT_CPU)); | ||
2364 | } | 2295 | } |
2365 | } | 2296 | } |
2366 | 2297 | ||
@@ -2405,7 +2336,7 @@ static void selinux_bprm_committed_creds(struct linux_binprm *bprm) | |||
2405 | /* Wake up the parent if it is waiting so that it can recheck | 2336 | /* Wake up the parent if it is waiting so that it can recheck |
2406 | * wait permission to the new task SID. */ | 2337 | * wait permission to the new task SID. */ |
2407 | read_lock(&tasklist_lock); | 2338 | read_lock(&tasklist_lock); |
2408 | wake_up_interruptible(¤t->real_parent->signal->wait_chldexit); | 2339 | __wake_up_parent(current, current->real_parent); |
2409 | read_unlock(&tasklist_lock); | 2340 | read_unlock(&tasklist_lock); |
2410 | } | 2341 | } |
2411 | 2342 | ||
@@ -2515,7 +2446,7 @@ out: | |||
2515 | static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | 2446 | static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) |
2516 | { | 2447 | { |
2517 | const struct cred *cred = current_cred(); | 2448 | const struct cred *cred = current_cred(); |
2518 | struct avc_audit_data ad; | 2449 | struct common_audit_data ad; |
2519 | int rc; | 2450 | int rc; |
2520 | 2451 | ||
2521 | rc = superblock_doinit(sb, data); | 2452 | rc = superblock_doinit(sb, data); |
@@ -2526,7 +2457,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
2526 | if (flags & MS_KERNMOUNT) | 2457 | if (flags & MS_KERNMOUNT) |
2527 | return 0; | 2458 | return 0; |
2528 | 2459 | ||
2529 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2460 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2530 | ad.u.fs.path.dentry = sb->s_root; | 2461 | ad.u.fs.path.dentry = sb->s_root; |
2531 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); | 2462 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); |
2532 | } | 2463 | } |
@@ -2534,9 +2465,9 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
2534 | static int selinux_sb_statfs(struct dentry *dentry) | 2465 | static int selinux_sb_statfs(struct dentry *dentry) |
2535 | { | 2466 | { |
2536 | const struct cred *cred = current_cred(); | 2467 | const struct cred *cred = current_cred(); |
2537 | struct avc_audit_data ad; | 2468 | struct common_audit_data ad; |
2538 | 2469 | ||
2539 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2470 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2540 | ad.u.fs.path.dentry = dentry->d_sb->s_root; | 2471 | ad.u.fs.path.dentry = dentry->d_sb->s_root; |
2541 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); | 2472 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); |
2542 | } | 2473 | } |
@@ -2581,8 +2512,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
2581 | char **name, void **value, | 2512 | char **name, void **value, |
2582 | size_t *len) | 2513 | size_t *len) |
2583 | { | 2514 | { |
2584 | const struct cred *cred = current_cred(); | 2515 | const struct task_security_struct *tsec = current_security(); |
2585 | const struct task_security_struct *tsec = cred->security; | ||
2586 | struct inode_security_struct *dsec; | 2516 | struct inode_security_struct *dsec; |
2587 | struct superblock_security_struct *sbsec; | 2517 | struct superblock_security_struct *sbsec; |
2588 | u32 sid, newsid, clen; | 2518 | u32 sid, newsid, clen; |
@@ -2595,7 +2525,10 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | |||
2595 | sid = tsec->sid; | 2525 | sid = tsec->sid; |
2596 | newsid = tsec->create_sid; | 2526 | newsid = tsec->create_sid; |
2597 | 2527 | ||
2598 | if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { | 2528 | if ((sbsec->flags & SE_SBINITIALIZED) && |
2529 | (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) | ||
2530 | newsid = sbsec->mntpoint_sid; | ||
2531 | else if (!newsid || !(sbsec->flags & SE_SBLABELSUPP)) { | ||
2599 | rc = security_transition_sid(sid, dsec->sid, | 2532 | rc = security_transition_sid(sid, dsec->sid, |
2600 | inode_mode_to_security_class(inode->i_mode), | 2533 | inode_mode_to_security_class(inode->i_mode), |
2601 | &newsid); | 2534 | &newsid); |
@@ -2698,25 +2631,43 @@ static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *na | |||
2698 | static int selinux_inode_permission(struct inode *inode, int mask) | 2631 | static int selinux_inode_permission(struct inode *inode, int mask) |
2699 | { | 2632 | { |
2700 | const struct cred *cred = current_cred(); | 2633 | const struct cred *cred = current_cred(); |
2634 | struct common_audit_data ad; | ||
2635 | u32 perms; | ||
2636 | bool from_access; | ||
2701 | 2637 | ||
2702 | if (!mask) { | 2638 | from_access = mask & MAY_ACCESS; |
2703 | /* No permission to check. Existence test. */ | 2639 | mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND); |
2640 | |||
2641 | /* No permission to check. Existence test. */ | ||
2642 | if (!mask) | ||
2704 | return 0; | 2643 | return 0; |
2705 | } | ||
2706 | 2644 | ||
2707 | return inode_has_perm(cred, inode, | 2645 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2708 | file_mask_to_av(inode->i_mode, mask), NULL); | 2646 | ad.u.fs.inode = inode; |
2647 | |||
2648 | if (from_access) | ||
2649 | ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS; | ||
2650 | |||
2651 | perms = file_mask_to_av(inode->i_mode, mask); | ||
2652 | |||
2653 | return inode_has_perm(cred, inode, perms, &ad); | ||
2709 | } | 2654 | } |
2710 | 2655 | ||
2711 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | 2656 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) |
2712 | { | 2657 | { |
2713 | const struct cred *cred = current_cred(); | 2658 | const struct cred *cred = current_cred(); |
2659 | unsigned int ia_valid = iattr->ia_valid; | ||
2660 | |||
2661 | /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */ | ||
2662 | if (ia_valid & ATTR_FORCE) { | ||
2663 | ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE | | ||
2664 | ATTR_FORCE); | ||
2665 | if (!ia_valid) | ||
2666 | return 0; | ||
2667 | } | ||
2714 | 2668 | ||
2715 | if (iattr->ia_valid & ATTR_FORCE) | 2669 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | |
2716 | return 0; | 2670 | ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) |
2717 | |||
2718 | if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | | ||
2719 | ATTR_ATIME_SET | ATTR_MTIME_SET)) | ||
2720 | return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR); | 2671 | return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR); |
2721 | 2672 | ||
2722 | return dentry_has_perm(cred, NULL, dentry, FILE__WRITE); | 2673 | return dentry_has_perm(cred, NULL, dentry, FILE__WRITE); |
@@ -2756,7 +2707,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2756 | struct inode *inode = dentry->d_inode; | 2707 | struct inode *inode = dentry->d_inode; |
2757 | struct inode_security_struct *isec = inode->i_security; | 2708 | struct inode_security_struct *isec = inode->i_security; |
2758 | struct superblock_security_struct *sbsec; | 2709 | struct superblock_security_struct *sbsec; |
2759 | struct avc_audit_data ad; | 2710 | struct common_audit_data ad; |
2760 | u32 newsid, sid = current_sid(); | 2711 | u32 newsid, sid = current_sid(); |
2761 | int rc = 0; | 2712 | int rc = 0; |
2762 | 2713 | ||
@@ -2770,7 +2721,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2770 | if (!is_owner_or_cap(inode)) | 2721 | if (!is_owner_or_cap(inode)) |
2771 | return -EPERM; | 2722 | return -EPERM; |
2772 | 2723 | ||
2773 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2724 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2774 | ad.u.fs.path.dentry = dentry; | 2725 | ad.u.fs.path.dentry = dentry; |
2775 | 2726 | ||
2776 | rc = avc_has_perm(sid, isec->sid, isec->sclass, | 2727 | rc = avc_has_perm(sid, isec->sid, isec->sclass, |
@@ -2915,6 +2866,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name, | |||
2915 | return rc; | 2866 | return rc; |
2916 | 2867 | ||
2917 | isec->sid = newsid; | 2868 | isec->sid = newsid; |
2869 | isec->initialized = 1; | ||
2918 | return 0; | 2870 | return 0; |
2919 | } | 2871 | } |
2920 | 2872 | ||
@@ -2939,11 +2891,6 @@ static int selinux_revalidate_file_permission(struct file *file, int mask) | |||
2939 | const struct cred *cred = current_cred(); | 2891 | const struct cred *cred = current_cred(); |
2940 | struct inode *inode = file->f_path.dentry->d_inode; | 2892 | struct inode *inode = file->f_path.dentry->d_inode; |
2941 | 2893 | ||
2942 | if (!mask) { | ||
2943 | /* No permission to check. Existence test. */ | ||
2944 | return 0; | ||
2945 | } | ||
2946 | |||
2947 | /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */ | 2894 | /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */ |
2948 | if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) | 2895 | if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) |
2949 | mask |= MAY_APPEND; | 2896 | mask |= MAY_APPEND; |
@@ -2954,10 +2901,20 @@ static int selinux_revalidate_file_permission(struct file *file, int mask) | |||
2954 | 2901 | ||
2955 | static int selinux_file_permission(struct file *file, int mask) | 2902 | static int selinux_file_permission(struct file *file, int mask) |
2956 | { | 2903 | { |
2904 | struct inode *inode = file->f_path.dentry->d_inode; | ||
2905 | struct file_security_struct *fsec = file->f_security; | ||
2906 | struct inode_security_struct *isec = inode->i_security; | ||
2907 | u32 sid = current_sid(); | ||
2908 | |||
2957 | if (!mask) | 2909 | if (!mask) |
2958 | /* No permission to check. Existence test. */ | 2910 | /* No permission to check. Existence test. */ |
2959 | return 0; | 2911 | return 0; |
2960 | 2912 | ||
2913 | if (sid == fsec->sid && fsec->isid == isec->sid && | ||
2914 | fsec->pseqno == avc_policy_seqno()) | ||
2915 | /* No change since dentry_open check. */ | ||
2916 | return 0; | ||
2917 | |||
2961 | return selinux_revalidate_file_permission(file, mask); | 2918 | return selinux_revalidate_file_permission(file, mask); |
2962 | } | 2919 | } |
2963 | 2920 | ||
@@ -2987,13 +2944,15 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd, | |||
2987 | return file_has_perm(cred, file, av); | 2944 | return file_has_perm(cred, file, av); |
2988 | } | 2945 | } |
2989 | 2946 | ||
2947 | static int default_noexec; | ||
2948 | |||
2990 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) | 2949 | static int file_map_prot_check(struct file *file, unsigned long prot, int shared) |
2991 | { | 2950 | { |
2992 | const struct cred *cred = current_cred(); | 2951 | const struct cred *cred = current_cred(); |
2993 | int rc = 0; | 2952 | int rc = 0; |
2994 | 2953 | ||
2995 | #ifndef CONFIG_PPC32 | 2954 | if (default_noexec && |
2996 | if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { | 2955 | (prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) { |
2997 | /* | 2956 | /* |
2998 | * We are making executable an anonymous mapping or a | 2957 | * We are making executable an anonymous mapping or a |
2999 | * private file mapping that will also be writable. | 2958 | * private file mapping that will also be writable. |
@@ -3003,7 +2962,6 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared | |||
3003 | if (rc) | 2962 | if (rc) |
3004 | goto error; | 2963 | goto error; |
3005 | } | 2964 | } |
3006 | #endif | ||
3007 | 2965 | ||
3008 | if (file) { | 2966 | if (file) { |
3009 | /* read access is always possible with a mapping */ | 2967 | /* read access is always possible with a mapping */ |
@@ -3064,8 +3022,8 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
3064 | if (selinux_checkreqprot) | 3022 | if (selinux_checkreqprot) |
3065 | prot = reqprot; | 3023 | prot = reqprot; |
3066 | 3024 | ||
3067 | #ifndef CONFIG_PPC32 | 3025 | if (default_noexec && |
3068 | if ((prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { | 3026 | (prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) { |
3069 | int rc = 0; | 3027 | int rc = 0; |
3070 | if (vma->vm_start >= vma->vm_mm->start_brk && | 3028 | if (vma->vm_start >= vma->vm_mm->start_brk && |
3071 | vma->vm_end <= vma->vm_mm->brk) { | 3029 | vma->vm_end <= vma->vm_mm->brk) { |
@@ -3087,7 +3045,6 @@ static int selinux_file_mprotect(struct vm_area_struct *vma, | |||
3087 | if (rc) | 3045 | if (rc) |
3088 | return rc; | 3046 | return rc; |
3089 | } | 3047 | } |
3090 | #endif | ||
3091 | 3048 | ||
3092 | return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); | 3049 | return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED); |
3093 | } | 3050 | } |
@@ -3220,12 +3177,29 @@ static int selinux_task_create(unsigned long clone_flags) | |||
3220 | } | 3177 | } |
3221 | 3178 | ||
3222 | /* | 3179 | /* |
3180 | * allocate the SELinux part of blank credentials | ||
3181 | */ | ||
3182 | static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp) | ||
3183 | { | ||
3184 | struct task_security_struct *tsec; | ||
3185 | |||
3186 | tsec = kzalloc(sizeof(struct task_security_struct), gfp); | ||
3187 | if (!tsec) | ||
3188 | return -ENOMEM; | ||
3189 | |||
3190 | cred->security = tsec; | ||
3191 | return 0; | ||
3192 | } | ||
3193 | |||
3194 | /* | ||
3223 | * detach and free the LSM part of a set of credentials | 3195 | * detach and free the LSM part of a set of credentials |
3224 | */ | 3196 | */ |
3225 | static void selinux_cred_free(struct cred *cred) | 3197 | static void selinux_cred_free(struct cred *cred) |
3226 | { | 3198 | { |
3227 | struct task_security_struct *tsec = cred->security; | 3199 | struct task_security_struct *tsec = cred->security; |
3228 | cred->security = NULL; | 3200 | |
3201 | BUG_ON((unsigned long) cred->security < PAGE_SIZE); | ||
3202 | cred->security = (void *) 0x7UL; | ||
3229 | kfree(tsec); | 3203 | kfree(tsec); |
3230 | } | 3204 | } |
3231 | 3205 | ||
@@ -3249,6 +3223,17 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old, | |||
3249 | } | 3223 | } |
3250 | 3224 | ||
3251 | /* | 3225 | /* |
3226 | * transfer the SELinux data to a blank set of creds | ||
3227 | */ | ||
3228 | static void selinux_cred_transfer(struct cred *new, const struct cred *old) | ||
3229 | { | ||
3230 | const struct task_security_struct *old_tsec = old->security; | ||
3231 | struct task_security_struct *tsec = new->security; | ||
3232 | |||
3233 | *tsec = *old_tsec; | ||
3234 | } | ||
3235 | |||
3236 | /* | ||
3252 | * set the security data for a kernel service | 3237 | * set the security data for a kernel service |
3253 | * - all the creation contexts are set to unlabelled | 3238 | * - all the creation contexts are set to unlabelled |
3254 | */ | 3239 | */ |
@@ -3289,7 +3274,21 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
3289 | 3274 | ||
3290 | if (ret == 0) | 3275 | if (ret == 0) |
3291 | tsec->create_sid = isec->sid; | 3276 | tsec->create_sid = isec->sid; |
3292 | return 0; | 3277 | return ret; |
3278 | } | ||
3279 | |||
3280 | static int selinux_kernel_module_request(char *kmod_name) | ||
3281 | { | ||
3282 | u32 sid; | ||
3283 | struct common_audit_data ad; | ||
3284 | |||
3285 | sid = task_sid(current); | ||
3286 | |||
3287 | COMMON_AUDIT_DATA_INIT(&ad, KMOD); | ||
3288 | ad.u.kmod_name = kmod_name; | ||
3289 | |||
3290 | return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM, | ||
3291 | SYSTEM__MODULE_REQUEST, &ad); | ||
3293 | } | 3292 | } |
3294 | 3293 | ||
3295 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) | 3294 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) |
@@ -3339,25 +3338,26 @@ static int selinux_task_getioprio(struct task_struct *p) | |||
3339 | return current_has_perm(p, PROCESS__GETSCHED); | 3338 | return current_has_perm(p, PROCESS__GETSCHED); |
3340 | } | 3339 | } |
3341 | 3340 | ||
3342 | static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim) | 3341 | static int selinux_task_setrlimit(struct task_struct *p, unsigned int resource, |
3342 | struct rlimit *new_rlim) | ||
3343 | { | 3343 | { |
3344 | struct rlimit *old_rlim = current->signal->rlim + resource; | 3344 | struct rlimit *old_rlim = p->signal->rlim + resource; |
3345 | 3345 | ||
3346 | /* Control the ability to change the hard limit (whether | 3346 | /* Control the ability to change the hard limit (whether |
3347 | lowering or raising it), so that the hard limit can | 3347 | lowering or raising it), so that the hard limit can |
3348 | later be used as a safe reset point for the soft limit | 3348 | later be used as a safe reset point for the soft limit |
3349 | upon context transitions. See selinux_bprm_committing_creds. */ | 3349 | upon context transitions. See selinux_bprm_committing_creds. */ |
3350 | if (old_rlim->rlim_max != new_rlim->rlim_max) | 3350 | if (old_rlim->rlim_max != new_rlim->rlim_max) |
3351 | return current_has_perm(current, PROCESS__SETRLIMIT); | 3351 | return current_has_perm(p, PROCESS__SETRLIMIT); |
3352 | 3352 | ||
3353 | return 0; | 3353 | return 0; |
3354 | } | 3354 | } |
3355 | 3355 | ||
3356 | static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp) | 3356 | static int selinux_task_setscheduler(struct task_struct *p) |
3357 | { | 3357 | { |
3358 | int rc; | 3358 | int rc; |
3359 | 3359 | ||
3360 | rc = cap_task_setscheduler(p, policy, lp); | 3360 | rc = cap_task_setscheduler(p); |
3361 | if (rc) | 3361 | if (rc) |
3362 | return rc; | 3362 | return rc; |
3363 | 3363 | ||
@@ -3409,7 +3409,7 @@ static void selinux_task_to_inode(struct task_struct *p, | |||
3409 | 3409 | ||
3410 | /* Returns error only if unable to parse addresses */ | 3410 | /* Returns error only if unable to parse addresses */ |
3411 | static int selinux_parse_skb_ipv4(struct sk_buff *skb, | 3411 | static int selinux_parse_skb_ipv4(struct sk_buff *skb, |
3412 | struct avc_audit_data *ad, u8 *proto) | 3412 | struct common_audit_data *ad, u8 *proto) |
3413 | { | 3413 | { |
3414 | int offset, ihlen, ret = -EINVAL; | 3414 | int offset, ihlen, ret = -EINVAL; |
3415 | struct iphdr _iph, *ih; | 3415 | struct iphdr _iph, *ih; |
@@ -3490,7 +3490,7 @@ out: | |||
3490 | 3490 | ||
3491 | /* Returns error only if unable to parse addresses */ | 3491 | /* Returns error only if unable to parse addresses */ |
3492 | static int selinux_parse_skb_ipv6(struct sk_buff *skb, | 3492 | static int selinux_parse_skb_ipv6(struct sk_buff *skb, |
3493 | struct avc_audit_data *ad, u8 *proto) | 3493 | struct common_audit_data *ad, u8 *proto) |
3494 | { | 3494 | { |
3495 | u8 nexthdr; | 3495 | u8 nexthdr; |
3496 | int ret = -EINVAL, offset; | 3496 | int ret = -EINVAL, offset; |
@@ -3561,7 +3561,7 @@ out: | |||
3561 | 3561 | ||
3562 | #endif /* IPV6 */ | 3562 | #endif /* IPV6 */ |
3563 | 3563 | ||
3564 | static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, | 3564 | static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad, |
3565 | char **_addrp, int src, u8 *proto) | 3565 | char **_addrp, int src, u8 *proto) |
3566 | { | 3566 | { |
3567 | char *addrp; | 3567 | char *addrp; |
@@ -3639,71 +3639,54 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) | |||
3639 | } | 3639 | } |
3640 | 3640 | ||
3641 | /* socket security operations */ | 3641 | /* socket security operations */ |
3642 | static int socket_has_perm(struct task_struct *task, struct socket *sock, | 3642 | |
3643 | u32 perms) | 3643 | static u32 socket_sockcreate_sid(const struct task_security_struct *tsec) |
3644 | { | 3644 | { |
3645 | struct inode_security_struct *isec; | 3645 | return tsec->sockcreate_sid ? : tsec->sid; |
3646 | struct avc_audit_data ad; | 3646 | } |
3647 | u32 sid; | ||
3648 | int err = 0; | ||
3649 | 3647 | ||
3650 | isec = SOCK_INODE(sock)->i_security; | 3648 | static int sock_has_perm(struct task_struct *task, struct sock *sk, u32 perms) |
3649 | { | ||
3650 | struct sk_security_struct *sksec = sk->sk_security; | ||
3651 | struct common_audit_data ad; | ||
3652 | u32 tsid = task_sid(task); | ||
3651 | 3653 | ||
3652 | if (isec->sid == SECINITSID_KERNEL) | 3654 | if (sksec->sid == SECINITSID_KERNEL) |
3653 | goto out; | 3655 | return 0; |
3654 | sid = task_sid(task); | ||
3655 | 3656 | ||
3656 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3657 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3657 | ad.u.net.sk = sock->sk; | 3658 | ad.u.net.sk = sk; |
3658 | err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | ||
3659 | 3659 | ||
3660 | out: | 3660 | return avc_has_perm(tsid, sksec->sid, sksec->sclass, perms, &ad); |
3661 | return err; | ||
3662 | } | 3661 | } |
3663 | 3662 | ||
3664 | static int selinux_socket_create(int family, int type, | 3663 | static int selinux_socket_create(int family, int type, |
3665 | int protocol, int kern) | 3664 | int protocol, int kern) |
3666 | { | 3665 | { |
3667 | const struct cred *cred = current_cred(); | 3666 | const struct task_security_struct *tsec = current_security(); |
3668 | const struct task_security_struct *tsec = cred->security; | 3667 | u32 newsid; |
3669 | u32 sid, newsid; | ||
3670 | u16 secclass; | 3668 | u16 secclass; |
3671 | int err = 0; | ||
3672 | 3669 | ||
3673 | if (kern) | 3670 | if (kern) |
3674 | goto out; | 3671 | return 0; |
3675 | |||
3676 | sid = tsec->sid; | ||
3677 | newsid = tsec->sockcreate_sid ?: sid; | ||
3678 | 3672 | ||
3673 | newsid = socket_sockcreate_sid(tsec); | ||
3679 | secclass = socket_type_to_security_class(family, type, protocol); | 3674 | secclass = socket_type_to_security_class(family, type, protocol); |
3680 | err = avc_has_perm(sid, newsid, secclass, SOCKET__CREATE, NULL); | 3675 | return avc_has_perm(tsec->sid, newsid, secclass, SOCKET__CREATE, NULL); |
3681 | |||
3682 | out: | ||
3683 | return err; | ||
3684 | } | 3676 | } |
3685 | 3677 | ||
3686 | static int selinux_socket_post_create(struct socket *sock, int family, | 3678 | static int selinux_socket_post_create(struct socket *sock, int family, |
3687 | int type, int protocol, int kern) | 3679 | int type, int protocol, int kern) |
3688 | { | 3680 | { |
3689 | const struct cred *cred = current_cred(); | 3681 | const struct task_security_struct *tsec = current_security(); |
3690 | const struct task_security_struct *tsec = cred->security; | 3682 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; |
3691 | struct inode_security_struct *isec; | ||
3692 | struct sk_security_struct *sksec; | 3683 | struct sk_security_struct *sksec; |
3693 | u32 sid, newsid; | ||
3694 | int err = 0; | 3684 | int err = 0; |
3695 | 3685 | ||
3696 | sid = tsec->sid; | ||
3697 | newsid = tsec->sockcreate_sid; | ||
3698 | |||
3699 | isec = SOCK_INODE(sock)->i_security; | ||
3700 | |||
3701 | if (kern) | 3686 | if (kern) |
3702 | isec->sid = SECINITSID_KERNEL; | 3687 | isec->sid = SECINITSID_KERNEL; |
3703 | else if (newsid) | ||
3704 | isec->sid = newsid; | ||
3705 | else | 3688 | else |
3706 | isec->sid = sid; | 3689 | isec->sid = socket_sockcreate_sid(tsec); |
3707 | 3690 | ||
3708 | isec->sclass = socket_type_to_security_class(family, type, protocol); | 3691 | isec->sclass = socket_type_to_security_class(family, type, protocol); |
3709 | isec->initialized = 1; | 3692 | isec->initialized = 1; |
@@ -3724,10 +3707,11 @@ static int selinux_socket_post_create(struct socket *sock, int family, | |||
3724 | 3707 | ||
3725 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) | 3708 | static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) |
3726 | { | 3709 | { |
3710 | struct sock *sk = sock->sk; | ||
3727 | u16 family; | 3711 | u16 family; |
3728 | int err; | 3712 | int err; |
3729 | 3713 | ||
3730 | err = socket_has_perm(current, sock, SOCKET__BIND); | 3714 | err = sock_has_perm(current, sk, SOCKET__BIND); |
3731 | if (err) | 3715 | if (err) |
3732 | goto out; | 3716 | goto out; |
3733 | 3717 | ||
@@ -3736,19 +3720,16 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3736 | * Multiple address binding for SCTP is not supported yet: we just | 3720 | * Multiple address binding for SCTP is not supported yet: we just |
3737 | * check the first address now. | 3721 | * check the first address now. |
3738 | */ | 3722 | */ |
3739 | family = sock->sk->sk_family; | 3723 | family = sk->sk_family; |
3740 | if (family == PF_INET || family == PF_INET6) { | 3724 | if (family == PF_INET || family == PF_INET6) { |
3741 | char *addrp; | 3725 | char *addrp; |
3742 | struct inode_security_struct *isec; | 3726 | struct sk_security_struct *sksec = sk->sk_security; |
3743 | struct avc_audit_data ad; | 3727 | struct common_audit_data ad; |
3744 | struct sockaddr_in *addr4 = NULL; | 3728 | struct sockaddr_in *addr4 = NULL; |
3745 | struct sockaddr_in6 *addr6 = NULL; | 3729 | struct sockaddr_in6 *addr6 = NULL; |
3746 | unsigned short snum; | 3730 | unsigned short snum; |
3747 | struct sock *sk = sock->sk; | ||
3748 | u32 sid, node_perm; | 3731 | u32 sid, node_perm; |
3749 | 3732 | ||
3750 | isec = SOCK_INODE(sock)->i_security; | ||
3751 | |||
3752 | if (family == PF_INET) { | 3733 | if (family == PF_INET) { |
3753 | addr4 = (struct sockaddr_in *)address; | 3734 | addr4 = (struct sockaddr_in *)address; |
3754 | snum = ntohs(addr4->sin_port); | 3735 | snum = ntohs(addr4->sin_port); |
@@ -3769,18 +3750,18 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3769 | snum, &sid); | 3750 | snum, &sid); |
3770 | if (err) | 3751 | if (err) |
3771 | goto out; | 3752 | goto out; |
3772 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3753 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3773 | ad.u.net.sport = htons(snum); | 3754 | ad.u.net.sport = htons(snum); |
3774 | ad.u.net.family = family; | 3755 | ad.u.net.family = family; |
3775 | err = avc_has_perm(isec->sid, sid, | 3756 | err = avc_has_perm(sksec->sid, sid, |
3776 | isec->sclass, | 3757 | sksec->sclass, |
3777 | SOCKET__NAME_BIND, &ad); | 3758 | SOCKET__NAME_BIND, &ad); |
3778 | if (err) | 3759 | if (err) |
3779 | goto out; | 3760 | goto out; |
3780 | } | 3761 | } |
3781 | } | 3762 | } |
3782 | 3763 | ||
3783 | switch (isec->sclass) { | 3764 | switch (sksec->sclass) { |
3784 | case SECCLASS_TCP_SOCKET: | 3765 | case SECCLASS_TCP_SOCKET: |
3785 | node_perm = TCP_SOCKET__NODE_BIND; | 3766 | node_perm = TCP_SOCKET__NODE_BIND; |
3786 | break; | 3767 | break; |
@@ -3802,7 +3783,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3802 | if (err) | 3783 | if (err) |
3803 | goto out; | 3784 | goto out; |
3804 | 3785 | ||
3805 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3786 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3806 | ad.u.net.sport = htons(snum); | 3787 | ad.u.net.sport = htons(snum); |
3807 | ad.u.net.family = family; | 3788 | ad.u.net.family = family; |
3808 | 3789 | ||
@@ -3811,8 +3792,8 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3811 | else | 3792 | else |
3812 | ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); | 3793 | ipv6_addr_copy(&ad.u.net.v6info.saddr, &addr6->sin6_addr); |
3813 | 3794 | ||
3814 | err = avc_has_perm(isec->sid, sid, | 3795 | err = avc_has_perm(sksec->sid, sid, |
3815 | isec->sclass, node_perm, &ad); | 3796 | sksec->sclass, node_perm, &ad); |
3816 | if (err) | 3797 | if (err) |
3817 | goto out; | 3798 | goto out; |
3818 | } | 3799 | } |
@@ -3823,20 +3804,19 @@ out: | |||
3823 | static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) | 3804 | static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) |
3824 | { | 3805 | { |
3825 | struct sock *sk = sock->sk; | 3806 | struct sock *sk = sock->sk; |
3826 | struct inode_security_struct *isec; | 3807 | struct sk_security_struct *sksec = sk->sk_security; |
3827 | int err; | 3808 | int err; |
3828 | 3809 | ||
3829 | err = socket_has_perm(current, sock, SOCKET__CONNECT); | 3810 | err = sock_has_perm(current, sk, SOCKET__CONNECT); |
3830 | if (err) | 3811 | if (err) |
3831 | return err; | 3812 | return err; |
3832 | 3813 | ||
3833 | /* | 3814 | /* |
3834 | * If a TCP or DCCP socket, check name_connect permission for the port. | 3815 | * If a TCP or DCCP socket, check name_connect permission for the port. |
3835 | */ | 3816 | */ |
3836 | isec = SOCK_INODE(sock)->i_security; | 3817 | if (sksec->sclass == SECCLASS_TCP_SOCKET || |
3837 | if (isec->sclass == SECCLASS_TCP_SOCKET || | 3818 | sksec->sclass == SECCLASS_DCCP_SOCKET) { |
3838 | isec->sclass == SECCLASS_DCCP_SOCKET) { | 3819 | struct common_audit_data ad; |
3839 | struct avc_audit_data ad; | ||
3840 | struct sockaddr_in *addr4 = NULL; | 3820 | struct sockaddr_in *addr4 = NULL; |
3841 | struct sockaddr_in6 *addr6 = NULL; | 3821 | struct sockaddr_in6 *addr6 = NULL; |
3842 | unsigned short snum; | 3822 | unsigned short snum; |
@@ -3858,13 +3838,13 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3858 | if (err) | 3838 | if (err) |
3859 | goto out; | 3839 | goto out; |
3860 | 3840 | ||
3861 | perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? | 3841 | perm = (sksec->sclass == SECCLASS_TCP_SOCKET) ? |
3862 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; | 3842 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; |
3863 | 3843 | ||
3864 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3844 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3865 | ad.u.net.dport = htons(snum); | 3845 | ad.u.net.dport = htons(snum); |
3866 | ad.u.net.family = sk->sk_family; | 3846 | ad.u.net.family = sk->sk_family; |
3867 | err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); | 3847 | err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad); |
3868 | if (err) | 3848 | if (err) |
3869 | goto out; | 3849 | goto out; |
3870 | } | 3850 | } |
@@ -3877,7 +3857,7 @@ out: | |||
3877 | 3857 | ||
3878 | static int selinux_socket_listen(struct socket *sock, int backlog) | 3858 | static int selinux_socket_listen(struct socket *sock, int backlog) |
3879 | { | 3859 | { |
3880 | return socket_has_perm(current, sock, SOCKET__LISTEN); | 3860 | return sock_has_perm(current, sock->sk, SOCKET__LISTEN); |
3881 | } | 3861 | } |
3882 | 3862 | ||
3883 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | 3863 | static int selinux_socket_accept(struct socket *sock, struct socket *newsock) |
@@ -3886,7 +3866,7 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
3886 | struct inode_security_struct *isec; | 3866 | struct inode_security_struct *isec; |
3887 | struct inode_security_struct *newisec; | 3867 | struct inode_security_struct *newisec; |
3888 | 3868 | ||
3889 | err = socket_has_perm(current, sock, SOCKET__ACCEPT); | 3869 | err = sock_has_perm(current, sock->sk, SOCKET__ACCEPT); |
3890 | if (err) | 3870 | if (err) |
3891 | return err; | 3871 | return err; |
3892 | 3872 | ||
@@ -3903,30 +3883,30 @@ static int selinux_socket_accept(struct socket *sock, struct socket *newsock) | |||
3903 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, | 3883 | static int selinux_socket_sendmsg(struct socket *sock, struct msghdr *msg, |
3904 | int size) | 3884 | int size) |
3905 | { | 3885 | { |
3906 | return socket_has_perm(current, sock, SOCKET__WRITE); | 3886 | return sock_has_perm(current, sock->sk, SOCKET__WRITE); |
3907 | } | 3887 | } |
3908 | 3888 | ||
3909 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, | 3889 | static int selinux_socket_recvmsg(struct socket *sock, struct msghdr *msg, |
3910 | int size, int flags) | 3890 | int size, int flags) |
3911 | { | 3891 | { |
3912 | return socket_has_perm(current, sock, SOCKET__READ); | 3892 | return sock_has_perm(current, sock->sk, SOCKET__READ); |
3913 | } | 3893 | } |
3914 | 3894 | ||
3915 | static int selinux_socket_getsockname(struct socket *sock) | 3895 | static int selinux_socket_getsockname(struct socket *sock) |
3916 | { | 3896 | { |
3917 | return socket_has_perm(current, sock, SOCKET__GETATTR); | 3897 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); |
3918 | } | 3898 | } |
3919 | 3899 | ||
3920 | static int selinux_socket_getpeername(struct socket *sock) | 3900 | static int selinux_socket_getpeername(struct socket *sock) |
3921 | { | 3901 | { |
3922 | return socket_has_perm(current, sock, SOCKET__GETATTR); | 3902 | return sock_has_perm(current, sock->sk, SOCKET__GETATTR); |
3923 | } | 3903 | } |
3924 | 3904 | ||
3925 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) | 3905 | static int selinux_socket_setsockopt(struct socket *sock, int level, int optname) |
3926 | { | 3906 | { |
3927 | int err; | 3907 | int err; |
3928 | 3908 | ||
3929 | err = socket_has_perm(current, sock, SOCKET__SETOPT); | 3909 | err = sock_has_perm(current, sock->sk, SOCKET__SETOPT); |
3930 | if (err) | 3910 | if (err) |
3931 | return err; | 3911 | return err; |
3932 | 3912 | ||
@@ -3936,73 +3916,63 @@ static int selinux_socket_setsockopt(struct socket *sock, int level, int optname | |||
3936 | static int selinux_socket_getsockopt(struct socket *sock, int level, | 3916 | static int selinux_socket_getsockopt(struct socket *sock, int level, |
3937 | int optname) | 3917 | int optname) |
3938 | { | 3918 | { |
3939 | return socket_has_perm(current, sock, SOCKET__GETOPT); | 3919 | return sock_has_perm(current, sock->sk, SOCKET__GETOPT); |
3940 | } | 3920 | } |
3941 | 3921 | ||
3942 | static int selinux_socket_shutdown(struct socket *sock, int how) | 3922 | static int selinux_socket_shutdown(struct socket *sock, int how) |
3943 | { | 3923 | { |
3944 | return socket_has_perm(current, sock, SOCKET__SHUTDOWN); | 3924 | return sock_has_perm(current, sock->sk, SOCKET__SHUTDOWN); |
3945 | } | 3925 | } |
3946 | 3926 | ||
3947 | static int selinux_socket_unix_stream_connect(struct socket *sock, | 3927 | static int selinux_socket_unix_stream_connect(struct sock *sock, |
3948 | struct socket *other, | 3928 | struct sock *other, |
3949 | struct sock *newsk) | 3929 | struct sock *newsk) |
3950 | { | 3930 | { |
3951 | struct sk_security_struct *ssec; | 3931 | struct sk_security_struct *sksec_sock = sock->sk_security; |
3952 | struct inode_security_struct *isec; | 3932 | struct sk_security_struct *sksec_other = other->sk_security; |
3953 | struct inode_security_struct *other_isec; | 3933 | struct sk_security_struct *sksec_new = newsk->sk_security; |
3954 | struct avc_audit_data ad; | 3934 | struct common_audit_data ad; |
3955 | int err; | 3935 | int err; |
3956 | 3936 | ||
3957 | isec = SOCK_INODE(sock)->i_security; | 3937 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3958 | other_isec = SOCK_INODE(other)->i_security; | 3938 | ad.u.net.sk = other; |
3959 | |||
3960 | AVC_AUDIT_DATA_INIT(&ad, NET); | ||
3961 | ad.u.net.sk = other->sk; | ||
3962 | 3939 | ||
3963 | err = avc_has_perm(isec->sid, other_isec->sid, | 3940 | err = avc_has_perm(sksec_sock->sid, sksec_other->sid, |
3964 | isec->sclass, | 3941 | sksec_other->sclass, |
3965 | UNIX_STREAM_SOCKET__CONNECTTO, &ad); | 3942 | UNIX_STREAM_SOCKET__CONNECTTO, &ad); |
3966 | if (err) | 3943 | if (err) |
3967 | return err; | 3944 | return err; |
3968 | 3945 | ||
3969 | /* connecting socket */ | ||
3970 | ssec = sock->sk->sk_security; | ||
3971 | ssec->peer_sid = other_isec->sid; | ||
3972 | |||
3973 | /* server child socket */ | 3946 | /* server child socket */ |
3974 | ssec = newsk->sk_security; | 3947 | sksec_new->peer_sid = sksec_sock->sid; |
3975 | ssec->peer_sid = isec->sid; | 3948 | err = security_sid_mls_copy(sksec_other->sid, sksec_sock->sid, |
3976 | err = security_sid_mls_copy(other_isec->sid, ssec->peer_sid, &ssec->sid); | 3949 | &sksec_new->sid); |
3950 | if (err) | ||
3951 | return err; | ||
3977 | 3952 | ||
3978 | return err; | 3953 | /* connecting socket */ |
3954 | sksec_sock->peer_sid = sksec_new->sid; | ||
3955 | |||
3956 | return 0; | ||
3979 | } | 3957 | } |
3980 | 3958 | ||
3981 | static int selinux_socket_unix_may_send(struct socket *sock, | 3959 | static int selinux_socket_unix_may_send(struct socket *sock, |
3982 | struct socket *other) | 3960 | struct socket *other) |
3983 | { | 3961 | { |
3984 | struct inode_security_struct *isec; | 3962 | struct sk_security_struct *ssec = sock->sk->sk_security; |
3985 | struct inode_security_struct *other_isec; | 3963 | struct sk_security_struct *osec = other->sk->sk_security; |
3986 | struct avc_audit_data ad; | 3964 | struct common_audit_data ad; |
3987 | int err; | ||
3988 | |||
3989 | isec = SOCK_INODE(sock)->i_security; | ||
3990 | other_isec = SOCK_INODE(other)->i_security; | ||
3991 | 3965 | ||
3992 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3966 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3993 | ad.u.net.sk = other->sk; | 3967 | ad.u.net.sk = other->sk; |
3994 | 3968 | ||
3995 | err = avc_has_perm(isec->sid, other_isec->sid, | 3969 | return avc_has_perm(ssec->sid, osec->sid, osec->sclass, SOCKET__SENDTO, |
3996 | isec->sclass, SOCKET__SENDTO, &ad); | 3970 | &ad); |
3997 | if (err) | ||
3998 | return err; | ||
3999 | |||
4000 | return 0; | ||
4001 | } | 3971 | } |
4002 | 3972 | ||
4003 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, | 3973 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, |
4004 | u32 peer_sid, | 3974 | u32 peer_sid, |
4005 | struct avc_audit_data *ad) | 3975 | struct common_audit_data *ad) |
4006 | { | 3976 | { |
4007 | int err; | 3977 | int err; |
4008 | u32 if_sid; | 3978 | u32 if_sid; |
@@ -4030,11 +4000,11 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, | |||
4030 | struct sk_security_struct *sksec = sk->sk_security; | 4000 | struct sk_security_struct *sksec = sk->sk_security; |
4031 | u32 peer_sid; | 4001 | u32 peer_sid; |
4032 | u32 sk_sid = sksec->sid; | 4002 | u32 sk_sid = sksec->sid; |
4033 | struct avc_audit_data ad; | 4003 | struct common_audit_data ad; |
4034 | char *addrp; | 4004 | char *addrp; |
4035 | 4005 | ||
4036 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4006 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4037 | ad.u.net.netif = skb->iif; | 4007 | ad.u.net.netif = skb->skb_iif; |
4038 | ad.u.net.family = family; | 4008 | ad.u.net.family = family; |
4039 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); | 4009 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); |
4040 | if (err) | 4010 | if (err) |
@@ -4071,7 +4041,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4071 | struct sk_security_struct *sksec = sk->sk_security; | 4041 | struct sk_security_struct *sksec = sk->sk_security; |
4072 | u16 family = sk->sk_family; | 4042 | u16 family = sk->sk_family; |
4073 | u32 sk_sid = sksec->sid; | 4043 | u32 sk_sid = sksec->sid; |
4074 | struct avc_audit_data ad; | 4044 | struct common_audit_data ad; |
4075 | char *addrp; | 4045 | char *addrp; |
4076 | u8 secmark_active; | 4046 | u8 secmark_active; |
4077 | u8 peerlbl_active; | 4047 | u8 peerlbl_active; |
@@ -4095,8 +4065,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4095 | if (!secmark_active && !peerlbl_active) | 4065 | if (!secmark_active && !peerlbl_active) |
4096 | return 0; | 4066 | return 0; |
4097 | 4067 | ||
4098 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4068 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4099 | ad.u.net.netif = skb->iif; | 4069 | ad.u.net.netif = skb->skb_iif; |
4100 | ad.u.net.family = family; | 4070 | ad.u.net.family = family; |
4101 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); | 4071 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); |
4102 | if (err) | 4072 | if (err) |
@@ -4108,7 +4078,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4108 | err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); | 4078 | err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); |
4109 | if (err) | 4079 | if (err) |
4110 | return err; | 4080 | return err; |
4111 | err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family, | 4081 | err = selinux_inet_sys_rcv_skb(skb->skb_iif, addrp, family, |
4112 | peer_sid, &ad); | 4082 | peer_sid, &ad); |
4113 | if (err) { | 4083 | if (err) { |
4114 | selinux_netlbl_err(skb, err, 0); | 4084 | selinux_netlbl_err(skb, err, 0); |
@@ -4136,26 +4106,18 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
4136 | int err = 0; | 4106 | int err = 0; |
4137 | char *scontext; | 4107 | char *scontext; |
4138 | u32 scontext_len; | 4108 | u32 scontext_len; |
4139 | struct sk_security_struct *ssec; | 4109 | struct sk_security_struct *sksec = sock->sk->sk_security; |
4140 | struct inode_security_struct *isec; | ||
4141 | u32 peer_sid = SECSID_NULL; | 4110 | u32 peer_sid = SECSID_NULL; |
4142 | 4111 | ||
4143 | isec = SOCK_INODE(sock)->i_security; | 4112 | if (sksec->sclass == SECCLASS_UNIX_STREAM_SOCKET || |
4144 | 4113 | sksec->sclass == SECCLASS_TCP_SOCKET) | |
4145 | if (isec->sclass == SECCLASS_UNIX_STREAM_SOCKET || | 4114 | peer_sid = sksec->peer_sid; |
4146 | isec->sclass == SECCLASS_TCP_SOCKET) { | 4115 | if (peer_sid == SECSID_NULL) |
4147 | ssec = sock->sk->sk_security; | 4116 | return -ENOPROTOOPT; |
4148 | peer_sid = ssec->peer_sid; | ||
4149 | } | ||
4150 | if (peer_sid == SECSID_NULL) { | ||
4151 | err = -ENOPROTOOPT; | ||
4152 | goto out; | ||
4153 | } | ||
4154 | 4117 | ||
4155 | err = security_sid_to_context(peer_sid, &scontext, &scontext_len); | 4118 | err = security_sid_to_context(peer_sid, &scontext, &scontext_len); |
4156 | |||
4157 | if (err) | 4119 | if (err) |
4158 | goto out; | 4120 | return err; |
4159 | 4121 | ||
4160 | if (scontext_len > len) { | 4122 | if (scontext_len > len) { |
4161 | err = -ERANGE; | 4123 | err = -ERANGE; |
@@ -4168,9 +4130,7 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op | |||
4168 | out_len: | 4130 | out_len: |
4169 | if (put_user(scontext_len, optlen)) | 4131 | if (put_user(scontext_len, optlen)) |
4170 | err = -EFAULT; | 4132 | err = -EFAULT; |
4171 | |||
4172 | kfree(scontext); | 4133 | kfree(scontext); |
4173 | out: | ||
4174 | return err; | 4134 | return err; |
4175 | } | 4135 | } |
4176 | 4136 | ||
@@ -4202,24 +4162,39 @@ out: | |||
4202 | 4162 | ||
4203 | static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) | 4163 | static int selinux_sk_alloc_security(struct sock *sk, int family, gfp_t priority) |
4204 | { | 4164 | { |
4205 | return sk_alloc_security(sk, family, priority); | 4165 | struct sk_security_struct *sksec; |
4166 | |||
4167 | sksec = kzalloc(sizeof(*sksec), priority); | ||
4168 | if (!sksec) | ||
4169 | return -ENOMEM; | ||
4170 | |||
4171 | sksec->peer_sid = SECINITSID_UNLABELED; | ||
4172 | sksec->sid = SECINITSID_UNLABELED; | ||
4173 | selinux_netlbl_sk_security_reset(sksec); | ||
4174 | sk->sk_security = sksec; | ||
4175 | |||
4176 | return 0; | ||
4206 | } | 4177 | } |
4207 | 4178 | ||
4208 | static void selinux_sk_free_security(struct sock *sk) | 4179 | static void selinux_sk_free_security(struct sock *sk) |
4209 | { | 4180 | { |
4210 | sk_free_security(sk); | 4181 | struct sk_security_struct *sksec = sk->sk_security; |
4182 | |||
4183 | sk->sk_security = NULL; | ||
4184 | selinux_netlbl_sk_security_free(sksec); | ||
4185 | kfree(sksec); | ||
4211 | } | 4186 | } |
4212 | 4187 | ||
4213 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) | 4188 | static void selinux_sk_clone_security(const struct sock *sk, struct sock *newsk) |
4214 | { | 4189 | { |
4215 | struct sk_security_struct *ssec = sk->sk_security; | 4190 | struct sk_security_struct *sksec = sk->sk_security; |
4216 | struct sk_security_struct *newssec = newsk->sk_security; | 4191 | struct sk_security_struct *newsksec = newsk->sk_security; |
4217 | 4192 | ||
4218 | newssec->sid = ssec->sid; | 4193 | newsksec->sid = sksec->sid; |
4219 | newssec->peer_sid = ssec->peer_sid; | 4194 | newsksec->peer_sid = sksec->peer_sid; |
4220 | newssec->sclass = ssec->sclass; | 4195 | newsksec->sclass = sksec->sclass; |
4221 | 4196 | ||
4222 | selinux_netlbl_sk_security_reset(newssec); | 4197 | selinux_netlbl_sk_security_reset(newsksec); |
4223 | } | 4198 | } |
4224 | 4199 | ||
4225 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) | 4200 | static void selinux_sk_getsecid(struct sock *sk, u32 *secid) |
@@ -4303,19 +4278,92 @@ static void selinux_inet_conn_established(struct sock *sk, struct sk_buff *skb) | |||
4303 | selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid); | 4278 | selinux_skb_peerlbl_sid(skb, family, &sksec->peer_sid); |
4304 | } | 4279 | } |
4305 | 4280 | ||
4281 | static int selinux_secmark_relabel_packet(u32 sid) | ||
4282 | { | ||
4283 | const struct task_security_struct *__tsec; | ||
4284 | u32 tsid; | ||
4285 | |||
4286 | __tsec = current_security(); | ||
4287 | tsid = __tsec->sid; | ||
4288 | |||
4289 | return avc_has_perm(tsid, sid, SECCLASS_PACKET, PACKET__RELABELTO, NULL); | ||
4290 | } | ||
4291 | |||
4292 | static void selinux_secmark_refcount_inc(void) | ||
4293 | { | ||
4294 | atomic_inc(&selinux_secmark_refcount); | ||
4295 | } | ||
4296 | |||
4297 | static void selinux_secmark_refcount_dec(void) | ||
4298 | { | ||
4299 | atomic_dec(&selinux_secmark_refcount); | ||
4300 | } | ||
4301 | |||
4306 | static void selinux_req_classify_flow(const struct request_sock *req, | 4302 | static void selinux_req_classify_flow(const struct request_sock *req, |
4307 | struct flowi *fl) | 4303 | struct flowi *fl) |
4308 | { | 4304 | { |
4309 | fl->secid = req->secid; | 4305 | fl->secid = req->secid; |
4310 | } | 4306 | } |
4311 | 4307 | ||
4308 | static int selinux_tun_dev_create(void) | ||
4309 | { | ||
4310 | u32 sid = current_sid(); | ||
4311 | |||
4312 | /* we aren't taking into account the "sockcreate" SID since the socket | ||
4313 | * that is being created here is not a socket in the traditional sense, | ||
4314 | * instead it is a private sock, accessible only to the kernel, and | ||
4315 | * representing a wide range of network traffic spanning multiple | ||
4316 | * connections unlike traditional sockets - check the TUN driver to | ||
4317 | * get a better understanding of why this socket is special */ | ||
4318 | |||
4319 | return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE, | ||
4320 | NULL); | ||
4321 | } | ||
4322 | |||
4323 | static void selinux_tun_dev_post_create(struct sock *sk) | ||
4324 | { | ||
4325 | struct sk_security_struct *sksec = sk->sk_security; | ||
4326 | |||
4327 | /* we don't currently perform any NetLabel based labeling here and it | ||
4328 | * isn't clear that we would want to do so anyway; while we could apply | ||
4329 | * labeling without the support of the TUN user the resulting labeled | ||
4330 | * traffic from the other end of the connection would almost certainly | ||
4331 | * cause confusion to the TUN user that had no idea network labeling | ||
4332 | * protocols were being used */ | ||
4333 | |||
4334 | /* see the comments in selinux_tun_dev_create() about why we don't use | ||
4335 | * the sockcreate SID here */ | ||
4336 | |||
4337 | sksec->sid = current_sid(); | ||
4338 | sksec->sclass = SECCLASS_TUN_SOCKET; | ||
4339 | } | ||
4340 | |||
4341 | static int selinux_tun_dev_attach(struct sock *sk) | ||
4342 | { | ||
4343 | struct sk_security_struct *sksec = sk->sk_security; | ||
4344 | u32 sid = current_sid(); | ||
4345 | int err; | ||
4346 | |||
4347 | err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET, | ||
4348 | TUN_SOCKET__RELABELFROM, NULL); | ||
4349 | if (err) | ||
4350 | return err; | ||
4351 | err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, | ||
4352 | TUN_SOCKET__RELABELTO, NULL); | ||
4353 | if (err) | ||
4354 | return err; | ||
4355 | |||
4356 | sksec->sid = sid; | ||
4357 | |||
4358 | return 0; | ||
4359 | } | ||
4360 | |||
4312 | static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | 4361 | static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) |
4313 | { | 4362 | { |
4314 | int err = 0; | 4363 | int err = 0; |
4315 | u32 perm; | 4364 | u32 perm; |
4316 | struct nlmsghdr *nlh; | 4365 | struct nlmsghdr *nlh; |
4317 | struct socket *sock = sk->sk_socket; | 4366 | struct sk_security_struct *sksec = sk->sk_security; |
4318 | struct inode_security_struct *isec = SOCK_INODE(sock)->i_security; | ||
4319 | 4367 | ||
4320 | if (skb->len < NLMSG_SPACE(0)) { | 4368 | if (skb->len < NLMSG_SPACE(0)) { |
4321 | err = -EINVAL; | 4369 | err = -EINVAL; |
@@ -4323,13 +4371,13 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
4323 | } | 4371 | } |
4324 | nlh = nlmsg_hdr(skb); | 4372 | nlh = nlmsg_hdr(skb); |
4325 | 4373 | ||
4326 | err = selinux_nlmsg_lookup(isec->sclass, nlh->nlmsg_type, &perm); | 4374 | err = selinux_nlmsg_lookup(sksec->sclass, nlh->nlmsg_type, &perm); |
4327 | if (err) { | 4375 | if (err) { |
4328 | if (err == -EINVAL) { | 4376 | if (err == -EINVAL) { |
4329 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, | 4377 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_SELINUX_ERR, |
4330 | "SELinux: unrecognized netlink message" | 4378 | "SELinux: unrecognized netlink message" |
4331 | " type=%hu for sclass=%hu\n", | 4379 | " type=%hu for sclass=%hu\n", |
4332 | nlh->nlmsg_type, isec->sclass); | 4380 | nlh->nlmsg_type, sksec->sclass); |
4333 | if (!selinux_enforcing || security_get_allow_unknown()) | 4381 | if (!selinux_enforcing || security_get_allow_unknown()) |
4334 | err = 0; | 4382 | err = 0; |
4335 | } | 4383 | } |
@@ -4340,7 +4388,7 @@ static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | |||
4340 | goto out; | 4388 | goto out; |
4341 | } | 4389 | } |
4342 | 4390 | ||
4343 | err = socket_has_perm(current, sock, perm); | 4391 | err = sock_has_perm(current, sk, perm); |
4344 | out: | 4392 | out: |
4345 | return err; | 4393 | return err; |
4346 | } | 4394 | } |
@@ -4353,7 +4401,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
4353 | int err; | 4401 | int err; |
4354 | char *addrp; | 4402 | char *addrp; |
4355 | u32 peer_sid; | 4403 | u32 peer_sid; |
4356 | struct avc_audit_data ad; | 4404 | struct common_audit_data ad; |
4357 | u8 secmark_active; | 4405 | u8 secmark_active; |
4358 | u8 netlbl_active; | 4406 | u8 netlbl_active; |
4359 | u8 peerlbl_active; | 4407 | u8 peerlbl_active; |
@@ -4370,7 +4418,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
4370 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) | 4418 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) |
4371 | return NF_DROP; | 4419 | return NF_DROP; |
4372 | 4420 | ||
4373 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4421 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4374 | ad.u.net.netif = ifindex; | 4422 | ad.u.net.netif = ifindex; |
4375 | ad.u.net.family = family; | 4423 | ad.u.net.family = family; |
4376 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) | 4424 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) |
@@ -4458,7 +4506,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4458 | { | 4506 | { |
4459 | struct sock *sk = skb->sk; | 4507 | struct sock *sk = skb->sk; |
4460 | struct sk_security_struct *sksec; | 4508 | struct sk_security_struct *sksec; |
4461 | struct avc_audit_data ad; | 4509 | struct common_audit_data ad; |
4462 | char *addrp; | 4510 | char *addrp; |
4463 | u8 proto; | 4511 | u8 proto; |
4464 | 4512 | ||
@@ -4466,7 +4514,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4466 | return NF_ACCEPT; | 4514 | return NF_ACCEPT; |
4467 | sksec = sk->sk_security; | 4515 | sksec = sk->sk_security; |
4468 | 4516 | ||
4469 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4517 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4470 | ad.u.net.netif = ifindex; | 4518 | ad.u.net.netif = ifindex; |
4471 | ad.u.net.family = family; | 4519 | ad.u.net.family = family; |
4472 | if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) | 4520 | if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) |
@@ -4475,11 +4523,11 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4475 | if (selinux_secmark_enabled()) | 4523 | if (selinux_secmark_enabled()) |
4476 | if (avc_has_perm(sksec->sid, skb->secmark, | 4524 | if (avc_has_perm(sksec->sid, skb->secmark, |
4477 | SECCLASS_PACKET, PACKET__SEND, &ad)) | 4525 | SECCLASS_PACKET, PACKET__SEND, &ad)) |
4478 | return NF_DROP; | 4526 | return NF_DROP_ERR(-ECONNREFUSED); |
4479 | 4527 | ||
4480 | if (selinux_policycap_netpeer) | 4528 | if (selinux_policycap_netpeer) |
4481 | if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) | 4529 | if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) |
4482 | return NF_DROP; | 4530 | return NF_DROP_ERR(-ECONNREFUSED); |
4483 | 4531 | ||
4484 | return NF_ACCEPT; | 4532 | return NF_ACCEPT; |
4485 | } | 4533 | } |
@@ -4490,7 +4538,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4490 | u32 secmark_perm; | 4538 | u32 secmark_perm; |
4491 | u32 peer_sid; | 4539 | u32 peer_sid; |
4492 | struct sock *sk; | 4540 | struct sock *sk; |
4493 | struct avc_audit_data ad; | 4541 | struct common_audit_data ad; |
4494 | char *addrp; | 4542 | char *addrp; |
4495 | u8 secmark_active; | 4543 | u8 secmark_active; |
4496 | u8 peerlbl_active; | 4544 | u8 peerlbl_active; |
@@ -4536,7 +4584,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4536 | secmark_perm = PACKET__SEND; | 4584 | secmark_perm = PACKET__SEND; |
4537 | break; | 4585 | break; |
4538 | default: | 4586 | default: |
4539 | return NF_DROP; | 4587 | return NF_DROP_ERR(-ECONNREFUSED); |
4540 | } | 4588 | } |
4541 | if (secmark_perm == PACKET__FORWARD_OUT) { | 4589 | if (secmark_perm == PACKET__FORWARD_OUT) { |
4542 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) | 4590 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) |
@@ -4549,7 +4597,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4549 | secmark_perm = PACKET__SEND; | 4597 | secmark_perm = PACKET__SEND; |
4550 | } | 4598 | } |
4551 | 4599 | ||
4552 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4600 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4553 | ad.u.net.netif = ifindex; | 4601 | ad.u.net.netif = ifindex; |
4554 | ad.u.net.family = family; | 4602 | ad.u.net.family = family; |
4555 | if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) | 4603 | if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) |
@@ -4558,7 +4606,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4558 | if (secmark_active) | 4606 | if (secmark_active) |
4559 | if (avc_has_perm(peer_sid, skb->secmark, | 4607 | if (avc_has_perm(peer_sid, skb->secmark, |
4560 | SECCLASS_PACKET, secmark_perm, &ad)) | 4608 | SECCLASS_PACKET, secmark_perm, &ad)) |
4561 | return NF_DROP; | 4609 | return NF_DROP_ERR(-ECONNREFUSED); |
4562 | 4610 | ||
4563 | if (peerlbl_active) { | 4611 | if (peerlbl_active) { |
4564 | u32 if_sid; | 4612 | u32 if_sid; |
@@ -4568,13 +4616,13 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4568 | return NF_DROP; | 4616 | return NF_DROP; |
4569 | if (avc_has_perm(peer_sid, if_sid, | 4617 | if (avc_has_perm(peer_sid, if_sid, |
4570 | SECCLASS_NETIF, NETIF__EGRESS, &ad)) | 4618 | SECCLASS_NETIF, NETIF__EGRESS, &ad)) |
4571 | return NF_DROP; | 4619 | return NF_DROP_ERR(-ECONNREFUSED); |
4572 | 4620 | ||
4573 | if (sel_netnode_sid(addrp, family, &node_sid)) | 4621 | if (sel_netnode_sid(addrp, family, &node_sid)) |
4574 | return NF_DROP; | 4622 | return NF_DROP; |
4575 | if (avc_has_perm(peer_sid, node_sid, | 4623 | if (avc_has_perm(peer_sid, node_sid, |
4576 | SECCLASS_NODE, NODE__SENDTO, &ad)) | 4624 | SECCLASS_NODE, NODE__SENDTO, &ad)) |
4577 | return NF_DROP; | 4625 | return NF_DROP_ERR(-ECONNREFUSED); |
4578 | } | 4626 | } |
4579 | 4627 | ||
4580 | return NF_ACCEPT; | 4628 | return NF_ACCEPT; |
@@ -4610,22 +4658,19 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) | |||
4610 | if (err) | 4658 | if (err) |
4611 | return err; | 4659 | return err; |
4612 | 4660 | ||
4613 | if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS) | 4661 | return selinux_nlmsg_perm(sk, skb); |
4614 | err = selinux_nlmsg_perm(sk, skb); | ||
4615 | |||
4616 | return err; | ||
4617 | } | 4662 | } |
4618 | 4663 | ||
4619 | static int selinux_netlink_recv(struct sk_buff *skb, int capability) | 4664 | static int selinux_netlink_recv(struct sk_buff *skb, int capability) |
4620 | { | 4665 | { |
4621 | int err; | 4666 | int err; |
4622 | struct avc_audit_data ad; | 4667 | struct common_audit_data ad; |
4623 | 4668 | ||
4624 | err = cap_netlink_recv(skb, capability); | 4669 | err = cap_netlink_recv(skb, capability); |
4625 | if (err) | 4670 | if (err) |
4626 | return err; | 4671 | return err; |
4627 | 4672 | ||
4628 | AVC_AUDIT_DATA_INIT(&ad, CAP); | 4673 | COMMON_AUDIT_DATA_INIT(&ad, CAP); |
4629 | ad.u.cap = capability; | 4674 | ad.u.cap = capability; |
4630 | 4675 | ||
4631 | return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid, | 4676 | return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid, |
@@ -4684,12 +4729,12 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, | |||
4684 | u32 perms) | 4729 | u32 perms) |
4685 | { | 4730 | { |
4686 | struct ipc_security_struct *isec; | 4731 | struct ipc_security_struct *isec; |
4687 | struct avc_audit_data ad; | 4732 | struct common_audit_data ad; |
4688 | u32 sid = current_sid(); | 4733 | u32 sid = current_sid(); |
4689 | 4734 | ||
4690 | isec = ipc_perms->security; | 4735 | isec = ipc_perms->security; |
4691 | 4736 | ||
4692 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4737 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4693 | ad.u.ipc_id = ipc_perms->key; | 4738 | ad.u.ipc_id = ipc_perms->key; |
4694 | 4739 | ||
4695 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | 4740 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); |
@@ -4709,7 +4754,7 @@ static void selinux_msg_msg_free_security(struct msg_msg *msg) | |||
4709 | static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | 4754 | static int selinux_msg_queue_alloc_security(struct msg_queue *msq) |
4710 | { | 4755 | { |
4711 | struct ipc_security_struct *isec; | 4756 | struct ipc_security_struct *isec; |
4712 | struct avc_audit_data ad; | 4757 | struct common_audit_data ad; |
4713 | u32 sid = current_sid(); | 4758 | u32 sid = current_sid(); |
4714 | int rc; | 4759 | int rc; |
4715 | 4760 | ||
@@ -4719,7 +4764,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | |||
4719 | 4764 | ||
4720 | isec = msq->q_perm.security; | 4765 | isec = msq->q_perm.security; |
4721 | 4766 | ||
4722 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4767 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4723 | ad.u.ipc_id = msq->q_perm.key; | 4768 | ad.u.ipc_id = msq->q_perm.key; |
4724 | 4769 | ||
4725 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4770 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
@@ -4739,12 +4784,12 @@ static void selinux_msg_queue_free_security(struct msg_queue *msq) | |||
4739 | static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) | 4784 | static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) |
4740 | { | 4785 | { |
4741 | struct ipc_security_struct *isec; | 4786 | struct ipc_security_struct *isec; |
4742 | struct avc_audit_data ad; | 4787 | struct common_audit_data ad; |
4743 | u32 sid = current_sid(); | 4788 | u32 sid = current_sid(); |
4744 | 4789 | ||
4745 | isec = msq->q_perm.security; | 4790 | isec = msq->q_perm.security; |
4746 | 4791 | ||
4747 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4792 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4748 | ad.u.ipc_id = msq->q_perm.key; | 4793 | ad.u.ipc_id = msq->q_perm.key; |
4749 | 4794 | ||
4750 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4795 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
@@ -4783,7 +4828,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | |||
4783 | { | 4828 | { |
4784 | struct ipc_security_struct *isec; | 4829 | struct ipc_security_struct *isec; |
4785 | struct msg_security_struct *msec; | 4830 | struct msg_security_struct *msec; |
4786 | struct avc_audit_data ad; | 4831 | struct common_audit_data ad; |
4787 | u32 sid = current_sid(); | 4832 | u32 sid = current_sid(); |
4788 | int rc; | 4833 | int rc; |
4789 | 4834 | ||
@@ -4804,7 +4849,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | |||
4804 | return rc; | 4849 | return rc; |
4805 | } | 4850 | } |
4806 | 4851 | ||
4807 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4852 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4808 | ad.u.ipc_id = msq->q_perm.key; | 4853 | ad.u.ipc_id = msq->q_perm.key; |
4809 | 4854 | ||
4810 | /* Can this process write to the queue? */ | 4855 | /* Can this process write to the queue? */ |
@@ -4828,14 +4873,14 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | |||
4828 | { | 4873 | { |
4829 | struct ipc_security_struct *isec; | 4874 | struct ipc_security_struct *isec; |
4830 | struct msg_security_struct *msec; | 4875 | struct msg_security_struct *msec; |
4831 | struct avc_audit_data ad; | 4876 | struct common_audit_data ad; |
4832 | u32 sid = task_sid(target); | 4877 | u32 sid = task_sid(target); |
4833 | int rc; | 4878 | int rc; |
4834 | 4879 | ||
4835 | isec = msq->q_perm.security; | 4880 | isec = msq->q_perm.security; |
4836 | msec = msg->security; | 4881 | msec = msg->security; |
4837 | 4882 | ||
4838 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4883 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4839 | ad.u.ipc_id = msq->q_perm.key; | 4884 | ad.u.ipc_id = msq->q_perm.key; |
4840 | 4885 | ||
4841 | rc = avc_has_perm(sid, isec->sid, | 4886 | rc = avc_has_perm(sid, isec->sid, |
@@ -4850,7 +4895,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | |||
4850 | static int selinux_shm_alloc_security(struct shmid_kernel *shp) | 4895 | static int selinux_shm_alloc_security(struct shmid_kernel *shp) |
4851 | { | 4896 | { |
4852 | struct ipc_security_struct *isec; | 4897 | struct ipc_security_struct *isec; |
4853 | struct avc_audit_data ad; | 4898 | struct common_audit_data ad; |
4854 | u32 sid = current_sid(); | 4899 | u32 sid = current_sid(); |
4855 | int rc; | 4900 | int rc; |
4856 | 4901 | ||
@@ -4860,7 +4905,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) | |||
4860 | 4905 | ||
4861 | isec = shp->shm_perm.security; | 4906 | isec = shp->shm_perm.security; |
4862 | 4907 | ||
4863 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4908 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4864 | ad.u.ipc_id = shp->shm_perm.key; | 4909 | ad.u.ipc_id = shp->shm_perm.key; |
4865 | 4910 | ||
4866 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 4911 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
@@ -4880,12 +4925,12 @@ static void selinux_shm_free_security(struct shmid_kernel *shp) | |||
4880 | static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) | 4925 | static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) |
4881 | { | 4926 | { |
4882 | struct ipc_security_struct *isec; | 4927 | struct ipc_security_struct *isec; |
4883 | struct avc_audit_data ad; | 4928 | struct common_audit_data ad; |
4884 | u32 sid = current_sid(); | 4929 | u32 sid = current_sid(); |
4885 | 4930 | ||
4886 | isec = shp->shm_perm.security; | 4931 | isec = shp->shm_perm.security; |
4887 | 4932 | ||
4888 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4933 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4889 | ad.u.ipc_id = shp->shm_perm.key; | 4934 | ad.u.ipc_id = shp->shm_perm.key; |
4890 | 4935 | ||
4891 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 4936 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
@@ -4942,7 +4987,7 @@ static int selinux_shm_shmat(struct shmid_kernel *shp, | |||
4942 | static int selinux_sem_alloc_security(struct sem_array *sma) | 4987 | static int selinux_sem_alloc_security(struct sem_array *sma) |
4943 | { | 4988 | { |
4944 | struct ipc_security_struct *isec; | 4989 | struct ipc_security_struct *isec; |
4945 | struct avc_audit_data ad; | 4990 | struct common_audit_data ad; |
4946 | u32 sid = current_sid(); | 4991 | u32 sid = current_sid(); |
4947 | int rc; | 4992 | int rc; |
4948 | 4993 | ||
@@ -4952,7 +4997,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma) | |||
4952 | 4997 | ||
4953 | isec = sma->sem_perm.security; | 4998 | isec = sma->sem_perm.security; |
4954 | 4999 | ||
4955 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 5000 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4956 | ad.u.ipc_id = sma->sem_perm.key; | 5001 | ad.u.ipc_id = sma->sem_perm.key; |
4957 | 5002 | ||
4958 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 5003 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
@@ -4972,12 +5017,12 @@ static void selinux_sem_free_security(struct sem_array *sma) | |||
4972 | static int selinux_sem_associate(struct sem_array *sma, int semflg) | 5017 | static int selinux_sem_associate(struct sem_array *sma, int semflg) |
4973 | { | 5018 | { |
4974 | struct ipc_security_struct *isec; | 5019 | struct ipc_security_struct *isec; |
4975 | struct avc_audit_data ad; | 5020 | struct common_audit_data ad; |
4976 | u32 sid = current_sid(); | 5021 | u32 sid = current_sid(); |
4977 | 5022 | ||
4978 | isec = sma->sem_perm.security; | 5023 | isec = sma->sem_perm.security; |
4979 | 5024 | ||
4980 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 5025 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4981 | ad.u.ipc_id = sma->sem_perm.key; | 5026 | ad.u.ipc_id = sma->sem_perm.key; |
4982 | 5027 | ||
4983 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 5028 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
@@ -5195,7 +5240,7 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5195 | 5240 | ||
5196 | /* Only allow single threaded processes to change context */ | 5241 | /* Only allow single threaded processes to change context */ |
5197 | error = -EPERM; | 5242 | error = -EPERM; |
5198 | if (!is_single_threaded(p)) { | 5243 | if (!current_is_single_threaded()) { |
5199 | error = security_bounded_transition(tsec->sid, sid); | 5244 | error = security_bounded_transition(tsec->sid, sid); |
5200 | if (error) | 5245 | if (error) |
5201 | goto abort_change; | 5246 | goto abort_change; |
@@ -5252,6 +5297,32 @@ static void selinux_release_secctx(char *secdata, u32 seclen) | |||
5252 | kfree(secdata); | 5297 | kfree(secdata); |
5253 | } | 5298 | } |
5254 | 5299 | ||
5300 | /* | ||
5301 | * called with inode->i_mutex locked | ||
5302 | */ | ||
5303 | static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) | ||
5304 | { | ||
5305 | return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0); | ||
5306 | } | ||
5307 | |||
5308 | /* | ||
5309 | * called with inode->i_mutex locked | ||
5310 | */ | ||
5311 | static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) | ||
5312 | { | ||
5313 | return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0); | ||
5314 | } | ||
5315 | |||
5316 | static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | ||
5317 | { | ||
5318 | int len = 0; | ||
5319 | len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX, | ||
5320 | ctx, true); | ||
5321 | if (len < 0) | ||
5322 | return len; | ||
5323 | *ctxlen = len; | ||
5324 | return 0; | ||
5325 | } | ||
5255 | #ifdef CONFIG_KEYS | 5326 | #ifdef CONFIG_KEYS |
5256 | 5327 | ||
5257 | static int selinux_key_alloc(struct key *k, const struct cred *cred, | 5328 | static int selinux_key_alloc(struct key *k, const struct cred *cred, |
@@ -5323,7 +5394,7 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) | |||
5323 | static struct security_operations selinux_ops = { | 5394 | static struct security_operations selinux_ops = { |
5324 | .name = "selinux", | 5395 | .name = "selinux", |
5325 | 5396 | ||
5326 | .ptrace_may_access = selinux_ptrace_may_access, | 5397 | .ptrace_access_check = selinux_ptrace_access_check, |
5327 | .ptrace_traceme = selinux_ptrace_traceme, | 5398 | .ptrace_traceme = selinux_ptrace_traceme, |
5328 | .capget = selinux_capget, | 5399 | .capget = selinux_capget, |
5329 | .capset = selinux_capset, | 5400 | .capset = selinux_capset, |
@@ -5396,10 +5467,13 @@ static struct security_operations selinux_ops = { | |||
5396 | .dentry_open = selinux_dentry_open, | 5467 | .dentry_open = selinux_dentry_open, |
5397 | 5468 | ||
5398 | .task_create = selinux_task_create, | 5469 | .task_create = selinux_task_create, |
5470 | .cred_alloc_blank = selinux_cred_alloc_blank, | ||
5399 | .cred_free = selinux_cred_free, | 5471 | .cred_free = selinux_cred_free, |
5400 | .cred_prepare = selinux_cred_prepare, | 5472 | .cred_prepare = selinux_cred_prepare, |
5473 | .cred_transfer = selinux_cred_transfer, | ||
5401 | .kernel_act_as = selinux_kernel_act_as, | 5474 | .kernel_act_as = selinux_kernel_act_as, |
5402 | .kernel_create_files_as = selinux_kernel_create_files_as, | 5475 | .kernel_create_files_as = selinux_kernel_create_files_as, |
5476 | .kernel_module_request = selinux_kernel_module_request, | ||
5403 | .task_setpgid = selinux_task_setpgid, | 5477 | .task_setpgid = selinux_task_setpgid, |
5404 | .task_getpgid = selinux_task_getpgid, | 5478 | .task_getpgid = selinux_task_getpgid, |
5405 | .task_getsid = selinux_task_getsid, | 5479 | .task_getsid = selinux_task_getsid, |
@@ -5448,6 +5522,9 @@ static struct security_operations selinux_ops = { | |||
5448 | .secid_to_secctx = selinux_secid_to_secctx, | 5522 | .secid_to_secctx = selinux_secid_to_secctx, |
5449 | .secctx_to_secid = selinux_secctx_to_secid, | 5523 | .secctx_to_secid = selinux_secctx_to_secid, |
5450 | .release_secctx = selinux_release_secctx, | 5524 | .release_secctx = selinux_release_secctx, |
5525 | .inode_notifysecctx = selinux_inode_notifysecctx, | ||
5526 | .inode_setsecctx = selinux_inode_setsecctx, | ||
5527 | .inode_getsecctx = selinux_inode_getsecctx, | ||
5451 | 5528 | ||
5452 | .unix_stream_connect = selinux_socket_unix_stream_connect, | 5529 | .unix_stream_connect = selinux_socket_unix_stream_connect, |
5453 | .unix_may_send = selinux_socket_unix_may_send, | 5530 | .unix_may_send = selinux_socket_unix_may_send, |
@@ -5476,7 +5553,13 @@ static struct security_operations selinux_ops = { | |||
5476 | .inet_conn_request = selinux_inet_conn_request, | 5553 | .inet_conn_request = selinux_inet_conn_request, |
5477 | .inet_csk_clone = selinux_inet_csk_clone, | 5554 | .inet_csk_clone = selinux_inet_csk_clone, |
5478 | .inet_conn_established = selinux_inet_conn_established, | 5555 | .inet_conn_established = selinux_inet_conn_established, |
5556 | .secmark_relabel_packet = selinux_secmark_relabel_packet, | ||
5557 | .secmark_refcount_inc = selinux_secmark_refcount_inc, | ||
5558 | .secmark_refcount_dec = selinux_secmark_refcount_dec, | ||
5479 | .req_classify_flow = selinux_req_classify_flow, | 5559 | .req_classify_flow = selinux_req_classify_flow, |
5560 | .tun_dev_create = selinux_tun_dev_create, | ||
5561 | .tun_dev_post_create = selinux_tun_dev_post_create, | ||
5562 | .tun_dev_attach = selinux_tun_dev_attach, | ||
5480 | 5563 | ||
5481 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 5564 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
5482 | .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, | 5565 | .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, |
@@ -5523,14 +5606,13 @@ static __init int selinux_init(void) | |||
5523 | /* Set the security state for the initial task. */ | 5606 | /* Set the security state for the initial task. */ |
5524 | cred_init_security(); | 5607 | cred_init_security(); |
5525 | 5608 | ||
5609 | default_noexec = !(VM_DATA_DEFAULT_FLAGS & VM_EXEC); | ||
5610 | |||
5526 | sel_inode_cache = kmem_cache_create("selinux_inode_security", | 5611 | sel_inode_cache = kmem_cache_create("selinux_inode_security", |
5527 | sizeof(struct inode_security_struct), | 5612 | sizeof(struct inode_security_struct), |
5528 | 0, SLAB_PANIC, NULL); | 5613 | 0, SLAB_PANIC, NULL); |
5529 | avc_init(); | 5614 | avc_init(); |
5530 | 5615 | ||
5531 | secondary_ops = security_ops; | ||
5532 | if (!secondary_ops) | ||
5533 | panic("SELinux: No initial security operations\n"); | ||
5534 | if (register_security(&selinux_ops)) | 5616 | if (register_security(&selinux_ops)) |
5535 | panic("SELinux: Unable to register with kernel.\n"); | 5617 | panic("SELinux: Unable to register with kernel.\n"); |
5536 | 5618 | ||
@@ -5542,35 +5624,18 @@ static __init int selinux_init(void) | |||
5542 | return 0; | 5624 | return 0; |
5543 | } | 5625 | } |
5544 | 5626 | ||
5627 | static void delayed_superblock_init(struct super_block *sb, void *unused) | ||
5628 | { | ||
5629 | superblock_doinit(sb, NULL); | ||
5630 | } | ||
5631 | |||
5545 | void selinux_complete_init(void) | 5632 | void selinux_complete_init(void) |
5546 | { | 5633 | { |
5547 | printk(KERN_DEBUG "SELinux: Completing initialization.\n"); | 5634 | printk(KERN_DEBUG "SELinux: Completing initialization.\n"); |
5548 | 5635 | ||
5549 | /* Set up any superblocks initialized prior to the policy load. */ | 5636 | /* Set up any superblocks initialized prior to the policy load. */ |
5550 | printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n"); | 5637 | printk(KERN_DEBUG "SELinux: Setting up existing superblocks.\n"); |
5551 | spin_lock(&sb_lock); | 5638 | iterate_supers(delayed_superblock_init, NULL); |
5552 | spin_lock(&sb_security_lock); | ||
5553 | next_sb: | ||
5554 | if (!list_empty(&superblock_security_head)) { | ||
5555 | struct superblock_security_struct *sbsec = | ||
5556 | list_entry(superblock_security_head.next, | ||
5557 | struct superblock_security_struct, | ||
5558 | list); | ||
5559 | struct super_block *sb = sbsec->sb; | ||
5560 | sb->s_count++; | ||
5561 | spin_unlock(&sb_security_lock); | ||
5562 | spin_unlock(&sb_lock); | ||
5563 | down_read(&sb->s_umount); | ||
5564 | if (sb->s_root) | ||
5565 | superblock_doinit(sb, NULL); | ||
5566 | drop_super(sb); | ||
5567 | spin_lock(&sb_lock); | ||
5568 | spin_lock(&sb_security_lock); | ||
5569 | list_del_init(&sbsec->list); | ||
5570 | goto next_sb; | ||
5571 | } | ||
5572 | spin_unlock(&sb_security_lock); | ||
5573 | spin_unlock(&sb_lock); | ||
5574 | } | 5639 | } |
5575 | 5640 | ||
5576 | /* SELinux requires early initialization in order to label | 5641 | /* SELinux requires early initialization in order to label |
@@ -5691,8 +5756,10 @@ int selinux_disable(void) | |||
5691 | selinux_disabled = 1; | 5756 | selinux_disabled = 1; |
5692 | selinux_enabled = 0; | 5757 | selinux_enabled = 0; |
5693 | 5758 | ||
5694 | /* Reset security_ops to the secondary module, dummy or capability. */ | 5759 | reset_security_ops(); |
5695 | security_ops = secondary_ops; | 5760 | |
5761 | /* Try to destroy the avc node cache */ | ||
5762 | avc_disable(); | ||
5696 | 5763 | ||
5697 | /* Unregister netfilter hooks. */ | 5764 | /* Unregister netfilter hooks. */ |
5698 | selinux_nf_ip_exit(); | 5765 | selinux_nf_ip_exit(); |