diff options
author | Eric Paris <eparis@redhat.com> | 2008-10-29 17:06:46 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2008-10-30 11:00:52 -0400 |
commit | 8b6a5a37f87a414ef8636e36ec75accb27bb7508 (patch) | |
tree | 26ff1dddb3c8727118b24819e83b4b7c500ff595 | |
parent | 0da939b0058742ad2d8580b7db6b966d0fc72252 (diff) |
SELinux: check open perms in dentry_open not inode_permission
Some operations, like searching a directory path or connecting a unix domain
socket, make explicit calls into inode_permission. Our choices are to
either try to come up with a signature for all of the explicit calls to
inode_permission and do not check open on those, or to move the open checks to
dentry_open where we know this is always an open operation. This patch moves
the checks to dentry_open.
Signed-off-by: Eric Paris <eparis@redhat.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r-- | security/selinux/hooks.c | 59 |
1 files changed, 30 insertions, 29 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index c679ba653e1d..03ff7db2a2ca 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -1686,15 +1686,39 @@ static inline u32 file_mask_to_av(int mode, int mask) | |||
1686 | return av; | 1686 | return av; |
1687 | } | 1687 | } |
1688 | 1688 | ||
1689 | /* Convert a Linux file to an access vector. */ | ||
1690 | static inline u32 file_to_av(struct file *file) | ||
1691 | { | ||
1692 | u32 av = 0; | ||
1693 | |||
1694 | if (file->f_mode & FMODE_READ) | ||
1695 | av |= FILE__READ; | ||
1696 | if (file->f_mode & FMODE_WRITE) { | ||
1697 | if (file->f_flags & O_APPEND) | ||
1698 | av |= FILE__APPEND; | ||
1699 | else | ||
1700 | av |= FILE__WRITE; | ||
1701 | } | ||
1702 | if (!av) { | ||
1703 | /* | ||
1704 | * Special file opened with flags 3 for ioctl-only use. | ||
1705 | */ | ||
1706 | av = FILE__IOCTL; | ||
1707 | } | ||
1708 | |||
1709 | return av; | ||
1710 | } | ||
1711 | |||
1689 | /* | 1712 | /* |
1690 | * Convert a file mask to an access vector and include the correct open | 1713 | * Convert a file to an access vector and include the correct open |
1691 | * open permission. | 1714 | * open permission. |
1692 | */ | 1715 | */ |
1693 | static inline u32 open_file_mask_to_av(int mode, int mask) | 1716 | static inline u32 open_file_to_av(struct file *file) |
1694 | { | 1717 | { |
1695 | u32 av = file_mask_to_av(mode, mask); | 1718 | u32 av = file_to_av(file); |
1696 | 1719 | ||
1697 | if (selinux_policycap_openperm) { | 1720 | if (selinux_policycap_openperm) { |
1721 | mode_t mode = file->f_path.dentry->d_inode->i_mode; | ||
1698 | /* | 1722 | /* |
1699 | * lnk files and socks do not really have an 'open' | 1723 | * lnk files and socks do not really have an 'open' |
1700 | */ | 1724 | */ |
@@ -1710,34 +1734,11 @@ static inline u32 open_file_mask_to_av(int mode, int mask) | |||
1710 | av |= DIR__OPEN; | 1734 | av |= DIR__OPEN; |
1711 | else | 1735 | else |
1712 | printk(KERN_ERR "SELinux: WARNING: inside %s with " | 1736 | printk(KERN_ERR "SELinux: WARNING: inside %s with " |
1713 | "unknown mode:%x\n", __func__, mode); | 1737 | "unknown mode:%o\n", __func__, mode); |
1714 | } | 1738 | } |
1715 | return av; | 1739 | return av; |
1716 | } | 1740 | } |
1717 | 1741 | ||
1718 | /* Convert a Linux file to an access vector. */ | ||
1719 | static inline u32 file_to_av(struct file *file) | ||
1720 | { | ||
1721 | u32 av = 0; | ||
1722 | |||
1723 | if (file->f_mode & FMODE_READ) | ||
1724 | av |= FILE__READ; | ||
1725 | if (file->f_mode & FMODE_WRITE) { | ||
1726 | if (file->f_flags & O_APPEND) | ||
1727 | av |= FILE__APPEND; | ||
1728 | else | ||
1729 | av |= FILE__WRITE; | ||
1730 | } | ||
1731 | if (!av) { | ||
1732 | /* | ||
1733 | * Special file opened with flags 3 for ioctl-only use. | ||
1734 | */ | ||
1735 | av = FILE__IOCTL; | ||
1736 | } | ||
1737 | |||
1738 | return av; | ||
1739 | } | ||
1740 | |||
1741 | /* Hook functions begin here. */ | 1742 | /* Hook functions begin here. */ |
1742 | 1743 | ||
1743 | static int selinux_ptrace_may_access(struct task_struct *child, | 1744 | static int selinux_ptrace_may_access(struct task_struct *child, |
@@ -2654,7 +2655,7 @@ static int selinux_inode_permission(struct inode *inode, int mask) | |||
2654 | } | 2655 | } |
2655 | 2656 | ||
2656 | return inode_has_perm(current, inode, | 2657 | return inode_has_perm(current, inode, |
2657 | open_file_mask_to_av(inode->i_mode, mask), NULL); | 2658 | file_mask_to_av(inode->i_mode, mask), NULL); |
2658 | } | 2659 | } |
2659 | 2660 | ||
2660 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) | 2661 | static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr) |
@@ -3170,7 +3171,7 @@ static int selinux_dentry_open(struct file *file) | |||
3170 | * new inode label or new policy. | 3171 | * new inode label or new policy. |
3171 | * This check is not redundant - do not remove. | 3172 | * This check is not redundant - do not remove. |
3172 | */ | 3173 | */ |
3173 | return inode_has_perm(current, inode, file_to_av(file), NULL); | 3174 | return inode_has_perm(current, inode, open_file_to_av(file), NULL); |
3174 | } | 3175 | } |
3175 | 3176 | ||
3176 | /* task security operations */ | 3177 | /* task security operations */ |