diff options
Diffstat (limited to 'security')
| -rw-r--r-- | security/selinux/hooks.c | 120 |
1 files changed, 18 insertions, 102 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6ae19fd28be5..c8b359fc2949 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -44,7 +44,6 @@ | |||
| 44 | #include <linux/fdtable.h> | 44 | #include <linux/fdtable.h> |
| 45 | #include <linux/namei.h> | 45 | #include <linux/namei.h> |
| 46 | #include <linux/mount.h> | 46 | #include <linux/mount.h> |
| 47 | #include <linux/proc_fs.h> | ||
| 48 | #include <linux/netfilter_ipv4.h> | 47 | #include <linux/netfilter_ipv4.h> |
| 49 | #include <linux/netfilter_ipv6.h> | 48 | #include <linux/netfilter_ipv6.h> |
| 50 | #include <linux/tty.h> | 49 | #include <linux/tty.h> |
| @@ -71,7 +70,6 @@ | |||
| 71 | #include <net/ipv6.h> | 70 | #include <net/ipv6.h> |
| 72 | #include <linux/hugetlb.h> | 71 | #include <linux/hugetlb.h> |
| 73 | #include <linux/personality.h> | 72 | #include <linux/personality.h> |
| 74 | #include <linux/sysctl.h> | ||
| 75 | #include <linux/audit.h> | 73 | #include <linux/audit.h> |
| 76 | #include <linux/string.h> | 74 | #include <linux/string.h> |
| 77 | #include <linux/selinux.h> | 75 | #include <linux/selinux.h> |
| @@ -1121,39 +1119,35 @@ static inline u16 socket_type_to_security_class(int family, int type, int protoc | |||
| 1121 | } | 1119 | } |
| 1122 | 1120 | ||
| 1123 | #ifdef CONFIG_PROC_FS | 1121 | #ifdef CONFIG_PROC_FS |
| 1124 | static int selinux_proc_get_sid(struct proc_dir_entry *de, | 1122 | static int selinux_proc_get_sid(struct dentry *dentry, |
| 1125 | u16 tclass, | 1123 | u16 tclass, |
| 1126 | u32 *sid) | 1124 | u32 *sid) |
| 1127 | { | 1125 | { |
| 1128 | int buflen, rc; | 1126 | int rc; |
| 1129 | char *buffer, *path, *end; | 1127 | char *buffer, *path; |
| 1130 | 1128 | ||
| 1131 | buffer = (char *)__get_free_page(GFP_KERNEL); | 1129 | buffer = (char *)__get_free_page(GFP_KERNEL); |
| 1132 | if (!buffer) | 1130 | if (!buffer) |
| 1133 | return -ENOMEM; | 1131 | return -ENOMEM; |
| 1134 | 1132 | ||
| 1135 | buflen = PAGE_SIZE; | 1133 | path = dentry_path_raw(dentry, buffer, PAGE_SIZE); |
| 1136 | end = buffer+buflen; | 1134 | if (IS_ERR(path)) |
| 1137 | *--end = '\0'; | 1135 | rc = PTR_ERR(path); |
| 1138 | buflen--; | 1136 | else { |
| 1139 | path = end-1; | 1137 | /* each process gets a /proc/PID/ entry. Strip off the |
| 1140 | *path = '/'; | 1138 | * PID part to get a valid selinux labeling. |
| 1141 | while (de && de != de->parent) { | 1139 | * e.g. /proc/1/net/rpc/nfs -> /net/rpc/nfs */ |
| 1142 | buflen -= de->namelen + 1; | 1140 | while (path[1] >= '0' && path[1] <= '9') { |
| 1143 | if (buflen < 0) | 1141 | path[1] = '/'; |
| 1144 | break; | 1142 | path++; |
| 1145 | end -= de->namelen; | 1143 | } |
| 1146 | memcpy(end, de->name, de->namelen); | 1144 | rc = security_genfs_sid("proc", path, tclass, sid); |
| 1147 | *--end = '/'; | ||
| 1148 | path = end; | ||
| 1149 | de = de->parent; | ||
| 1150 | } | 1145 | } |
| 1151 | rc = security_genfs_sid("proc", path, tclass, sid); | ||
| 1152 | free_page((unsigned long)buffer); | 1146 | free_page((unsigned long)buffer); |
| 1153 | return rc; | 1147 | return rc; |
| 1154 | } | 1148 | } |
| 1155 | #else | 1149 | #else |
| 1156 | static int selinux_proc_get_sid(struct proc_dir_entry *de, | 1150 | static int selinux_proc_get_sid(struct dentry *dentry, |
| 1157 | u16 tclass, | 1151 | u16 tclass, |
| 1158 | u32 *sid) | 1152 | u32 *sid) |
| 1159 | { | 1153 | { |
| @@ -1315,10 +1309,9 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent | |||
| 1315 | isec->sid = sbsec->sid; | 1309 | isec->sid = sbsec->sid; |
| 1316 | 1310 | ||
| 1317 | if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) { | 1311 | if ((sbsec->flags & SE_SBPROC) && !S_ISLNK(inode->i_mode)) { |
| 1318 | struct proc_inode *proci = PROC_I(inode); | 1312 | if (opt_dentry) { |
| 1319 | if (proci->pde) { | ||
| 1320 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | 1313 | isec->sclass = inode_mode_to_security_class(inode->i_mode); |
| 1321 | rc = selinux_proc_get_sid(proci->pde, | 1314 | rc = selinux_proc_get_sid(opt_dentry, |
| 1322 | isec->sclass, | 1315 | isec->sclass, |
| 1323 | &sid); | 1316 | &sid); |
| 1324 | if (rc) | 1317 | if (rc) |
| @@ -1861,82 +1854,6 @@ static int selinux_capable(struct task_struct *tsk, const struct cred *cred, | |||
| 1861 | return task_has_capability(tsk, cred, cap, audit); | 1854 | return task_has_capability(tsk, cred, cap, audit); |
| 1862 | } | 1855 | } |
| 1863 | 1856 | ||
| 1864 | static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid) | ||
| 1865 | { | ||
| 1866 | int buflen, rc; | ||
| 1867 | char *buffer, *path, *end; | ||
| 1868 | |||
| 1869 | rc = -ENOMEM; | ||
| 1870 | buffer = (char *)__get_free_page(GFP_KERNEL); | ||
| 1871 | if (!buffer) | ||
| 1872 | goto out; | ||
| 1873 | |||
| 1874 | buflen = PAGE_SIZE; | ||
| 1875 | end = buffer+buflen; | ||
| 1876 | *--end = '\0'; | ||
| 1877 | buflen--; | ||
| 1878 | path = end-1; | ||
| 1879 | *path = '/'; | ||
| 1880 | while (table) { | ||
| 1881 | const char *name = table->procname; | ||
| 1882 | size_t namelen = strlen(name); | ||
| 1883 | buflen -= namelen + 1; | ||
| 1884 | if (buflen < 0) | ||
| 1885 | goto out_free; | ||
| 1886 | end -= namelen; | ||
| 1887 | memcpy(end, name, namelen); | ||
| 1888 | *--end = '/'; | ||
| 1889 | path = end; | ||
| 1890 | table = table->parent; | ||
| 1891 | } | ||
| 1892 | buflen -= 4; | ||
| 1893 | if (buflen < 0) | ||
| 1894 | goto out_free; | ||
| 1895 | end -= 4; | ||
| 1896 | memcpy(end, "/sys", 4); | ||
| 1897 | path = end; | ||
| 1898 | rc = security_genfs_sid("proc", path, tclass, sid); | ||
| 1899 | out_free: | ||
| 1900 | free_page((unsigned long)buffer); | ||
| 1901 | out: | ||
| 1902 | return rc; | ||
| 1903 | } | ||
| 1904 | |||
| 1905 | static int selinux_sysctl(ctl_table *table, int op) | ||
| 1906 | { | ||
| 1907 | int error = 0; | ||
| 1908 | u32 av; | ||
| 1909 | u32 tsid, sid; | ||
| 1910 | int rc; | ||
| 1911 | |||
| 1912 | sid = current_sid(); | ||
| 1913 | |||
| 1914 | rc = selinux_sysctl_get_sid(table, (op == 0001) ? | ||
| 1915 | SECCLASS_DIR : SECCLASS_FILE, &tsid); | ||
| 1916 | if (rc) { | ||
| 1917 | /* Default to the well-defined sysctl SID. */ | ||
| 1918 | tsid = SECINITSID_SYSCTL; | ||
| 1919 | } | ||
| 1920 | |||
| 1921 | /* The op values are "defined" in sysctl.c, thereby creating | ||
| 1922 | * a bad coupling between this module and sysctl.c */ | ||
| 1923 | if (op == 001) { | ||
| 1924 | error = avc_has_perm(sid, tsid, | ||
| 1925 | SECCLASS_DIR, DIR__SEARCH, NULL); | ||
| 1926 | } else { | ||
| 1927 | av = 0; | ||
| 1928 | if (op & 004) | ||
| 1929 | av |= FILE__READ; | ||
| 1930 | if (op & 002) | ||
| 1931 | av |= FILE__WRITE; | ||
| 1932 | if (av) | ||
| 1933 | error = avc_has_perm(sid, tsid, | ||
| 1934 | SECCLASS_FILE, av, NULL); | ||
| 1935 | } | ||
| 1936 | |||
| 1937 | return error; | ||
| 1938 | } | ||
| 1939 | |||
| 1940 | static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb) | 1857 | static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb) |
| 1941 | { | 1858 | { |
| 1942 | const struct cred *cred = current_cred(); | 1859 | const struct cred *cred = current_cred(); |
| @@ -5398,7 +5315,6 @@ static struct security_operations selinux_ops = { | |||
| 5398 | .ptrace_traceme = selinux_ptrace_traceme, | 5315 | .ptrace_traceme = selinux_ptrace_traceme, |
| 5399 | .capget = selinux_capget, | 5316 | .capget = selinux_capget, |
| 5400 | .capset = selinux_capset, | 5317 | .capset = selinux_capset, |
| 5401 | .sysctl = selinux_sysctl, | ||
| 5402 | .capable = selinux_capable, | 5318 | .capable = selinux_capable, |
| 5403 | .quotactl = selinux_quotactl, | 5319 | .quotactl = selinux_quotactl, |
| 5404 | .quota_on = selinux_quota_on, | 5320 | .quota_on = selinux_quota_on, |
