diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 113 |
1 files changed, 68 insertions, 45 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8fb248843009..20219ef5439a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -990,6 +990,7 @@ static void selinux_write_opts(struct seq_file *m, | |||
990 | continue; | 990 | continue; |
991 | default: | 991 | default: |
992 | BUG(); | 992 | BUG(); |
993 | return; | ||
993 | }; | 994 | }; |
994 | /* we need a comma before each option */ | 995 | /* we need a comma before each option */ |
995 | seq_putc(m, ','); | 996 | seq_putc(m, ','); |
@@ -1443,6 +1444,7 @@ static int task_has_capability(struct task_struct *tsk, | |||
1443 | printk(KERN_ERR | 1444 | printk(KERN_ERR |
1444 | "SELinux: out of range capability %d\n", cap); | 1445 | "SELinux: out of range capability %d\n", cap); |
1445 | BUG(); | 1446 | BUG(); |
1447 | return -EINVAL; | ||
1446 | } | 1448 | } |
1447 | 1449 | ||
1448 | rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd); | 1450 | rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd); |
@@ -1474,7 +1476,6 @@ static int inode_has_perm(const struct cred *cred, | |||
1474 | unsigned flags) | 1476 | unsigned flags) |
1475 | { | 1477 | { |
1476 | struct inode_security_struct *isec; | 1478 | struct inode_security_struct *isec; |
1477 | struct common_audit_data ad; | ||
1478 | u32 sid; | 1479 | u32 sid; |
1479 | 1480 | ||
1480 | validate_creds(cred); | 1481 | validate_creds(cred); |
@@ -1485,29 +1486,48 @@ static int inode_has_perm(const struct cred *cred, | |||
1485 | sid = cred_sid(cred); | 1486 | sid = cred_sid(cred); |
1486 | isec = inode->i_security; | 1487 | isec = inode->i_security; |
1487 | 1488 | ||
1488 | if (!adp) { | ||
1489 | adp = &ad; | ||
1490 | COMMON_AUDIT_DATA_INIT(&ad, FS); | ||
1491 | ad.u.fs.inode = inode; | ||
1492 | } | ||
1493 | |||
1494 | return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags); | 1489 | return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags); |
1495 | } | 1490 | } |
1496 | 1491 | ||
1492 | static int inode_has_perm_noadp(const struct cred *cred, | ||
1493 | struct inode *inode, | ||
1494 | u32 perms, | ||
1495 | unsigned flags) | ||
1496 | { | ||
1497 | struct common_audit_data ad; | ||
1498 | |||
1499 | COMMON_AUDIT_DATA_INIT(&ad, INODE); | ||
1500 | ad.u.inode = inode; | ||
1501 | return inode_has_perm(cred, inode, perms, &ad, flags); | ||
1502 | } | ||
1503 | |||
1497 | /* Same as inode_has_perm, but pass explicit audit data containing | 1504 | /* Same as inode_has_perm, but pass explicit audit data containing |
1498 | the dentry to help the auditing code to more easily generate the | 1505 | the dentry to help the auditing code to more easily generate the |
1499 | pathname if needed. */ | 1506 | pathname if needed. */ |
1500 | static inline int dentry_has_perm(const struct cred *cred, | 1507 | static inline int dentry_has_perm(const struct cred *cred, |
1501 | struct vfsmount *mnt, | ||
1502 | struct dentry *dentry, | 1508 | struct dentry *dentry, |
1503 | u32 av) | 1509 | u32 av) |
1504 | { | 1510 | { |
1505 | struct inode *inode = dentry->d_inode; | 1511 | struct inode *inode = dentry->d_inode; |
1506 | struct common_audit_data ad; | 1512 | struct common_audit_data ad; |
1507 | 1513 | ||
1508 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 1514 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
1509 | ad.u.fs.path.mnt = mnt; | 1515 | ad.u.dentry = dentry; |
1510 | ad.u.fs.path.dentry = dentry; | 1516 | return inode_has_perm(cred, inode, av, &ad, 0); |
1517 | } | ||
1518 | |||
1519 | /* Same as inode_has_perm, but pass explicit audit data containing | ||
1520 | the path to help the auditing code to more easily generate the | ||
1521 | pathname if needed. */ | ||
1522 | static inline int path_has_perm(const struct cred *cred, | ||
1523 | struct path *path, | ||
1524 | u32 av) | ||
1525 | { | ||
1526 | struct inode *inode = path->dentry->d_inode; | ||
1527 | struct common_audit_data ad; | ||
1528 | |||
1529 | COMMON_AUDIT_DATA_INIT(&ad, PATH); | ||
1530 | ad.u.path = *path; | ||
1511 | return inode_has_perm(cred, inode, av, &ad, 0); | 1531 | return inode_has_perm(cred, inode, av, &ad, 0); |
1512 | } | 1532 | } |
1513 | 1533 | ||
@@ -1529,8 +1549,8 @@ static int file_has_perm(const struct cred *cred, | |||
1529 | u32 sid = cred_sid(cred); | 1549 | u32 sid = cred_sid(cred); |
1530 | int rc; | 1550 | int rc; |
1531 | 1551 | ||
1532 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 1552 | COMMON_AUDIT_DATA_INIT(&ad, PATH); |
1533 | ad.u.fs.path = file->f_path; | 1553 | ad.u.path = file->f_path; |
1534 | 1554 | ||
1535 | if (sid != fsec->sid) { | 1555 | if (sid != fsec->sid) { |
1536 | rc = avc_has_perm(sid, fsec->sid, | 1556 | rc = avc_has_perm(sid, fsec->sid, |
@@ -1568,8 +1588,8 @@ static int may_create(struct inode *dir, | |||
1568 | sid = tsec->sid; | 1588 | sid = tsec->sid; |
1569 | newsid = tsec->create_sid; | 1589 | newsid = tsec->create_sid; |
1570 | 1590 | ||
1571 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 1591 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
1572 | ad.u.fs.path.dentry = dentry; | 1592 | ad.u.dentry = dentry; |
1573 | 1593 | ||
1574 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, | 1594 | rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR, |
1575 | DIR__ADD_NAME | DIR__SEARCH, | 1595 | DIR__ADD_NAME | DIR__SEARCH, |
@@ -1621,8 +1641,8 @@ static int may_link(struct inode *dir, | |||
1621 | dsec = dir->i_security; | 1641 | dsec = dir->i_security; |
1622 | isec = dentry->d_inode->i_security; | 1642 | isec = dentry->d_inode->i_security; |
1623 | 1643 | ||
1624 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 1644 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
1625 | ad.u.fs.path.dentry = dentry; | 1645 | ad.u.dentry = dentry; |
1626 | 1646 | ||
1627 | av = DIR__SEARCH; | 1647 | av = DIR__SEARCH; |
1628 | av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); | 1648 | av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME); |
@@ -1667,9 +1687,9 @@ static inline int may_rename(struct inode *old_dir, | |||
1667 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); | 1687 | old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode); |
1668 | new_dsec = new_dir->i_security; | 1688 | new_dsec = new_dir->i_security; |
1669 | 1689 | ||
1670 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 1690 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
1671 | 1691 | ||
1672 | ad.u.fs.path.dentry = old_dentry; | 1692 | ad.u.dentry = old_dentry; |
1673 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, | 1693 | rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR, |
1674 | DIR__REMOVE_NAME | DIR__SEARCH, &ad); | 1694 | DIR__REMOVE_NAME | DIR__SEARCH, &ad); |
1675 | if (rc) | 1695 | if (rc) |
@@ -1685,7 +1705,7 @@ static inline int may_rename(struct inode *old_dir, | |||
1685 | return rc; | 1705 | return rc; |
1686 | } | 1706 | } |
1687 | 1707 | ||
1688 | ad.u.fs.path.dentry = new_dentry; | 1708 | ad.u.dentry = new_dentry; |
1689 | av = DIR__ADD_NAME | DIR__SEARCH; | 1709 | av = DIR__ADD_NAME | DIR__SEARCH; |
1690 | if (new_dentry->d_inode) | 1710 | if (new_dentry->d_inode) |
1691 | av |= DIR__REMOVE_NAME; | 1711 | av |= DIR__REMOVE_NAME; |
@@ -1895,7 +1915,7 @@ static int selinux_quota_on(struct dentry *dentry) | |||
1895 | { | 1915 | { |
1896 | const struct cred *cred = current_cred(); | 1916 | const struct cred *cred = current_cred(); |
1897 | 1917 | ||
1898 | return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON); | 1918 | return dentry_has_perm(cred, dentry, FILE__QUOTAON); |
1899 | } | 1919 | } |
1900 | 1920 | ||
1901 | static int selinux_syslog(int type) | 1921 | static int selinux_syslog(int type) |
@@ -1992,8 +2012,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm) | |||
1992 | return rc; | 2012 | return rc; |
1993 | } | 2013 | } |
1994 | 2014 | ||
1995 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 2015 | COMMON_AUDIT_DATA_INIT(&ad, PATH); |
1996 | ad.u.fs.path = bprm->file->f_path; | 2016 | ad.u.path = bprm->file->f_path; |
1997 | 2017 | ||
1998 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) | 2018 | if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) |
1999 | new_tsec->sid = old_tsec->sid; | 2019 | new_tsec->sid = old_tsec->sid; |
@@ -2107,8 +2127,8 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2107 | struct tty_file_private, list); | 2127 | struct tty_file_private, list); |
2108 | file = file_priv->file; | 2128 | file = file_priv->file; |
2109 | inode = file->f_path.dentry->d_inode; | 2129 | inode = file->f_path.dentry->d_inode; |
2110 | if (inode_has_perm(cred, inode, | 2130 | if (inode_has_perm_noadp(cred, inode, |
2111 | FILE__READ | FILE__WRITE, NULL, 0)) { | 2131 | FILE__READ | FILE__WRITE, 0)) { |
2112 | drop_tty = 1; | 2132 | drop_tty = 1; |
2113 | } | 2133 | } |
2114 | } | 2134 | } |
@@ -2121,7 +2141,7 @@ static inline void flush_unauthorized_files(const struct cred *cred, | |||
2121 | 2141 | ||
2122 | /* Revalidate access to inherited open files. */ | 2142 | /* Revalidate access to inherited open files. */ |
2123 | 2143 | ||
2124 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 2144 | COMMON_AUDIT_DATA_INIT(&ad, INODE); |
2125 | 2145 | ||
2126 | spin_lock(&files->file_lock); | 2146 | spin_lock(&files->file_lock); |
2127 | for (;;) { | 2147 | for (;;) { |
@@ -2469,8 +2489,8 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
2469 | if (flags & MS_KERNMOUNT) | 2489 | if (flags & MS_KERNMOUNT) |
2470 | return 0; | 2490 | return 0; |
2471 | 2491 | ||
2472 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 2492 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
2473 | ad.u.fs.path.dentry = sb->s_root; | 2493 | ad.u.dentry = sb->s_root; |
2474 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); | 2494 | return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad); |
2475 | } | 2495 | } |
2476 | 2496 | ||
@@ -2479,8 +2499,8 @@ static int selinux_sb_statfs(struct dentry *dentry) | |||
2479 | const struct cred *cred = current_cred(); | 2499 | const struct cred *cred = current_cred(); |
2480 | struct common_audit_data ad; | 2500 | struct common_audit_data ad; |
2481 | 2501 | ||
2482 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 2502 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
2483 | ad.u.fs.path.dentry = dentry->d_sb->s_root; | 2503 | ad.u.dentry = dentry->d_sb->s_root; |
2484 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); | 2504 | return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad); |
2485 | } | 2505 | } |
2486 | 2506 | ||
@@ -2496,8 +2516,7 @@ static int selinux_mount(char *dev_name, | |||
2496 | return superblock_has_perm(cred, path->mnt->mnt_sb, | 2516 | return superblock_has_perm(cred, path->mnt->mnt_sb, |
2497 | FILESYSTEM__REMOUNT, NULL); | 2517 | FILESYSTEM__REMOUNT, NULL); |
2498 | else | 2518 | else |
2499 | return dentry_has_perm(cred, path->mnt, path->dentry, | 2519 | return path_has_perm(cred, path, FILE__MOUNTON); |
2500 | FILE__MOUNTON); | ||
2501 | } | 2520 | } |
2502 | 2521 | ||
2503 | static int selinux_umount(struct vfsmount *mnt, int flags) | 2522 | static int selinux_umount(struct vfsmount *mnt, int flags) |
@@ -2630,14 +2649,14 @@ static int selinux_inode_readlink(struct dentry *dentry) | |||
2630 | { | 2649 | { |
2631 | const struct cred *cred = current_cred(); | 2650 | const struct cred *cred = current_cred(); |
2632 | 2651 | ||
2633 | return dentry_has_perm(cred, NULL, dentry, FILE__READ); | 2652 | return dentry_has_perm(cred, dentry, FILE__READ); |
2634 | } | 2653 | } |
2635 | 2654 | ||
2636 | static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata) | 2655 | static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata) |
2637 | { | 2656 | { |
2638 | const struct cred *cred = current_cred(); | 2657 | const struct cred *cred = current_cred(); |
2639 | 2658 | ||
2640 | return dentry_has_perm(cred, NULL, dentry, FILE__READ); | 2659 | return dentry_has_perm(cred, dentry, FILE__READ); |
2641 | } | 2660 | } |
2642 | 2661 | ||
2643 | static int selinux_inode_permission(struct inode *inode, int mask, unsigned flags) | 2662 | static int selinux_inode_permission(struct inode *inode, int mask, unsigned flags) |
@@ -2654,8 +2673,8 @@ static int selinux_inode_permission(struct inode *inode, int mask, unsigned flag | |||
2654 | if (!mask) | 2673 | if (!mask) |
2655 | return 0; | 2674 | return 0; |
2656 | 2675 | ||
2657 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 2676 | COMMON_AUDIT_DATA_INIT(&ad, INODE); |
2658 | ad.u.fs.inode = inode; | 2677 | ad.u.inode = inode; |
2659 | 2678 | ||
2660 | if (from_access) | 2679 | if (from_access) |
2661 | ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS; | 2680 | ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS; |
@@ -2680,16 +2699,20 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | |||
2680 | 2699 | ||
2681 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | | 2700 | if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | |
2682 | ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) | 2701 | ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET)) |
2683 | return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR); | 2702 | return dentry_has_perm(cred, dentry, FILE__SETATTR); |
2684 | 2703 | ||
2685 | return dentry_has_perm(cred, NULL, dentry, FILE__WRITE); | 2704 | return dentry_has_perm(cred, dentry, FILE__WRITE); |
2686 | } | 2705 | } |
2687 | 2706 | ||
2688 | static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) | 2707 | static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry) |
2689 | { | 2708 | { |
2690 | const struct cred *cred = current_cred(); | 2709 | const struct cred *cred = current_cred(); |
2710 | struct path path; | ||
2711 | |||
2712 | path.dentry = dentry; | ||
2713 | path.mnt = mnt; | ||
2691 | 2714 | ||
2692 | return dentry_has_perm(cred, mnt, dentry, FILE__GETATTR); | 2715 | return path_has_perm(cred, &path, FILE__GETATTR); |
2693 | } | 2716 | } |
2694 | 2717 | ||
2695 | static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name) | 2718 | static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name) |
@@ -2710,7 +2733,7 @@ static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name) | |||
2710 | 2733 | ||
2711 | /* Not an attribute we recognize, so just check the | 2734 | /* Not an attribute we recognize, so just check the |
2712 | ordinary setattr permission. */ | 2735 | ordinary setattr permission. */ |
2713 | return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR); | 2736 | return dentry_has_perm(cred, dentry, FILE__SETATTR); |
2714 | } | 2737 | } |
2715 | 2738 | ||
2716 | static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | 2739 | static int selinux_inode_setxattr(struct dentry *dentry, const char *name, |
@@ -2733,8 +2756,8 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name, | |||
2733 | if (!inode_owner_or_capable(inode)) | 2756 | if (!inode_owner_or_capable(inode)) |
2734 | return -EPERM; | 2757 | return -EPERM; |
2735 | 2758 | ||
2736 | COMMON_AUDIT_DATA_INIT(&ad, FS); | 2759 | COMMON_AUDIT_DATA_INIT(&ad, DENTRY); |
2737 | ad.u.fs.path.dentry = dentry; | 2760 | ad.u.dentry = dentry; |
2738 | 2761 | ||
2739 | rc = avc_has_perm(sid, isec->sid, isec->sclass, | 2762 | rc = avc_has_perm(sid, isec->sid, isec->sclass, |
2740 | FILE__RELABELFROM, &ad); | 2763 | FILE__RELABELFROM, &ad); |
@@ -2797,14 +2820,14 @@ static int selinux_inode_getxattr(struct dentry *dentry, const char *name) | |||
2797 | { | 2820 | { |
2798 | const struct cred *cred = current_cred(); | 2821 | const struct cred *cred = current_cred(); |
2799 | 2822 | ||
2800 | return dentry_has_perm(cred, NULL, dentry, FILE__GETATTR); | 2823 | return dentry_has_perm(cred, dentry, FILE__GETATTR); |
2801 | } | 2824 | } |
2802 | 2825 | ||
2803 | static int selinux_inode_listxattr(struct dentry *dentry) | 2826 | static int selinux_inode_listxattr(struct dentry *dentry) |
2804 | { | 2827 | { |
2805 | const struct cred *cred = current_cred(); | 2828 | const struct cred *cred = current_cred(); |
2806 | 2829 | ||
2807 | return dentry_has_perm(cred, NULL, dentry, FILE__GETATTR); | 2830 | return dentry_has_perm(cred, dentry, FILE__GETATTR); |
2808 | } | 2831 | } |
2809 | 2832 | ||
2810 | static int selinux_inode_removexattr(struct dentry *dentry, const char *name) | 2833 | static int selinux_inode_removexattr(struct dentry *dentry, const char *name) |
@@ -3210,7 +3233,7 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred) | |||
3210 | * new inode label or new policy. | 3233 | * new inode label or new policy. |
3211 | * This check is not redundant - do not remove. | 3234 | * This check is not redundant - do not remove. |
3212 | */ | 3235 | */ |
3213 | return inode_has_perm(cred, inode, open_file_to_av(file), NULL, 0); | 3236 | return inode_has_perm_noadp(cred, inode, open_file_to_av(file), 0); |
3214 | } | 3237 | } |
3215 | 3238 | ||
3216 | /* task security operations */ | 3239 | /* task security operations */ |