diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 332 |
1 files changed, 243 insertions, 89 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 1e8cfc4c2ed6..417f7c994522 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 | * |
@@ -448,6 +448,10 @@ static int sb_finish_set_opts(struct super_block *sb) | |||
448 | sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) | 448 | sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) |
449 | sbsec->flags &= ~SE_SBLABELSUPP; | 449 | sbsec->flags &= ~SE_SBLABELSUPP; |
450 | 450 | ||
451 | /* Special handling for sysfs. Is genfs but also has setxattr handler*/ | ||
452 | if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0) | ||
453 | sbsec->flags |= SE_SBLABELSUPP; | ||
454 | |||
451 | /* Initialize the root inode. */ | 455 | /* Initialize the root inode. */ |
452 | rc = inode_doinit_with_dentry(root_inode, root); | 456 | rc = inode_doinit_with_dentry(root_inode, root); |
453 | 457 | ||
@@ -1479,14 +1483,14 @@ static int task_has_capability(struct task_struct *tsk, | |||
1479 | const struct cred *cred, | 1483 | const struct cred *cred, |
1480 | int cap, int audit) | 1484 | int cap, int audit) |
1481 | { | 1485 | { |
1482 | struct avc_audit_data ad; | 1486 | struct common_audit_data ad; |
1483 | struct av_decision avd; | 1487 | struct av_decision avd; |
1484 | u16 sclass; | 1488 | u16 sclass; |
1485 | u32 sid = cred_sid(cred); | 1489 | u32 sid = cred_sid(cred); |
1486 | u32 av = CAP_TO_MASK(cap); | 1490 | u32 av = CAP_TO_MASK(cap); |
1487 | int rc; | 1491 | int rc; |
1488 | 1492 | ||
1489 | AVC_AUDIT_DATA_INIT(&ad, CAP); | 1493 | COMMON_AUDIT_DATA_INIT(&ad, CAP); |
1490 | ad.tsk = tsk; | 1494 | ad.tsk = tsk; |
1491 | ad.u.cap = cap; | 1495 | ad.u.cap = cap; |
1492 | 1496 | ||
@@ -1525,12 +1529,14 @@ static int task_has_system(struct task_struct *tsk, | |||
1525 | static int inode_has_perm(const struct cred *cred, | 1529 | static int inode_has_perm(const struct cred *cred, |
1526 | struct inode *inode, | 1530 | struct inode *inode, |
1527 | u32 perms, | 1531 | u32 perms, |
1528 | struct avc_audit_data *adp) | 1532 | struct common_audit_data *adp) |
1529 | { | 1533 | { |
1530 | struct inode_security_struct *isec; | 1534 | struct inode_security_struct *isec; |
1531 | struct avc_audit_data ad; | 1535 | struct common_audit_data ad; |
1532 | u32 sid; | 1536 | u32 sid; |
1533 | 1537 | ||
1538 | validate_creds(cred); | ||
1539 | |||
1534 | if (unlikely(IS_PRIVATE(inode))) | 1540 | if (unlikely(IS_PRIVATE(inode))) |
1535 | return 0; | 1541 | return 0; |
1536 | 1542 | ||
@@ -1539,7 +1545,7 @@ static int inode_has_perm(const struct cred *cred, | |||
1539 | 1545 | ||
1540 | if (!adp) { | 1546 | if (!adp) { |
1541 | adp = &ad; | 1547 | adp = &ad; |
1542 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1548 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1543 | ad.u.fs.inode = inode; | 1549 | ad.u.fs.inode = inode; |
1544 | } | 1550 | } |
1545 | 1551 | ||
@@ -1555,9 +1561,9 @@ static inline int dentry_has_perm(const struct cred *cred, | |||
1555 | u32 av) | 1561 | u32 av) |
1556 | { | 1562 | { |
1557 | struct inode *inode = dentry->d_inode; | 1563 | struct inode *inode = dentry->d_inode; |
1558 | struct avc_audit_data ad; | 1564 | struct common_audit_data ad; |
1559 | 1565 | ||
1560 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1566 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1561 | ad.u.fs.path.mnt = mnt; | 1567 | ad.u.fs.path.mnt = mnt; |
1562 | ad.u.fs.path.dentry = dentry; | 1568 | ad.u.fs.path.dentry = dentry; |
1563 | return inode_has_perm(cred, inode, av, &ad); | 1569 | return inode_has_perm(cred, inode, av, &ad); |
@@ -1577,11 +1583,11 @@ static int file_has_perm(const struct cred *cred, | |||
1577 | { | 1583 | { |
1578 | struct file_security_struct *fsec = file->f_security; | 1584 | struct file_security_struct *fsec = file->f_security; |
1579 | struct inode *inode = file->f_path.dentry->d_inode; | 1585 | struct inode *inode = file->f_path.dentry->d_inode; |
1580 | struct avc_audit_data ad; | 1586 | struct common_audit_data ad; |
1581 | u32 sid = cred_sid(cred); | 1587 | u32 sid = cred_sid(cred); |
1582 | int rc; | 1588 | int rc; |
1583 | 1589 | ||
1584 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1590 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1585 | ad.u.fs.path = file->f_path; | 1591 | ad.u.fs.path = file->f_path; |
1586 | 1592 | ||
1587 | if (sid != fsec->sid) { | 1593 | if (sid != fsec->sid) { |
@@ -1612,7 +1618,7 @@ static int may_create(struct inode *dir, | |||
1612 | struct inode_security_struct *dsec; | 1618 | struct inode_security_struct *dsec; |
1613 | struct superblock_security_struct *sbsec; | 1619 | struct superblock_security_struct *sbsec; |
1614 | u32 sid, newsid; | 1620 | u32 sid, newsid; |
1615 | struct avc_audit_data ad; | 1621 | struct common_audit_data ad; |
1616 | int rc; | 1622 | int rc; |
1617 | 1623 | ||
1618 | dsec = dir->i_security; | 1624 | dsec = dir->i_security; |
@@ -1621,7 +1627,7 @@ static int may_create(struct inode *dir, | |||
1621 | sid = tsec->sid; | 1627 | sid = tsec->sid; |
1622 | newsid = tsec->create_sid; | 1628 | newsid = tsec->create_sid; |
1623 | 1629 | ||
1624 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1630 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1625 | ad.u.fs.path.dentry = dentry; | 1631 | ad.u.fs.path.dentry = dentry; |
1626 | 1632 | ||
1627 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, | 1633 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, |
@@ -1665,7 +1671,7 @@ static int may_link(struct inode *dir, | |||
1665 | 1671 | ||
1666 | { | 1672 | { |
1667 | struct inode_security_struct *dsec, *isec; | 1673 | struct inode_security_struct *dsec, *isec; |
1668 | struct avc_audit_data ad; | 1674 | struct common_audit_data ad; |
1669 | u32 sid = current_sid(); | 1675 | u32 sid = current_sid(); |
1670 | u32 av; | 1676 | u32 av; |
1671 | int rc; | 1677 | int rc; |
@@ -1673,7 +1679,7 @@ static int may_link(struct inode *dir, | |||
1673 | dsec = dir->i_security; | 1679 | dsec = dir->i_security; |
1674 | isec = dentry->d_inode->i_security; | 1680 | isec = dentry->d_inode->i_security; |
1675 | 1681 | ||
1676 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1682 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1677 | ad.u.fs.path.dentry = dentry; | 1683 | ad.u.fs.path.dentry = dentry; |
1678 | 1684 | ||
1679 | av = DIR__SEARCH; | 1685 | av = DIR__SEARCH; |
@@ -1708,7 +1714,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1708 | struct dentry *new_dentry) | 1714 | struct dentry *new_dentry) |
1709 | { | 1715 | { |
1710 | struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; | 1716 | struct inode_security_struct *old_dsec, *new_dsec, *old_isec, *new_isec; |
1711 | struct avc_audit_data ad; | 1717 | struct common_audit_data ad; |
1712 | u32 sid = current_sid(); | 1718 | u32 sid = current_sid(); |
1713 | u32 av; | 1719 | u32 av; |
1714 | int old_is_dir, new_is_dir; | 1720 | int old_is_dir, new_is_dir; |
@@ -1719,7 +1725,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1719 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); | 1725 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); |
1720 | new_dsec = new_dir->i_security; | 1726 | new_dsec = new_dir->i_security; |
1721 | 1727 | ||
1722 | AVC_AUDIT_DATA_INIT(&ad, FS); | 1728 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
1723 | 1729 | ||
1724 | ad.u.fs.path.dentry = old_dentry; | 1730 | ad.u.fs.path.dentry = old_dentry; |
1725 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, | 1731 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, |
@@ -1761,7 +1767,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1761 | static int superblock_has_perm(const struct cred *cred, | 1767 | static int superblock_has_perm(const struct cred *cred, |
1762 | struct super_block *sb, | 1768 | struct super_block *sb, |
1763 | u32 perms, | 1769 | u32 perms, |
1764 | struct avc_audit_data *ad) | 1770 | struct common_audit_data *ad) |
1765 | { | 1771 | { |
1766 | struct superblock_security_struct *sbsec; | 1772 | struct superblock_security_struct *sbsec; |
1767 | u32 sid = cred_sid(cred); | 1773 | u32 sid = cred_sid(cred); |
@@ -1855,12 +1861,12 @@ static inline u32 open_file_to_av(struct file *file) | |||
1855 | 1861 | ||
1856 | /* Hook functions begin here. */ | 1862 | /* Hook functions begin here. */ |
1857 | 1863 | ||
1858 | static int selinux_ptrace_may_access(struct task_struct *child, | 1864 | static int selinux_ptrace_access_check(struct task_struct *child, |
1859 | unsigned int mode) | 1865 | unsigned int mode) |
1860 | { | 1866 | { |
1861 | int rc; | 1867 | int rc; |
1862 | 1868 | ||
1863 | rc = cap_ptrace_may_access(child, mode); | 1869 | rc = cap_ptrace_access_check(child, mode); |
1864 | if (rc) | 1870 | if (rc) |
1865 | return rc; | 1871 | return rc; |
1866 | 1872 | ||
@@ -2101,7 +2107,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2101 | const struct task_security_struct *old_tsec; | 2107 | const struct task_security_struct *old_tsec; |
2102 | struct task_security_struct *new_tsec; | 2108 | struct task_security_struct *new_tsec; |
2103 | struct inode_security_struct *isec; | 2109 | struct inode_security_struct *isec; |
2104 | struct avc_audit_data ad; | 2110 | struct common_audit_data ad; |
2105 | struct inode *inode = bprm->file->f_path.dentry->d_inode; | 2111 | struct inode *inode = bprm->file->f_path.dentry->d_inode; |
2106 | int rc; | 2112 | int rc; |
2107 | 2113 | ||
@@ -2139,7 +2145,7 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
2139 | return rc; | 2145 | return rc; |
2140 | } | 2146 | } |
2141 | 2147 | ||
2142 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2148 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2143 | ad.u.fs.path = bprm->file->f_path; | 2149 | ad.u.fs.path = bprm->file->f_path; |
2144 | 2150 | ||
2145 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) | 2151 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) |
@@ -2232,7 +2238,7 @@ extern struct dentry *selinux_null; | |||
2232 | static inline void flush_unauthorized_files(const struct cred *cred, | 2238 | static inline void flush_unauthorized_files(const struct cred *cred, |
2233 | struct files_struct *files) | 2239 | struct files_struct *files) |
2234 | { | 2240 | { |
2235 | struct avc_audit_data ad; | 2241 | struct common_audit_data ad; |
2236 | struct file *file, *devnull = NULL; | 2242 | struct file *file, *devnull = NULL; |
2237 | struct tty_struct *tty; | 2243 | struct tty_struct *tty; |
2238 | struct fdtable *fdt; | 2244 | struct fdtable *fdt; |
@@ -2266,7 +2272,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2266 | 2272 | ||
2267 | /* Revalidate access to inherited open files. */ | 2273 | /* Revalidate access to inherited open files. */ |
2268 | 2274 | ||
2269 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2275 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2270 | 2276 | ||
2271 | spin_lock(&files->file_lock); | 2277 | spin_lock(&files->file_lock); |
2272 | for (;;) { | 2278 | for (;;) { |
@@ -2515,7 +2521,7 @@ out: | |||
2515 | static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | 2521 | static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) |
2516 | { | 2522 | { |
2517 | const struct cred *cred = current_cred(); | 2523 | const struct cred *cred = current_cred(); |
2518 | struct avc_audit_data ad; | 2524 | struct common_audit_data ad; |
2519 | int rc; | 2525 | int rc; |
2520 | 2526 | ||
2521 | rc = superblock_doinit(sb, data); | 2527 | rc = superblock_doinit(sb, data); |
@@ -2526,7 +2532,7 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
2526 | if (flags & MS_KERNMOUNT) | 2532 | if (flags & MS_KERNMOUNT) |
2527 | return 0; | 2533 | return 0; |
2528 | 2534 | ||
2529 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2535 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2530 | ad.u.fs.path.dentry = sb->s_root; | 2536 | ad.u.fs.path.dentry = sb->s_root; |
2531 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); | 2537 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); |
2532 | } | 2538 | } |
@@ -2534,9 +2540,9 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
2534 | static int selinux_sb_statfs(struct dentry *dentry) | 2540 | static int selinux_sb_statfs(struct dentry *dentry) |
2535 | { | 2541 | { |
2536 | const struct cred *cred = current_cred(); | 2542 | const struct cred *cred = current_cred(); |
2537 | struct avc_audit_data ad; | 2543 | struct common_audit_data ad; |
2538 | 2544 | ||
2539 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2545 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2540 | ad.u.fs.path.dentry = dentry->d_sb->s_root; | 2546 | ad.u.fs.path.dentry = dentry->d_sb->s_root; |
2541 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); | 2547 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); |
2542 | } | 2548 | } |
@@ -2711,12 +2717,18 @@ static int selinux_inode_permission(struct inode *inode, int mask) | |||
2711 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | 2717 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) |
2712 | { | 2718 | { |
2713 | const struct cred *cred = current_cred(); | 2719 | const struct cred *cred = current_cred(); |
2720 | unsigned int ia_valid = iattr->ia_valid; | ||
2721 | |||
2722 | /* ATTR_FORCE is just used for ATTR_KILL_S[UG]ID. */ | ||
2723 | if (ia_valid & ATTR_FORCE) { | ||
2724 | ia_valid &= ~(ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_MODE | | ||
2725 | ATTR_FORCE); | ||
2726 | if (!ia_valid) | ||
2727 | return 0; | ||
2728 | } | ||
2714 | 2729 | ||
2715 | if (iattr->ia_valid & ATTR_FORCE) | 2730 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | |
2716 | return 0; | 2731 | 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); | 2732 | return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR); |
2721 | 2733 | ||
2722 | return dentry_has_perm(cred, NULL, dentry, FILE__WRITE); | 2734 | return dentry_has_perm(cred, NULL, dentry, FILE__WRITE); |
@@ -2756,7 +2768,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2756 | struct inode *inode = dentry->d_inode; | 2768 | struct inode *inode = dentry->d_inode; |
2757 | struct inode_security_struct *isec = inode->i_security; | 2769 | struct inode_security_struct *isec = inode->i_security; |
2758 | struct superblock_security_struct *sbsec; | 2770 | struct superblock_security_struct *sbsec; |
2759 | struct avc_audit_data ad; | 2771 | struct common_audit_data ad; |
2760 | u32 newsid, sid = current_sid(); | 2772 | u32 newsid, sid = current_sid(); |
2761 | int rc = 0; | 2773 | int rc = 0; |
2762 | 2774 | ||
@@ -2770,7 +2782,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2770 | if (!is_owner_or_cap(inode)) | 2782 | if (!is_owner_or_cap(inode)) |
2771 | return -EPERM; | 2783 | return -EPERM; |
2772 | 2784 | ||
2773 | AVC_AUDIT_DATA_INIT(&ad, FS); | 2785 | COMMON_AUDIT_DATA_INIT(&ad, FS); |
2774 | ad.u.fs.path.dentry = dentry; | 2786 | ad.u.fs.path.dentry = dentry; |
2775 | 2787 | ||
2776 | rc = avc_has_perm(sid, isec->sid, isec->sclass, | 2788 | rc = avc_has_perm(sid, isec->sid, isec->sclass, |
@@ -2915,6 +2927,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name, | |||
2915 | return rc; | 2927 | return rc; |
2916 | 2928 | ||
2917 | isec->sid = newsid; | 2929 | isec->sid = newsid; |
2930 | isec->initialized = 1; | ||
2918 | return 0; | 2931 | return 0; |
2919 | } | 2932 | } |
2920 | 2933 | ||
@@ -2939,11 +2952,6 @@ static int selinux_revalidate_file_permission(struct file *file, int mask) | |||
2939 | const struct cred *cred = current_cred(); | 2952 | const struct cred *cred = current_cred(); |
2940 | struct inode *inode = file->f_path.dentry->d_inode; | 2953 | struct inode *inode = file->f_path.dentry->d_inode; |
2941 | 2954 | ||
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 */ | 2955 | /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */ |
2948 | if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) | 2956 | if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) |
2949 | mask |= MAY_APPEND; | 2957 | mask |= MAY_APPEND; |
@@ -2954,10 +2962,20 @@ static int selinux_revalidate_file_permission(struct file *file, int mask) | |||
2954 | 2962 | ||
2955 | static int selinux_file_permission(struct file *file, int mask) | 2963 | static int selinux_file_permission(struct file *file, int mask) |
2956 | { | 2964 | { |
2965 | struct inode *inode = file->f_path.dentry->d_inode; | ||
2966 | struct file_security_struct *fsec = file->f_security; | ||
2967 | struct inode_security_struct *isec = inode->i_security; | ||
2968 | u32 sid = current_sid(); | ||
2969 | |||
2957 | if (!mask) | 2970 | if (!mask) |
2958 | /* No permission to check. Existence test. */ | 2971 | /* No permission to check. Existence test. */ |
2959 | return 0; | 2972 | return 0; |
2960 | 2973 | ||
2974 | if (sid == fsec->sid && fsec->isid == isec->sid && | ||
2975 | fsec->pseqno == avc_policy_seqno()) | ||
2976 | /* No change since dentry_open check. */ | ||
2977 | return 0; | ||
2978 | |||
2961 | return selinux_revalidate_file_permission(file, mask); | 2979 | return selinux_revalidate_file_permission(file, mask); |
2962 | } | 2980 | } |
2963 | 2981 | ||
@@ -3030,9 +3048,21 @@ static int selinux_file_mmap(struct file *file, unsigned long reqprot, | |||
3030 | int rc = 0; | 3048 | int rc = 0; |
3031 | u32 sid = current_sid(); | 3049 | u32 sid = current_sid(); |
3032 | 3050 | ||
3033 | if (addr < mmap_min_addr) | 3051 | /* |
3052 | * notice that we are intentionally putting the SELinux check before | ||
3053 | * the secondary cap_file_mmap check. This is such a likely attempt | ||
3054 | * at bad behaviour/exploit that we always want to get the AVC, even | ||
3055 | * if DAC would have also denied the operation. | ||
3056 | */ | ||
3057 | if (addr < CONFIG_LSM_MMAP_MIN_ADDR) { | ||
3034 | rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT, | 3058 | rc = avc_has_perm(sid, sid, SECCLASS_MEMPROTECT, |
3035 | MEMPROTECT__MMAP_ZERO, NULL); | 3059 | MEMPROTECT__MMAP_ZERO, NULL); |
3060 | if (rc) | ||
3061 | return rc; | ||
3062 | } | ||
3063 | |||
3064 | /* do DAC check on address space usage */ | ||
3065 | rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only); | ||
3036 | if (rc || addr_only) | 3066 | if (rc || addr_only) |
3037 | return rc; | 3067 | return rc; |
3038 | 3068 | ||
@@ -3208,12 +3238,29 @@ static int selinux_task_create(unsigned long clone_flags) | |||
3208 | } | 3238 | } |
3209 | 3239 | ||
3210 | /* | 3240 | /* |
3241 | * allocate the SELinux part of blank credentials | ||
3242 | */ | ||
3243 | static int selinux_cred_alloc_blank(struct cred *cred, gfp_t gfp) | ||
3244 | { | ||
3245 | struct task_security_struct *tsec; | ||
3246 | |||
3247 | tsec = kzalloc(sizeof(struct task_security_struct), gfp); | ||
3248 | if (!tsec) | ||
3249 | return -ENOMEM; | ||
3250 | |||
3251 | cred->security = tsec; | ||
3252 | return 0; | ||
3253 | } | ||
3254 | |||
3255 | /* | ||
3211 | * detach and free the LSM part of a set of credentials | 3256 | * detach and free the LSM part of a set of credentials |
3212 | */ | 3257 | */ |
3213 | static void selinux_cred_free(struct cred *cred) | 3258 | static void selinux_cred_free(struct cred *cred) |
3214 | { | 3259 | { |
3215 | struct task_security_struct *tsec = cred->security; | 3260 | struct task_security_struct *tsec = cred->security; |
3216 | cred->security = NULL; | 3261 | |
3262 | BUG_ON((unsigned long) cred->security < PAGE_SIZE); | ||
3263 | cred->security = (void *) 0x7UL; | ||
3217 | kfree(tsec); | 3264 | kfree(tsec); |
3218 | } | 3265 | } |
3219 | 3266 | ||
@@ -3237,6 +3284,17 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old, | |||
3237 | } | 3284 | } |
3238 | 3285 | ||
3239 | /* | 3286 | /* |
3287 | * transfer the SELinux data to a blank set of creds | ||
3288 | */ | ||
3289 | static void selinux_cred_transfer(struct cred *new, const struct cred *old) | ||
3290 | { | ||
3291 | const struct task_security_struct *old_tsec = old->security; | ||
3292 | struct task_security_struct *tsec = new->security; | ||
3293 | |||
3294 | *tsec = *old_tsec; | ||
3295 | } | ||
3296 | |||
3297 | /* | ||
3240 | * set the security data for a kernel service | 3298 | * set the security data for a kernel service |
3241 | * - all the creation contexts are set to unlabelled | 3299 | * - all the creation contexts are set to unlabelled |
3242 | */ | 3300 | */ |
@@ -3280,6 +3338,11 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
3280 | return 0; | 3338 | return 0; |
3281 | } | 3339 | } |
3282 | 3340 | ||
3341 | static int selinux_kernel_module_request(void) | ||
3342 | { | ||
3343 | return task_has_system(current, SYSTEM__MODULE_REQUEST); | ||
3344 | } | ||
3345 | |||
3283 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) | 3346 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) |
3284 | { | 3347 | { |
3285 | return current_has_perm(p, PROCESS__SETPGID); | 3348 | return current_has_perm(p, PROCESS__SETPGID); |
@@ -3397,7 +3460,7 @@ static void selinux_task_to_inode(struct task_struct *p, | |||
3397 | 3460 | ||
3398 | /* Returns error only if unable to parse addresses */ | 3461 | /* Returns error only if unable to parse addresses */ |
3399 | static int selinux_parse_skb_ipv4(struct sk_buff *skb, | 3462 | static int selinux_parse_skb_ipv4(struct sk_buff *skb, |
3400 | struct avc_audit_data *ad, u8 *proto) | 3463 | struct common_audit_data *ad, u8 *proto) |
3401 | { | 3464 | { |
3402 | int offset, ihlen, ret = -EINVAL; | 3465 | int offset, ihlen, ret = -EINVAL; |
3403 | struct iphdr _iph, *ih; | 3466 | struct iphdr _iph, *ih; |
@@ -3478,7 +3541,7 @@ out: | |||
3478 | 3541 | ||
3479 | /* Returns error only if unable to parse addresses */ | 3542 | /* Returns error only if unable to parse addresses */ |
3480 | static int selinux_parse_skb_ipv6(struct sk_buff *skb, | 3543 | static int selinux_parse_skb_ipv6(struct sk_buff *skb, |
3481 | struct avc_audit_data *ad, u8 *proto) | 3544 | struct common_audit_data *ad, u8 *proto) |
3482 | { | 3545 | { |
3483 | u8 nexthdr; | 3546 | u8 nexthdr; |
3484 | int ret = -EINVAL, offset; | 3547 | int ret = -EINVAL, offset; |
@@ -3549,7 +3612,7 @@ out: | |||
3549 | 3612 | ||
3550 | #endif /* IPV6 */ | 3613 | #endif /* IPV6 */ |
3551 | 3614 | ||
3552 | static int selinux_parse_skb(struct sk_buff *skb, struct avc_audit_data *ad, | 3615 | static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad, |
3553 | char **_addrp, int src, u8 *proto) | 3616 | char **_addrp, int src, u8 *proto) |
3554 | { | 3617 | { |
3555 | char *addrp; | 3618 | char *addrp; |
@@ -3631,7 +3694,7 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock, | |||
3631 | u32 perms) | 3694 | u32 perms) |
3632 | { | 3695 | { |
3633 | struct inode_security_struct *isec; | 3696 | struct inode_security_struct *isec; |
3634 | struct avc_audit_data ad; | 3697 | struct common_audit_data ad; |
3635 | u32 sid; | 3698 | u32 sid; |
3636 | int err = 0; | 3699 | int err = 0; |
3637 | 3700 | ||
@@ -3641,7 +3704,7 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock, | |||
3641 | goto out; | 3704 | goto out; |
3642 | sid = task_sid(task); | 3705 | sid = task_sid(task); |
3643 | 3706 | ||
3644 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3707 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3645 | ad.u.net.sk = sock->sk; | 3708 | ad.u.net.sk = sock->sk; |
3646 | err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | 3709 | err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); |
3647 | 3710 | ||
@@ -3728,7 +3791,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3728 | if (family == PF_INET || family == PF_INET6) { | 3791 | if (family == PF_INET || family == PF_INET6) { |
3729 | char *addrp; | 3792 | char *addrp; |
3730 | struct inode_security_struct *isec; | 3793 | struct inode_security_struct *isec; |
3731 | struct avc_audit_data ad; | 3794 | struct common_audit_data ad; |
3732 | struct sockaddr_in *addr4 = NULL; | 3795 | struct sockaddr_in *addr4 = NULL; |
3733 | struct sockaddr_in6 *addr6 = NULL; | 3796 | struct sockaddr_in6 *addr6 = NULL; |
3734 | unsigned short snum; | 3797 | unsigned short snum; |
@@ -3757,7 +3820,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3757 | snum, &sid); | 3820 | snum, &sid); |
3758 | if (err) | 3821 | if (err) |
3759 | goto out; | 3822 | goto out; |
3760 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3823 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3761 | ad.u.net.sport = htons(snum); | 3824 | ad.u.net.sport = htons(snum); |
3762 | ad.u.net.family = family; | 3825 | ad.u.net.family = family; |
3763 | err = avc_has_perm(isec->sid, sid, | 3826 | err = avc_has_perm(isec->sid, sid, |
@@ -3790,7 +3853,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3790 | if (err) | 3853 | if (err) |
3791 | goto out; | 3854 | goto out; |
3792 | 3855 | ||
3793 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3856 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3794 | ad.u.net.sport = htons(snum); | 3857 | ad.u.net.sport = htons(snum); |
3795 | ad.u.net.family = family; | 3858 | ad.u.net.family = family; |
3796 | 3859 | ||
@@ -3824,7 +3887,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3824 | isec = SOCK_INODE(sock)->i_security; | 3887 | isec = SOCK_INODE(sock)->i_security; |
3825 | if (isec->sclass == SECCLASS_TCP_SOCKET || | 3888 | if (isec->sclass == SECCLASS_TCP_SOCKET || |
3826 | isec->sclass == SECCLASS_DCCP_SOCKET) { | 3889 | isec->sclass == SECCLASS_DCCP_SOCKET) { |
3827 | struct avc_audit_data ad; | 3890 | struct common_audit_data ad; |
3828 | struct sockaddr_in *addr4 = NULL; | 3891 | struct sockaddr_in *addr4 = NULL; |
3829 | struct sockaddr_in6 *addr6 = NULL; | 3892 | struct sockaddr_in6 *addr6 = NULL; |
3830 | unsigned short snum; | 3893 | unsigned short snum; |
@@ -3849,7 +3912,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3849 | perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? | 3912 | perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? |
3850 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; | 3913 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; |
3851 | 3914 | ||
3852 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3915 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3853 | ad.u.net.dport = htons(snum); | 3916 | ad.u.net.dport = htons(snum); |
3854 | ad.u.net.family = sk->sk_family; | 3917 | ad.u.net.family = sk->sk_family; |
3855 | err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); | 3918 | err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); |
@@ -3939,13 +4002,13 @@ static int selinux_socket_unix_stream_connect(struct socket *sock, | |||
3939 | struct sk_security_struct *ssec; | 4002 | struct sk_security_struct *ssec; |
3940 | struct inode_security_struct *isec; | 4003 | struct inode_security_struct *isec; |
3941 | struct inode_security_struct *other_isec; | 4004 | struct inode_security_struct *other_isec; |
3942 | struct avc_audit_data ad; | 4005 | struct common_audit_data ad; |
3943 | int err; | 4006 | int err; |
3944 | 4007 | ||
3945 | isec = SOCK_INODE(sock)->i_security; | 4008 | isec = SOCK_INODE(sock)->i_security; |
3946 | other_isec = SOCK_INODE(other)->i_security; | 4009 | other_isec = SOCK_INODE(other)->i_security; |
3947 | 4010 | ||
3948 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4011 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3949 | ad.u.net.sk = other->sk; | 4012 | ad.u.net.sk = other->sk; |
3950 | 4013 | ||
3951 | err = avc_has_perm(isec->sid, other_isec->sid, | 4014 | err = avc_has_perm(isec->sid, other_isec->sid, |
@@ -3971,13 +4034,13 @@ static int selinux_socket_unix_may_send(struct socket *sock, | |||
3971 | { | 4034 | { |
3972 | struct inode_security_struct *isec; | 4035 | struct inode_security_struct *isec; |
3973 | struct inode_security_struct *other_isec; | 4036 | struct inode_security_struct *other_isec; |
3974 | struct avc_audit_data ad; | 4037 | struct common_audit_data ad; |
3975 | int err; | 4038 | int err; |
3976 | 4039 | ||
3977 | isec = SOCK_INODE(sock)->i_security; | 4040 | isec = SOCK_INODE(sock)->i_security; |
3978 | other_isec = SOCK_INODE(other)->i_security; | 4041 | other_isec = SOCK_INODE(other)->i_security; |
3979 | 4042 | ||
3980 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4043 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3981 | ad.u.net.sk = other->sk; | 4044 | ad.u.net.sk = other->sk; |
3982 | 4045 | ||
3983 | err = avc_has_perm(isec->sid, other_isec->sid, | 4046 | err = avc_has_perm(isec->sid, other_isec->sid, |
@@ -3990,7 +4053,7 @@ static int selinux_socket_unix_may_send(struct socket *sock, | |||
3990 | 4053 | ||
3991 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, | 4054 | static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family, |
3992 | u32 peer_sid, | 4055 | u32 peer_sid, |
3993 | struct avc_audit_data *ad) | 4056 | struct common_audit_data *ad) |
3994 | { | 4057 | { |
3995 | int err; | 4058 | int err; |
3996 | u32 if_sid; | 4059 | u32 if_sid; |
@@ -4018,10 +4081,10 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, | |||
4018 | struct sk_security_struct *sksec = sk->sk_security; | 4081 | struct sk_security_struct *sksec = sk->sk_security; |
4019 | u32 peer_sid; | 4082 | u32 peer_sid; |
4020 | u32 sk_sid = sksec->sid; | 4083 | u32 sk_sid = sksec->sid; |
4021 | struct avc_audit_data ad; | 4084 | struct common_audit_data ad; |
4022 | char *addrp; | 4085 | char *addrp; |
4023 | 4086 | ||
4024 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4087 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4025 | ad.u.net.netif = skb->iif; | 4088 | ad.u.net.netif = skb->iif; |
4026 | ad.u.net.family = family; | 4089 | ad.u.net.family = family; |
4027 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); | 4090 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); |
@@ -4059,7 +4122,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4059 | struct sk_security_struct *sksec = sk->sk_security; | 4122 | struct sk_security_struct *sksec = sk->sk_security; |
4060 | u16 family = sk->sk_family; | 4123 | u16 family = sk->sk_family; |
4061 | u32 sk_sid = sksec->sid; | 4124 | u32 sk_sid = sksec->sid; |
4062 | struct avc_audit_data ad; | 4125 | struct common_audit_data ad; |
4063 | char *addrp; | 4126 | char *addrp; |
4064 | u8 secmark_active; | 4127 | u8 secmark_active; |
4065 | u8 peerlbl_active; | 4128 | u8 peerlbl_active; |
@@ -4083,7 +4146,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4083 | if (!secmark_active && !peerlbl_active) | 4146 | if (!secmark_active && !peerlbl_active) |
4084 | return 0; | 4147 | return 0; |
4085 | 4148 | ||
4086 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4149 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4087 | ad.u.net.netif = skb->iif; | 4150 | ad.u.net.netif = skb->iif; |
4088 | ad.u.net.family = family; | 4151 | ad.u.net.family = family; |
4089 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); | 4152 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); |
@@ -4297,6 +4360,59 @@ static void selinux_req_classify_flow(const struct request_sock *req, | |||
4297 | fl->secid = req->secid; | 4360 | fl->secid = req->secid; |
4298 | } | 4361 | } |
4299 | 4362 | ||
4363 | static int selinux_tun_dev_create(void) | ||
4364 | { | ||
4365 | u32 sid = current_sid(); | ||
4366 | |||
4367 | /* we aren't taking into account the "sockcreate" SID since the socket | ||
4368 | * that is being created here is not a socket in the traditional sense, | ||
4369 | * instead it is a private sock, accessible only to the kernel, and | ||
4370 | * representing a wide range of network traffic spanning multiple | ||
4371 | * connections unlike traditional sockets - check the TUN driver to | ||
4372 | * get a better understanding of why this socket is special */ | ||
4373 | |||
4374 | return avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, TUN_SOCKET__CREATE, | ||
4375 | NULL); | ||
4376 | } | ||
4377 | |||
4378 | static void selinux_tun_dev_post_create(struct sock *sk) | ||
4379 | { | ||
4380 | struct sk_security_struct *sksec = sk->sk_security; | ||
4381 | |||
4382 | /* we don't currently perform any NetLabel based labeling here and it | ||
4383 | * isn't clear that we would want to do so anyway; while we could apply | ||
4384 | * labeling without the support of the TUN user the resulting labeled | ||
4385 | * traffic from the other end of the connection would almost certainly | ||
4386 | * cause confusion to the TUN user that had no idea network labeling | ||
4387 | * protocols were being used */ | ||
4388 | |||
4389 | /* see the comments in selinux_tun_dev_create() about why we don't use | ||
4390 | * the sockcreate SID here */ | ||
4391 | |||
4392 | sksec->sid = current_sid(); | ||
4393 | sksec->sclass = SECCLASS_TUN_SOCKET; | ||
4394 | } | ||
4395 | |||
4396 | static int selinux_tun_dev_attach(struct sock *sk) | ||
4397 | { | ||
4398 | struct sk_security_struct *sksec = sk->sk_security; | ||
4399 | u32 sid = current_sid(); | ||
4400 | int err; | ||
4401 | |||
4402 | err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET, | ||
4403 | TUN_SOCKET__RELABELFROM, NULL); | ||
4404 | if (err) | ||
4405 | return err; | ||
4406 | err = avc_has_perm(sid, sid, SECCLASS_TUN_SOCKET, | ||
4407 | TUN_SOCKET__RELABELTO, NULL); | ||
4408 | if (err) | ||
4409 | return err; | ||
4410 | |||
4411 | sksec->sid = sid; | ||
4412 | |||
4413 | return 0; | ||
4414 | } | ||
4415 | |||
4300 | static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) | 4416 | static int selinux_nlmsg_perm(struct sock *sk, struct sk_buff *skb) |
4301 | { | 4417 | { |
4302 | int err = 0; | 4418 | int err = 0; |
@@ -4341,7 +4457,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
4341 | int err; | 4457 | int err; |
4342 | char *addrp; | 4458 | char *addrp; |
4343 | u32 peer_sid; | 4459 | u32 peer_sid; |
4344 | struct avc_audit_data ad; | 4460 | struct common_audit_data ad; |
4345 | u8 secmark_active; | 4461 | u8 secmark_active; |
4346 | u8 netlbl_active; | 4462 | u8 netlbl_active; |
4347 | u8 peerlbl_active; | 4463 | u8 peerlbl_active; |
@@ -4358,7 +4474,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
4358 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) | 4474 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) |
4359 | return NF_DROP; | 4475 | return NF_DROP; |
4360 | 4476 | ||
4361 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4477 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4362 | ad.u.net.netif = ifindex; | 4478 | ad.u.net.netif = ifindex; |
4363 | ad.u.net.family = family; | 4479 | ad.u.net.family = family; |
4364 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) | 4480 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) |
@@ -4446,7 +4562,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4446 | { | 4562 | { |
4447 | struct sock *sk = skb->sk; | 4563 | struct sock *sk = skb->sk; |
4448 | struct sk_security_struct *sksec; | 4564 | struct sk_security_struct *sksec; |
4449 | struct avc_audit_data ad; | 4565 | struct common_audit_data ad; |
4450 | char *addrp; | 4566 | char *addrp; |
4451 | u8 proto; | 4567 | u8 proto; |
4452 | 4568 | ||
@@ -4454,7 +4570,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4454 | return NF_ACCEPT; | 4570 | return NF_ACCEPT; |
4455 | sksec = sk->sk_security; | 4571 | sksec = sk->sk_security; |
4456 | 4572 | ||
4457 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4573 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4458 | ad.u.net.netif = ifindex; | 4574 | ad.u.net.netif = ifindex; |
4459 | ad.u.net.family = family; | 4575 | ad.u.net.family = family; |
4460 | if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) | 4576 | if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) |
@@ -4478,7 +4594,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4478 | u32 secmark_perm; | 4594 | u32 secmark_perm; |
4479 | u32 peer_sid; | 4595 | u32 peer_sid; |
4480 | struct sock *sk; | 4596 | struct sock *sk; |
4481 | struct avc_audit_data ad; | 4597 | struct common_audit_data ad; |
4482 | char *addrp; | 4598 | char *addrp; |
4483 | u8 secmark_active; | 4599 | u8 secmark_active; |
4484 | u8 peerlbl_active; | 4600 | u8 peerlbl_active; |
@@ -4537,7 +4653,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4537 | secmark_perm = PACKET__SEND; | 4653 | secmark_perm = PACKET__SEND; |
4538 | } | 4654 | } |
4539 | 4655 | ||
4540 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4656 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4541 | ad.u.net.netif = ifindex; | 4657 | ad.u.net.netif = ifindex; |
4542 | ad.u.net.family = family; | 4658 | ad.u.net.family = family; |
4543 | if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) | 4659 | if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) |
@@ -4607,13 +4723,13 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) | |||
4607 | static int selinux_netlink_recv(struct sk_buff *skb, int capability) | 4723 | static int selinux_netlink_recv(struct sk_buff *skb, int capability) |
4608 | { | 4724 | { |
4609 | int err; | 4725 | int err; |
4610 | struct avc_audit_data ad; | 4726 | struct common_audit_data ad; |
4611 | 4727 | ||
4612 | err = cap_netlink_recv(skb, capability); | 4728 | err = cap_netlink_recv(skb, capability); |
4613 | if (err) | 4729 | if (err) |
4614 | return err; | 4730 | return err; |
4615 | 4731 | ||
4616 | AVC_AUDIT_DATA_INIT(&ad, CAP); | 4732 | COMMON_AUDIT_DATA_INIT(&ad, CAP); |
4617 | ad.u.cap = capability; | 4733 | ad.u.cap = capability; |
4618 | 4734 | ||
4619 | return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid, | 4735 | return avc_has_perm(NETLINK_CB(skb).sid, NETLINK_CB(skb).sid, |
@@ -4672,12 +4788,12 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, | |||
4672 | u32 perms) | 4788 | u32 perms) |
4673 | { | 4789 | { |
4674 | struct ipc_security_struct *isec; | 4790 | struct ipc_security_struct *isec; |
4675 | struct avc_audit_data ad; | 4791 | struct common_audit_data ad; |
4676 | u32 sid = current_sid(); | 4792 | u32 sid = current_sid(); |
4677 | 4793 | ||
4678 | isec = ipc_perms->security; | 4794 | isec = ipc_perms->security; |
4679 | 4795 | ||
4680 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4796 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4681 | ad.u.ipc_id = ipc_perms->key; | 4797 | ad.u.ipc_id = ipc_perms->key; |
4682 | 4798 | ||
4683 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | 4799 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); |
@@ -4697,7 +4813,7 @@ static void selinux_msg_msg_free_security(struct msg_msg *msg) | |||
4697 | static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | 4813 | static int selinux_msg_queue_alloc_security(struct msg_queue *msq) |
4698 | { | 4814 | { |
4699 | struct ipc_security_struct *isec; | 4815 | struct ipc_security_struct *isec; |
4700 | struct avc_audit_data ad; | 4816 | struct common_audit_data ad; |
4701 | u32 sid = current_sid(); | 4817 | u32 sid = current_sid(); |
4702 | int rc; | 4818 | int rc; |
4703 | 4819 | ||
@@ -4707,7 +4823,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | |||
4707 | 4823 | ||
4708 | isec = msq->q_perm.security; | 4824 | isec = msq->q_perm.security; |
4709 | 4825 | ||
4710 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4826 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4711 | ad.u.ipc_id = msq->q_perm.key; | 4827 | ad.u.ipc_id = msq->q_perm.key; |
4712 | 4828 | ||
4713 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4829 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
@@ -4727,12 +4843,12 @@ static void selinux_msg_queue_free_security(struct msg_queue *msq) | |||
4727 | static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) | 4843 | static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) |
4728 | { | 4844 | { |
4729 | struct ipc_security_struct *isec; | 4845 | struct ipc_security_struct *isec; |
4730 | struct avc_audit_data ad; | 4846 | struct common_audit_data ad; |
4731 | u32 sid = current_sid(); | 4847 | u32 sid = current_sid(); |
4732 | 4848 | ||
4733 | isec = msq->q_perm.security; | 4849 | isec = msq->q_perm.security; |
4734 | 4850 | ||
4735 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4851 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4736 | ad.u.ipc_id = msq->q_perm.key; | 4852 | ad.u.ipc_id = msq->q_perm.key; |
4737 | 4853 | ||
4738 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4854 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
@@ -4771,7 +4887,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | |||
4771 | { | 4887 | { |
4772 | struct ipc_security_struct *isec; | 4888 | struct ipc_security_struct *isec; |
4773 | struct msg_security_struct *msec; | 4889 | struct msg_security_struct *msec; |
4774 | struct avc_audit_data ad; | 4890 | struct common_audit_data ad; |
4775 | u32 sid = current_sid(); | 4891 | u32 sid = current_sid(); |
4776 | int rc; | 4892 | int rc; |
4777 | 4893 | ||
@@ -4792,7 +4908,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | |||
4792 | return rc; | 4908 | return rc; |
4793 | } | 4909 | } |
4794 | 4910 | ||
4795 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4911 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4796 | ad.u.ipc_id = msq->q_perm.key; | 4912 | ad.u.ipc_id = msq->q_perm.key; |
4797 | 4913 | ||
4798 | /* Can this process write to the queue? */ | 4914 | /* Can this process write to the queue? */ |
@@ -4816,14 +4932,14 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | |||
4816 | { | 4932 | { |
4817 | struct ipc_security_struct *isec; | 4933 | struct ipc_security_struct *isec; |
4818 | struct msg_security_struct *msec; | 4934 | struct msg_security_struct *msec; |
4819 | struct avc_audit_data ad; | 4935 | struct common_audit_data ad; |
4820 | u32 sid = task_sid(target); | 4936 | u32 sid = task_sid(target); |
4821 | int rc; | 4937 | int rc; |
4822 | 4938 | ||
4823 | isec = msq->q_perm.security; | 4939 | isec = msq->q_perm.security; |
4824 | msec = msg->security; | 4940 | msec = msg->security; |
4825 | 4941 | ||
4826 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4942 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4827 | ad.u.ipc_id = msq->q_perm.key; | 4943 | ad.u.ipc_id = msq->q_perm.key; |
4828 | 4944 | ||
4829 | rc = avc_has_perm(sid, isec->sid, | 4945 | rc = avc_has_perm(sid, isec->sid, |
@@ -4838,7 +4954,7 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | |||
4838 | static int selinux_shm_alloc_security(struct shmid_kernel *shp) | 4954 | static int selinux_shm_alloc_security(struct shmid_kernel *shp) |
4839 | { | 4955 | { |
4840 | struct ipc_security_struct *isec; | 4956 | struct ipc_security_struct *isec; |
4841 | struct avc_audit_data ad; | 4957 | struct common_audit_data ad; |
4842 | u32 sid = current_sid(); | 4958 | u32 sid = current_sid(); |
4843 | int rc; | 4959 | int rc; |
4844 | 4960 | ||
@@ -4848,7 +4964,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) | |||
4848 | 4964 | ||
4849 | isec = shp->shm_perm.security; | 4965 | isec = shp->shm_perm.security; |
4850 | 4966 | ||
4851 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4967 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4852 | ad.u.ipc_id = shp->shm_perm.key; | 4968 | ad.u.ipc_id = shp->shm_perm.key; |
4853 | 4969 | ||
4854 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 4970 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
@@ -4868,12 +4984,12 @@ static void selinux_shm_free_security(struct shmid_kernel *shp) | |||
4868 | static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) | 4984 | static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) |
4869 | { | 4985 | { |
4870 | struct ipc_security_struct *isec; | 4986 | struct ipc_security_struct *isec; |
4871 | struct avc_audit_data ad; | 4987 | struct common_audit_data ad; |
4872 | u32 sid = current_sid(); | 4988 | u32 sid = current_sid(); |
4873 | 4989 | ||
4874 | isec = shp->shm_perm.security; | 4990 | isec = shp->shm_perm.security; |
4875 | 4991 | ||
4876 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4992 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4877 | ad.u.ipc_id = shp->shm_perm.key; | 4993 | ad.u.ipc_id = shp->shm_perm.key; |
4878 | 4994 | ||
4879 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 4995 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
@@ -4930,7 +5046,7 @@ static int selinux_shm_shmat(struct shmid_kernel *shp, | |||
4930 | static int selinux_sem_alloc_security(struct sem_array *sma) | 5046 | static int selinux_sem_alloc_security(struct sem_array *sma) |
4931 | { | 5047 | { |
4932 | struct ipc_security_struct *isec; | 5048 | struct ipc_security_struct *isec; |
4933 | struct avc_audit_data ad; | 5049 | struct common_audit_data ad; |
4934 | u32 sid = current_sid(); | 5050 | u32 sid = current_sid(); |
4935 | int rc; | 5051 | int rc; |
4936 | 5052 | ||
@@ -4940,7 +5056,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma) | |||
4940 | 5056 | ||
4941 | isec = sma->sem_perm.security; | 5057 | isec = sma->sem_perm.security; |
4942 | 5058 | ||
4943 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 5059 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4944 | ad.u.ipc_id = sma->sem_perm.key; | 5060 | ad.u.ipc_id = sma->sem_perm.key; |
4945 | 5061 | ||
4946 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 5062 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
@@ -4960,12 +5076,12 @@ static void selinux_sem_free_security(struct sem_array *sma) | |||
4960 | static int selinux_sem_associate(struct sem_array *sma, int semflg) | 5076 | static int selinux_sem_associate(struct sem_array *sma, int semflg) |
4961 | { | 5077 | { |
4962 | struct ipc_security_struct *isec; | 5078 | struct ipc_security_struct *isec; |
4963 | struct avc_audit_data ad; | 5079 | struct common_audit_data ad; |
4964 | u32 sid = current_sid(); | 5080 | u32 sid = current_sid(); |
4965 | 5081 | ||
4966 | isec = sma->sem_perm.security; | 5082 | isec = sma->sem_perm.security; |
4967 | 5083 | ||
4968 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 5084 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4969 | ad.u.ipc_id = sma->sem_perm.key; | 5085 | ad.u.ipc_id = sma->sem_perm.key; |
4970 | 5086 | ||
4971 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 5087 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
@@ -5183,7 +5299,7 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5183 | 5299 | ||
5184 | /* Only allow single threaded processes to change context */ | 5300 | /* Only allow single threaded processes to change context */ |
5185 | error = -EPERM; | 5301 | error = -EPERM; |
5186 | if (!is_single_threaded(p)) { | 5302 | if (!current_is_single_threaded()) { |
5187 | error = security_bounded_transition(tsec->sid, sid); | 5303 | error = security_bounded_transition(tsec->sid, sid); |
5188 | if (error) | 5304 | if (error) |
5189 | goto abort_change; | 5305 | goto abort_change; |
@@ -5240,6 +5356,32 @@ static void selinux_release_secctx(char *secdata, u32 seclen) | |||
5240 | kfree(secdata); | 5356 | kfree(secdata); |
5241 | } | 5357 | } |
5242 | 5358 | ||
5359 | /* | ||
5360 | * called with inode->i_mutex locked | ||
5361 | */ | ||
5362 | static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) | ||
5363 | { | ||
5364 | return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0); | ||
5365 | } | ||
5366 | |||
5367 | /* | ||
5368 | * called with inode->i_mutex locked | ||
5369 | */ | ||
5370 | static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) | ||
5371 | { | ||
5372 | return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0); | ||
5373 | } | ||
5374 | |||
5375 | static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) | ||
5376 | { | ||
5377 | int len = 0; | ||
5378 | len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX, | ||
5379 | ctx, true); | ||
5380 | if (len < 0) | ||
5381 | return len; | ||
5382 | *ctxlen = len; | ||
5383 | return 0; | ||
5384 | } | ||
5243 | #ifdef CONFIG_KEYS | 5385 | #ifdef CONFIG_KEYS |
5244 | 5386 | ||
5245 | static int selinux_key_alloc(struct key *k, const struct cred *cred, | 5387 | static int selinux_key_alloc(struct key *k, const struct cred *cred, |
@@ -5311,7 +5453,7 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) | |||
5311 | static struct security_operations selinux_ops = { | 5453 | static struct security_operations selinux_ops = { |
5312 | .name = "selinux", | 5454 | .name = "selinux", |
5313 | 5455 | ||
5314 | .ptrace_may_access = selinux_ptrace_may_access, | 5456 | .ptrace_access_check = selinux_ptrace_access_check, |
5315 | .ptrace_traceme = selinux_ptrace_traceme, | 5457 | .ptrace_traceme = selinux_ptrace_traceme, |
5316 | .capget = selinux_capget, | 5458 | .capget = selinux_capget, |
5317 | .capset = selinux_capset, | 5459 | .capset = selinux_capset, |
@@ -5384,10 +5526,13 @@ static struct security_operations selinux_ops = { | |||
5384 | .dentry_open = selinux_dentry_open, | 5526 | .dentry_open = selinux_dentry_open, |
5385 | 5527 | ||
5386 | .task_create = selinux_task_create, | 5528 | .task_create = selinux_task_create, |
5529 | .cred_alloc_blank = selinux_cred_alloc_blank, | ||
5387 | .cred_free = selinux_cred_free, | 5530 | .cred_free = selinux_cred_free, |
5388 | .cred_prepare = selinux_cred_prepare, | 5531 | .cred_prepare = selinux_cred_prepare, |
5532 | .cred_transfer = selinux_cred_transfer, | ||
5389 | .kernel_act_as = selinux_kernel_act_as, | 5533 | .kernel_act_as = selinux_kernel_act_as, |
5390 | .kernel_create_files_as = selinux_kernel_create_files_as, | 5534 | .kernel_create_files_as = selinux_kernel_create_files_as, |
5535 | .kernel_module_request = selinux_kernel_module_request, | ||
5391 | .task_setpgid = selinux_task_setpgid, | 5536 | .task_setpgid = selinux_task_setpgid, |
5392 | .task_getpgid = selinux_task_getpgid, | 5537 | .task_getpgid = selinux_task_getpgid, |
5393 | .task_getsid = selinux_task_getsid, | 5538 | .task_getsid = selinux_task_getsid, |
@@ -5436,6 +5581,9 @@ static struct security_operations selinux_ops = { | |||
5436 | .secid_to_secctx = selinux_secid_to_secctx, | 5581 | .secid_to_secctx = selinux_secid_to_secctx, |
5437 | .secctx_to_secid = selinux_secctx_to_secid, | 5582 | .secctx_to_secid = selinux_secctx_to_secid, |
5438 | .release_secctx = selinux_release_secctx, | 5583 | .release_secctx = selinux_release_secctx, |
5584 | .inode_notifysecctx = selinux_inode_notifysecctx, | ||
5585 | .inode_setsecctx = selinux_inode_setsecctx, | ||
5586 | .inode_getsecctx = selinux_inode_getsecctx, | ||
5439 | 5587 | ||
5440 | .unix_stream_connect = selinux_socket_unix_stream_connect, | 5588 | .unix_stream_connect = selinux_socket_unix_stream_connect, |
5441 | .unix_may_send = selinux_socket_unix_may_send, | 5589 | .unix_may_send = selinux_socket_unix_may_send, |
@@ -5465,6 +5613,9 @@ static struct security_operations selinux_ops = { | |||
5465 | .inet_csk_clone = selinux_inet_csk_clone, | 5613 | .inet_csk_clone = selinux_inet_csk_clone, |
5466 | .inet_conn_established = selinux_inet_conn_established, | 5614 | .inet_conn_established = selinux_inet_conn_established, |
5467 | .req_classify_flow = selinux_req_classify_flow, | 5615 | .req_classify_flow = selinux_req_classify_flow, |
5616 | .tun_dev_create = selinux_tun_dev_create, | ||
5617 | .tun_dev_post_create = selinux_tun_dev_post_create, | ||
5618 | .tun_dev_attach = selinux_tun_dev_attach, | ||
5468 | 5619 | ||
5469 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 5620 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
5470 | .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, | 5621 | .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, |
@@ -5679,6 +5830,9 @@ int selinux_disable(void) | |||
5679 | selinux_disabled = 1; | 5830 | selinux_disabled = 1; |
5680 | selinux_enabled = 0; | 5831 | selinux_enabled = 0; |
5681 | 5832 | ||
5833 | /* Try to destroy the avc node cache */ | ||
5834 | avc_disable(); | ||
5835 | |||
5682 | /* Reset security_ops to the secondary module, dummy or capability. */ | 5836 | /* Reset security_ops to the secondary module, dummy or capability. */ |
5683 | security_ops = secondary_ops; | 5837 | security_ops = secondary_ops; |
5684 | 5838 | ||