diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 318 |
1 files changed, 230 insertions, 88 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8d8b69c5664e..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 | ||
@@ -3220,12 +3238,29 @@ static int selinux_task_create(unsigned long clone_flags) | |||
3220 | } | 3238 | } |
3221 | 3239 | ||
3222 | /* | 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 | /* | ||
3223 | * detach and free the LSM part of a set of credentials | 3256 | * detach and free the LSM part of a set of credentials |
3224 | */ | 3257 | */ |
3225 | static void selinux_cred_free(struct cred *cred) | 3258 | static void selinux_cred_free(struct cred *cred) |
3226 | { | 3259 | { |
3227 | struct task_security_struct *tsec = cred->security; | 3260 | struct task_security_struct *tsec = cred->security; |
3228 | cred->security = NULL; | 3261 | |
3262 | BUG_ON((unsigned long) cred->security < PAGE_SIZE); | ||
3263 | cred->security = (void *) 0x7UL; | ||
3229 | kfree(tsec); | 3264 | kfree(tsec); |
3230 | } | 3265 | } |
3231 | 3266 | ||
@@ -3249,6 +3284,17 @@ static int selinux_cred_prepare(struct cred *new, const struct cred *old, | |||
3249 | } | 3284 | } |
3250 | 3285 | ||
3251 | /* | 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 | /* | ||
3252 | * set the security data for a kernel service | 3298 | * set the security data for a kernel service |
3253 | * - all the creation contexts are set to unlabelled | 3299 | * - all the creation contexts are set to unlabelled |
3254 | */ | 3300 | */ |
@@ -3292,6 +3338,11 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
3292 | return 0; | 3338 | return 0; |
3293 | } | 3339 | } |
3294 | 3340 | ||
3341 | static int selinux_kernel_module_request(void) | ||
3342 | { | ||
3343 | return task_has_system(current, SYSTEM__MODULE_REQUEST); | ||
3344 | } | ||
3345 | |||
3295 | 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) |
3296 | { | 3347 | { |
3297 | return current_has_perm(p, PROCESS__SETPGID); | 3348 | return current_has_perm(p, PROCESS__SETPGID); |
@@ -3409,7 +3460,7 @@ static void selinux_task_to_inode(struct task_struct *p, | |||
3409 | 3460 | ||
3410 | /* Returns error only if unable to parse addresses */ | 3461 | /* Returns error only if unable to parse addresses */ |
3411 | static int selinux_parse_skb_ipv4(struct sk_buff *skb, | 3462 | static int selinux_parse_skb_ipv4(struct sk_buff *skb, |
3412 | struct avc_audit_data *ad, u8 *proto) | 3463 | struct common_audit_data *ad, u8 *proto) |
3413 | { | 3464 | { |
3414 | int offset, ihlen, ret = -EINVAL; | 3465 | int offset, ihlen, ret = -EINVAL; |
3415 | struct iphdr _iph, *ih; | 3466 | struct iphdr _iph, *ih; |
@@ -3490,7 +3541,7 @@ out: | |||
3490 | 3541 | ||
3491 | /* Returns error only if unable to parse addresses */ | 3542 | /* Returns error only if unable to parse addresses */ |
3492 | static int selinux_parse_skb_ipv6(struct sk_buff *skb, | 3543 | static int selinux_parse_skb_ipv6(struct sk_buff *skb, |
3493 | struct avc_audit_data *ad, u8 *proto) | 3544 | struct common_audit_data *ad, u8 *proto) |
3494 | { | 3545 | { |
3495 | u8 nexthdr; | 3546 | u8 nexthdr; |
3496 | int ret = -EINVAL, offset; | 3547 | int ret = -EINVAL, offset; |
@@ -3561,7 +3612,7 @@ out: | |||
3561 | 3612 | ||
3562 | #endif /* IPV6 */ | 3613 | #endif /* IPV6 */ |
3563 | 3614 | ||
3564 | 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, |
3565 | char **_addrp, int src, u8 *proto) | 3616 | char **_addrp, int src, u8 *proto) |
3566 | { | 3617 | { |
3567 | char *addrp; | 3618 | char *addrp; |
@@ -3643,7 +3694,7 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock, | |||
3643 | u32 perms) | 3694 | u32 perms) |
3644 | { | 3695 | { |
3645 | struct inode_security_struct *isec; | 3696 | struct inode_security_struct *isec; |
3646 | struct avc_audit_data ad; | 3697 | struct common_audit_data ad; |
3647 | u32 sid; | 3698 | u32 sid; |
3648 | int err = 0; | 3699 | int err = 0; |
3649 | 3700 | ||
@@ -3653,7 +3704,7 @@ static int socket_has_perm(struct task_struct *task, struct socket *sock, | |||
3653 | goto out; | 3704 | goto out; |
3654 | sid = task_sid(task); | 3705 | sid = task_sid(task); |
3655 | 3706 | ||
3656 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3707 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3657 | ad.u.net.sk = sock->sk; | 3708 | ad.u.net.sk = sock->sk; |
3658 | err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | 3709 | err = avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); |
3659 | 3710 | ||
@@ -3740,7 +3791,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3740 | if (family == PF_INET || family == PF_INET6) { | 3791 | if (family == PF_INET || family == PF_INET6) { |
3741 | char *addrp; | 3792 | char *addrp; |
3742 | struct inode_security_struct *isec; | 3793 | struct inode_security_struct *isec; |
3743 | struct avc_audit_data ad; | 3794 | struct common_audit_data ad; |
3744 | struct sockaddr_in *addr4 = NULL; | 3795 | struct sockaddr_in *addr4 = NULL; |
3745 | struct sockaddr_in6 *addr6 = NULL; | 3796 | struct sockaddr_in6 *addr6 = NULL; |
3746 | unsigned short snum; | 3797 | unsigned short snum; |
@@ -3769,7 +3820,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3769 | snum, &sid); | 3820 | snum, &sid); |
3770 | if (err) | 3821 | if (err) |
3771 | goto out; | 3822 | goto out; |
3772 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3823 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3773 | ad.u.net.sport = htons(snum); | 3824 | ad.u.net.sport = htons(snum); |
3774 | ad.u.net.family = family; | 3825 | ad.u.net.family = family; |
3775 | err = avc_has_perm(isec->sid, sid, | 3826 | err = avc_has_perm(isec->sid, sid, |
@@ -3802,7 +3853,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3802 | if (err) | 3853 | if (err) |
3803 | goto out; | 3854 | goto out; |
3804 | 3855 | ||
3805 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3856 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3806 | ad.u.net.sport = htons(snum); | 3857 | ad.u.net.sport = htons(snum); |
3807 | ad.u.net.family = family; | 3858 | ad.u.net.family = family; |
3808 | 3859 | ||
@@ -3836,7 +3887,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3836 | isec = SOCK_INODE(sock)->i_security; | 3887 | isec = SOCK_INODE(sock)->i_security; |
3837 | if (isec->sclass == SECCLASS_TCP_SOCKET || | 3888 | if (isec->sclass == SECCLASS_TCP_SOCKET || |
3838 | isec->sclass == SECCLASS_DCCP_SOCKET) { | 3889 | isec->sclass == SECCLASS_DCCP_SOCKET) { |
3839 | struct avc_audit_data ad; | 3890 | struct common_audit_data ad; |
3840 | struct sockaddr_in *addr4 = NULL; | 3891 | struct sockaddr_in *addr4 = NULL; |
3841 | struct sockaddr_in6 *addr6 = NULL; | 3892 | struct sockaddr_in6 *addr6 = NULL; |
3842 | unsigned short snum; | 3893 | unsigned short snum; |
@@ -3861,7 +3912,7 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address, | |||
3861 | perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? | 3912 | perm = (isec->sclass == SECCLASS_TCP_SOCKET) ? |
3862 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; | 3913 | TCP_SOCKET__NAME_CONNECT : DCCP_SOCKET__NAME_CONNECT; |
3863 | 3914 | ||
3864 | AVC_AUDIT_DATA_INIT(&ad, NET); | 3915 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3865 | ad.u.net.dport = htons(snum); | 3916 | ad.u.net.dport = htons(snum); |
3866 | ad.u.net.family = sk->sk_family; | 3917 | ad.u.net.family = sk->sk_family; |
3867 | err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); | 3918 | err = avc_has_perm(isec->sid, sid, isec->sclass, perm, &ad); |
@@ -3951,13 +4002,13 @@ static int selinux_socket_unix_stream_connect(struct socket *sock, | |||
3951 | struct sk_security_struct *ssec; | 4002 | struct sk_security_struct *ssec; |
3952 | struct inode_security_struct *isec; | 4003 | struct inode_security_struct *isec; |
3953 | struct inode_security_struct *other_isec; | 4004 | struct inode_security_struct *other_isec; |
3954 | struct avc_audit_data ad; | 4005 | struct common_audit_data ad; |
3955 | int err; | 4006 | int err; |
3956 | 4007 | ||
3957 | isec = SOCK_INODE(sock)->i_security; | 4008 | isec = SOCK_INODE(sock)->i_security; |
3958 | other_isec = SOCK_INODE(other)->i_security; | 4009 | other_isec = SOCK_INODE(other)->i_security; |
3959 | 4010 | ||
3960 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4011 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3961 | ad.u.net.sk = other->sk; | 4012 | ad.u.net.sk = other->sk; |
3962 | 4013 | ||
3963 | err = avc_has_perm(isec->sid, other_isec->sid, | 4014 | err = avc_has_perm(isec->sid, other_isec->sid, |
@@ -3983,13 +4034,13 @@ static int selinux_socket_unix_may_send(struct socket *sock, | |||
3983 | { | 4034 | { |
3984 | struct inode_security_struct *isec; | 4035 | struct inode_security_struct *isec; |
3985 | struct inode_security_struct *other_isec; | 4036 | struct inode_security_struct *other_isec; |
3986 | struct avc_audit_data ad; | 4037 | struct common_audit_data ad; |
3987 | int err; | 4038 | int err; |
3988 | 4039 | ||
3989 | isec = SOCK_INODE(sock)->i_security; | 4040 | isec = SOCK_INODE(sock)->i_security; |
3990 | other_isec = SOCK_INODE(other)->i_security; | 4041 | other_isec = SOCK_INODE(other)->i_security; |
3991 | 4042 | ||
3992 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4043 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
3993 | ad.u.net.sk = other->sk; | 4044 | ad.u.net.sk = other->sk; |
3994 | 4045 | ||
3995 | err = avc_has_perm(isec->sid, other_isec->sid, | 4046 | err = avc_has_perm(isec->sid, other_isec->sid, |
@@ -4002,7 +4053,7 @@ static int selinux_socket_unix_may_send(struct socket *sock, | |||
4002 | 4053 | ||
4003 | 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, |
4004 | u32 peer_sid, | 4055 | u32 peer_sid, |
4005 | struct avc_audit_data *ad) | 4056 | struct common_audit_data *ad) |
4006 | { | 4057 | { |
4007 | int err; | 4058 | int err; |
4008 | u32 if_sid; | 4059 | u32 if_sid; |
@@ -4030,10 +4081,10 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, | |||
4030 | struct sk_security_struct *sksec = sk->sk_security; | 4081 | struct sk_security_struct *sksec = sk->sk_security; |
4031 | u32 peer_sid; | 4082 | u32 peer_sid; |
4032 | u32 sk_sid = sksec->sid; | 4083 | u32 sk_sid = sksec->sid; |
4033 | struct avc_audit_data ad; | 4084 | struct common_audit_data ad; |
4034 | char *addrp; | 4085 | char *addrp; |
4035 | 4086 | ||
4036 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4087 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4037 | ad.u.net.netif = skb->iif; | 4088 | ad.u.net.netif = skb->iif; |
4038 | ad.u.net.family = family; | 4089 | ad.u.net.family = family; |
4039 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); | 4090 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); |
@@ -4071,7 +4122,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4071 | struct sk_security_struct *sksec = sk->sk_security; | 4122 | struct sk_security_struct *sksec = sk->sk_security; |
4072 | u16 family = sk->sk_family; | 4123 | u16 family = sk->sk_family; |
4073 | u32 sk_sid = sksec->sid; | 4124 | u32 sk_sid = sksec->sid; |
4074 | struct avc_audit_data ad; | 4125 | struct common_audit_data ad; |
4075 | char *addrp; | 4126 | char *addrp; |
4076 | u8 secmark_active; | 4127 | u8 secmark_active; |
4077 | u8 peerlbl_active; | 4128 | u8 peerlbl_active; |
@@ -4095,7 +4146,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4095 | if (!secmark_active && !peerlbl_active) | 4146 | if (!secmark_active && !peerlbl_active) |
4096 | return 0; | 4147 | return 0; |
4097 | 4148 | ||
4098 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4149 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4099 | ad.u.net.netif = skb->iif; | 4150 | ad.u.net.netif = skb->iif; |
4100 | ad.u.net.family = family; | 4151 | ad.u.net.family = family; |
4101 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); | 4152 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); |
@@ -4309,6 +4360,59 @@ static void selinux_req_classify_flow(const struct request_sock *req, | |||
4309 | fl->secid = req->secid; | 4360 | fl->secid = req->secid; |
4310 | } | 4361 | } |
4311 | 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 | |||
4312 | 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) |
4313 | { | 4417 | { |
4314 | int err = 0; | 4418 | int err = 0; |
@@ -4353,7 +4457,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
4353 | int err; | 4457 | int err; |
4354 | char *addrp; | 4458 | char *addrp; |
4355 | u32 peer_sid; | 4459 | u32 peer_sid; |
4356 | struct avc_audit_data ad; | 4460 | struct common_audit_data ad; |
4357 | u8 secmark_active; | 4461 | u8 secmark_active; |
4358 | u8 netlbl_active; | 4462 | u8 netlbl_active; |
4359 | u8 peerlbl_active; | 4463 | u8 peerlbl_active; |
@@ -4370,7 +4474,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
4370 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) | 4474 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid) != 0) |
4371 | return NF_DROP; | 4475 | return NF_DROP; |
4372 | 4476 | ||
4373 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4477 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4374 | ad.u.net.netif = ifindex; | 4478 | ad.u.net.netif = ifindex; |
4375 | ad.u.net.family = family; | 4479 | ad.u.net.family = family; |
4376 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) | 4480 | if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0) |
@@ -4458,7 +4562,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4458 | { | 4562 | { |
4459 | struct sock *sk = skb->sk; | 4563 | struct sock *sk = skb->sk; |
4460 | struct sk_security_struct *sksec; | 4564 | struct sk_security_struct *sksec; |
4461 | struct avc_audit_data ad; | 4565 | struct common_audit_data ad; |
4462 | char *addrp; | 4566 | char *addrp; |
4463 | u8 proto; | 4567 | u8 proto; |
4464 | 4568 | ||
@@ -4466,7 +4570,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, | |||
4466 | return NF_ACCEPT; | 4570 | return NF_ACCEPT; |
4467 | sksec = sk->sk_security; | 4571 | sksec = sk->sk_security; |
4468 | 4572 | ||
4469 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4573 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4470 | ad.u.net.netif = ifindex; | 4574 | ad.u.net.netif = ifindex; |
4471 | ad.u.net.family = family; | 4575 | ad.u.net.family = family; |
4472 | if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) | 4576 | if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto)) |
@@ -4490,7 +4594,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4490 | u32 secmark_perm; | 4594 | u32 secmark_perm; |
4491 | u32 peer_sid; | 4595 | u32 peer_sid; |
4492 | struct sock *sk; | 4596 | struct sock *sk; |
4493 | struct avc_audit_data ad; | 4597 | struct common_audit_data ad; |
4494 | char *addrp; | 4598 | char *addrp; |
4495 | u8 secmark_active; | 4599 | u8 secmark_active; |
4496 | u8 peerlbl_active; | 4600 | u8 peerlbl_active; |
@@ -4549,7 +4653,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4549 | secmark_perm = PACKET__SEND; | 4653 | secmark_perm = PACKET__SEND; |
4550 | } | 4654 | } |
4551 | 4655 | ||
4552 | AVC_AUDIT_DATA_INIT(&ad, NET); | 4656 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4553 | ad.u.net.netif = ifindex; | 4657 | ad.u.net.netif = ifindex; |
4554 | ad.u.net.family = family; | 4658 | ad.u.net.family = family; |
4555 | if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) | 4659 | if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) |
@@ -4619,13 +4723,13 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) | |||
4619 | static int selinux_netlink_recv(struct sk_buff *skb, int capability) | 4723 | static int selinux_netlink_recv(struct sk_buff *skb, int capability) |
4620 | { | 4724 | { |
4621 | int err; | 4725 | int err; |
4622 | struct avc_audit_data ad; | 4726 | struct common_audit_data ad; |
4623 | 4727 | ||
4624 | err = cap_netlink_recv(skb, capability); | 4728 | err = cap_netlink_recv(skb, capability); |
4625 | if (err) | 4729 | if (err) |
4626 | return err; | 4730 | return err; |
4627 | 4731 | ||
4628 | AVC_AUDIT_DATA_INIT(&ad, CAP); | 4732 | COMMON_AUDIT_DATA_INIT(&ad, CAP); |
4629 | ad.u.cap = capability; | 4733 | ad.u.cap = capability; |
4630 | 4734 | ||
4631 | 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, |
@@ -4684,12 +4788,12 @@ static int ipc_has_perm(struct kern_ipc_perm *ipc_perms, | |||
4684 | u32 perms) | 4788 | u32 perms) |
4685 | { | 4789 | { |
4686 | struct ipc_security_struct *isec; | 4790 | struct ipc_security_struct *isec; |
4687 | struct avc_audit_data ad; | 4791 | struct common_audit_data ad; |
4688 | u32 sid = current_sid(); | 4792 | u32 sid = current_sid(); |
4689 | 4793 | ||
4690 | isec = ipc_perms->security; | 4794 | isec = ipc_perms->security; |
4691 | 4795 | ||
4692 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4796 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4693 | ad.u.ipc_id = ipc_perms->key; | 4797 | ad.u.ipc_id = ipc_perms->key; |
4694 | 4798 | ||
4695 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); | 4799 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, &ad); |
@@ -4709,7 +4813,7 @@ static void selinux_msg_msg_free_security(struct msg_msg *msg) | |||
4709 | static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | 4813 | static int selinux_msg_queue_alloc_security(struct msg_queue *msq) |
4710 | { | 4814 | { |
4711 | struct ipc_security_struct *isec; | 4815 | struct ipc_security_struct *isec; |
4712 | struct avc_audit_data ad; | 4816 | struct common_audit_data ad; |
4713 | u32 sid = current_sid(); | 4817 | u32 sid = current_sid(); |
4714 | int rc; | 4818 | int rc; |
4715 | 4819 | ||
@@ -4719,7 +4823,7 @@ static int selinux_msg_queue_alloc_security(struct msg_queue *msq) | |||
4719 | 4823 | ||
4720 | isec = msq->q_perm.security; | 4824 | isec = msq->q_perm.security; |
4721 | 4825 | ||
4722 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4826 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4723 | ad.u.ipc_id = msq->q_perm.key; | 4827 | ad.u.ipc_id = msq->q_perm.key; |
4724 | 4828 | ||
4725 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4829 | rc = avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
@@ -4739,12 +4843,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) | 4843 | static int selinux_msg_queue_associate(struct msg_queue *msq, int msqflg) |
4740 | { | 4844 | { |
4741 | struct ipc_security_struct *isec; | 4845 | struct ipc_security_struct *isec; |
4742 | struct avc_audit_data ad; | 4846 | struct common_audit_data ad; |
4743 | u32 sid = current_sid(); | 4847 | u32 sid = current_sid(); |
4744 | 4848 | ||
4745 | isec = msq->q_perm.security; | 4849 | isec = msq->q_perm.security; |
4746 | 4850 | ||
4747 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4851 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4748 | ad.u.ipc_id = msq->q_perm.key; | 4852 | ad.u.ipc_id = msq->q_perm.key; |
4749 | 4853 | ||
4750 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, | 4854 | return avc_has_perm(sid, isec->sid, SECCLASS_MSGQ, |
@@ -4783,7 +4887,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | |||
4783 | { | 4887 | { |
4784 | struct ipc_security_struct *isec; | 4888 | struct ipc_security_struct *isec; |
4785 | struct msg_security_struct *msec; | 4889 | struct msg_security_struct *msec; |
4786 | struct avc_audit_data ad; | 4890 | struct common_audit_data ad; |
4787 | u32 sid = current_sid(); | 4891 | u32 sid = current_sid(); |
4788 | int rc; | 4892 | int rc; |
4789 | 4893 | ||
@@ -4804,7 +4908,7 @@ static int selinux_msg_queue_msgsnd(struct msg_queue *msq, struct msg_msg *msg, | |||
4804 | return rc; | 4908 | return rc; |
4805 | } | 4909 | } |
4806 | 4910 | ||
4807 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4911 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4808 | ad.u.ipc_id = msq->q_perm.key; | 4912 | ad.u.ipc_id = msq->q_perm.key; |
4809 | 4913 | ||
4810 | /* Can this process write to the queue? */ | 4914 | /* Can this process write to the queue? */ |
@@ -4828,14 +4932,14 @@ static int selinux_msg_queue_msgrcv(struct msg_queue *msq, struct msg_msg *msg, | |||
4828 | { | 4932 | { |
4829 | struct ipc_security_struct *isec; | 4933 | struct ipc_security_struct *isec; |
4830 | struct msg_security_struct *msec; | 4934 | struct msg_security_struct *msec; |
4831 | struct avc_audit_data ad; | 4935 | struct common_audit_data ad; |
4832 | u32 sid = task_sid(target); | 4936 | u32 sid = task_sid(target); |
4833 | int rc; | 4937 | int rc; |
4834 | 4938 | ||
4835 | isec = msq->q_perm.security; | 4939 | isec = msq->q_perm.security; |
4836 | msec = msg->security; | 4940 | msec = msg->security; |
4837 | 4941 | ||
4838 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4942 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4839 | ad.u.ipc_id = msq->q_perm.key; | 4943 | ad.u.ipc_id = msq->q_perm.key; |
4840 | 4944 | ||
4841 | rc = avc_has_perm(sid, isec->sid, | 4945 | rc = avc_has_perm(sid, isec->sid, |
@@ -4850,7 +4954,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) | 4954 | static int selinux_shm_alloc_security(struct shmid_kernel *shp) |
4851 | { | 4955 | { |
4852 | struct ipc_security_struct *isec; | 4956 | struct ipc_security_struct *isec; |
4853 | struct avc_audit_data ad; | 4957 | struct common_audit_data ad; |
4854 | u32 sid = current_sid(); | 4958 | u32 sid = current_sid(); |
4855 | int rc; | 4959 | int rc; |
4856 | 4960 | ||
@@ -4860,7 +4964,7 @@ static int selinux_shm_alloc_security(struct shmid_kernel *shp) | |||
4860 | 4964 | ||
4861 | isec = shp->shm_perm.security; | 4965 | isec = shp->shm_perm.security; |
4862 | 4966 | ||
4863 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4967 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4864 | ad.u.ipc_id = shp->shm_perm.key; | 4968 | ad.u.ipc_id = shp->shm_perm.key; |
4865 | 4969 | ||
4866 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 4970 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
@@ -4880,12 +4984,12 @@ static void selinux_shm_free_security(struct shmid_kernel *shp) | |||
4880 | static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) | 4984 | static int selinux_shm_associate(struct shmid_kernel *shp, int shmflg) |
4881 | { | 4985 | { |
4882 | struct ipc_security_struct *isec; | 4986 | struct ipc_security_struct *isec; |
4883 | struct avc_audit_data ad; | 4987 | struct common_audit_data ad; |
4884 | u32 sid = current_sid(); | 4988 | u32 sid = current_sid(); |
4885 | 4989 | ||
4886 | isec = shp->shm_perm.security; | 4990 | isec = shp->shm_perm.security; |
4887 | 4991 | ||
4888 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 4992 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4889 | ad.u.ipc_id = shp->shm_perm.key; | 4993 | ad.u.ipc_id = shp->shm_perm.key; |
4890 | 4994 | ||
4891 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, | 4995 | return avc_has_perm(sid, isec->sid, SECCLASS_SHM, |
@@ -4942,7 +5046,7 @@ static int selinux_shm_shmat(struct shmid_kernel *shp, | |||
4942 | static int selinux_sem_alloc_security(struct sem_array *sma) | 5046 | static int selinux_sem_alloc_security(struct sem_array *sma) |
4943 | { | 5047 | { |
4944 | struct ipc_security_struct *isec; | 5048 | struct ipc_security_struct *isec; |
4945 | struct avc_audit_data ad; | 5049 | struct common_audit_data ad; |
4946 | u32 sid = current_sid(); | 5050 | u32 sid = current_sid(); |
4947 | int rc; | 5051 | int rc; |
4948 | 5052 | ||
@@ -4952,7 +5056,7 @@ static int selinux_sem_alloc_security(struct sem_array *sma) | |||
4952 | 5056 | ||
4953 | isec = sma->sem_perm.security; | 5057 | isec = sma->sem_perm.security; |
4954 | 5058 | ||
4955 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 5059 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4956 | ad.u.ipc_id = sma->sem_perm.key; | 5060 | ad.u.ipc_id = sma->sem_perm.key; |
4957 | 5061 | ||
4958 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 5062 | rc = avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
@@ -4972,12 +5076,12 @@ static void selinux_sem_free_security(struct sem_array *sma) | |||
4972 | static int selinux_sem_associate(struct sem_array *sma, int semflg) | 5076 | static int selinux_sem_associate(struct sem_array *sma, int semflg) |
4973 | { | 5077 | { |
4974 | struct ipc_security_struct *isec; | 5078 | struct ipc_security_struct *isec; |
4975 | struct avc_audit_data ad; | 5079 | struct common_audit_data ad; |
4976 | u32 sid = current_sid(); | 5080 | u32 sid = current_sid(); |
4977 | 5081 | ||
4978 | isec = sma->sem_perm.security; | 5082 | isec = sma->sem_perm.security; |
4979 | 5083 | ||
4980 | AVC_AUDIT_DATA_INIT(&ad, IPC); | 5084 | COMMON_AUDIT_DATA_INIT(&ad, IPC); |
4981 | ad.u.ipc_id = sma->sem_perm.key; | 5085 | ad.u.ipc_id = sma->sem_perm.key; |
4982 | 5086 | ||
4983 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, | 5087 | return avc_has_perm(sid, isec->sid, SECCLASS_SEM, |
@@ -5195,7 +5299,7 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5195 | 5299 | ||
5196 | /* Only allow single threaded processes to change context */ | 5300 | /* Only allow single threaded processes to change context */ |
5197 | error = -EPERM; | 5301 | error = -EPERM; |
5198 | if (!is_single_threaded(p)) { | 5302 | if (!current_is_single_threaded()) { |
5199 | error = security_bounded_transition(tsec->sid, sid); | 5303 | error = security_bounded_transition(tsec->sid, sid); |
5200 | if (error) | 5304 | if (error) |
5201 | goto abort_change; | 5305 | goto abort_change; |
@@ -5252,6 +5356,32 @@ static void selinux_release_secctx(char *secdata, u32 seclen) | |||
5252 | kfree(secdata); | 5356 | kfree(secdata); |
5253 | } | 5357 | } |
5254 | 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 | } | ||
5255 | #ifdef CONFIG_KEYS | 5385 | #ifdef CONFIG_KEYS |
5256 | 5386 | ||
5257 | 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, |
@@ -5323,7 +5453,7 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) | |||
5323 | static struct security_operations selinux_ops = { | 5453 | static struct security_operations selinux_ops = { |
5324 | .name = "selinux", | 5454 | .name = "selinux", |
5325 | 5455 | ||
5326 | .ptrace_may_access = selinux_ptrace_may_access, | 5456 | .ptrace_access_check = selinux_ptrace_access_check, |
5327 | .ptrace_traceme = selinux_ptrace_traceme, | 5457 | .ptrace_traceme = selinux_ptrace_traceme, |
5328 | .capget = selinux_capget, | 5458 | .capget = selinux_capget, |
5329 | .capset = selinux_capset, | 5459 | .capset = selinux_capset, |
@@ -5396,10 +5526,13 @@ static struct security_operations selinux_ops = { | |||
5396 | .dentry_open = selinux_dentry_open, | 5526 | .dentry_open = selinux_dentry_open, |
5397 | 5527 | ||
5398 | .task_create = selinux_task_create, | 5528 | .task_create = selinux_task_create, |
5529 | .cred_alloc_blank = selinux_cred_alloc_blank, | ||
5399 | .cred_free = selinux_cred_free, | 5530 | .cred_free = selinux_cred_free, |
5400 | .cred_prepare = selinux_cred_prepare, | 5531 | .cred_prepare = selinux_cred_prepare, |
5532 | .cred_transfer = selinux_cred_transfer, | ||
5401 | .kernel_act_as = selinux_kernel_act_as, | 5533 | .kernel_act_as = selinux_kernel_act_as, |
5402 | .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, | ||
5403 | .task_setpgid = selinux_task_setpgid, | 5536 | .task_setpgid = selinux_task_setpgid, |
5404 | .task_getpgid = selinux_task_getpgid, | 5537 | .task_getpgid = selinux_task_getpgid, |
5405 | .task_getsid = selinux_task_getsid, | 5538 | .task_getsid = selinux_task_getsid, |
@@ -5448,6 +5581,9 @@ static struct security_operations selinux_ops = { | |||
5448 | .secid_to_secctx = selinux_secid_to_secctx, | 5581 | .secid_to_secctx = selinux_secid_to_secctx, |
5449 | .secctx_to_secid = selinux_secctx_to_secid, | 5582 | .secctx_to_secid = selinux_secctx_to_secid, |
5450 | .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, | ||
5451 | 5587 | ||
5452 | .unix_stream_connect = selinux_socket_unix_stream_connect, | 5588 | .unix_stream_connect = selinux_socket_unix_stream_connect, |
5453 | .unix_may_send = selinux_socket_unix_may_send, | 5589 | .unix_may_send = selinux_socket_unix_may_send, |
@@ -5477,6 +5613,9 @@ static struct security_operations selinux_ops = { | |||
5477 | .inet_csk_clone = selinux_inet_csk_clone, | 5613 | .inet_csk_clone = selinux_inet_csk_clone, |
5478 | .inet_conn_established = selinux_inet_conn_established, | 5614 | .inet_conn_established = selinux_inet_conn_established, |
5479 | .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, | ||
5480 | 5619 | ||
5481 | #ifdef CONFIG_SECURITY_NETWORK_XFRM | 5620 | #ifdef CONFIG_SECURITY_NETWORK_XFRM |
5482 | .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, | 5621 | .xfrm_policy_alloc_security = selinux_xfrm_policy_alloc, |
@@ -5691,6 +5830,9 @@ int selinux_disable(void) | |||
5691 | selinux_disabled = 1; | 5830 | selinux_disabled = 1; |
5692 | selinux_enabled = 0; | 5831 | selinux_enabled = 0; |
5693 | 5832 | ||
5833 | /* Try to destroy the avc node cache */ | ||
5834 | avc_disable(); | ||
5835 | |||
5694 | /* Reset security_ops to the secondary module, dummy or capability. */ | 5836 | /* Reset security_ops to the secondary module, dummy or capability. */ |
5695 | security_ops = secondary_ops; | 5837 | security_ops = secondary_ops; |
5696 | 5838 | ||