diff options
Diffstat (limited to 'security/selinux/hooks.c')
| -rw-r--r-- | security/selinux/hooks.c | 178 |
1 files changed, 60 insertions, 118 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8641f8894b4c..f40c8221ec1b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -1265,85 +1265,6 @@ static int inode_security_set_sid(struct inode *inode, u32 sid) | |||
| 1265 | return 0; | 1265 | return 0; |
| 1266 | } | 1266 | } |
| 1267 | 1267 | ||
| 1268 | /* Set the security attributes on a newly created file. */ | ||
| 1269 | static int post_create(struct inode *dir, | ||
| 1270 | struct dentry *dentry) | ||
| 1271 | { | ||
| 1272 | |||
| 1273 | struct task_security_struct *tsec; | ||
| 1274 | struct inode *inode; | ||
| 1275 | struct inode_security_struct *dsec; | ||
| 1276 | struct superblock_security_struct *sbsec; | ||
| 1277 | u32 newsid; | ||
| 1278 | char *context; | ||
| 1279 | unsigned int len; | ||
| 1280 | int rc; | ||
| 1281 | |||
| 1282 | tsec = current->security; | ||
| 1283 | dsec = dir->i_security; | ||
| 1284 | sbsec = dir->i_sb->s_security; | ||
| 1285 | |||
| 1286 | inode = dentry->d_inode; | ||
| 1287 | if (!inode) { | ||
| 1288 | /* Some file system types (e.g. NFS) may not instantiate | ||
| 1289 | a dentry for all create operations (e.g. symlink), | ||
| 1290 | so we have to check to see if the inode is non-NULL. */ | ||
| 1291 | printk(KERN_WARNING "post_create: no inode, dir (dev=%s, " | ||
| 1292 | "ino=%ld)\n", dir->i_sb->s_id, dir->i_ino); | ||
| 1293 | return 0; | ||
| 1294 | } | ||
| 1295 | |||
| 1296 | if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { | ||
| 1297 | newsid = tsec->create_sid; | ||
| 1298 | } else { | ||
| 1299 | rc = security_transition_sid(tsec->sid, dsec->sid, | ||
| 1300 | inode_mode_to_security_class(inode->i_mode), | ||
| 1301 | &newsid); | ||
| 1302 | if (rc) { | ||
| 1303 | printk(KERN_WARNING "post_create: " | ||
| 1304 | "security_transition_sid failed, rc=%d (dev=%s " | ||
| 1305 | "ino=%ld)\n", | ||
| 1306 | -rc, inode->i_sb->s_id, inode->i_ino); | ||
| 1307 | return rc; | ||
| 1308 | } | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | rc = inode_security_set_sid(inode, newsid); | ||
| 1312 | if (rc) { | ||
| 1313 | printk(KERN_WARNING "post_create: inode_security_set_sid " | ||
| 1314 | "failed, rc=%d (dev=%s ino=%ld)\n", | ||
| 1315 | -rc, inode->i_sb->s_id, inode->i_ino); | ||
| 1316 | return rc; | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | if (sbsec->behavior == SECURITY_FS_USE_XATTR && | ||
| 1320 | inode->i_op->setxattr) { | ||
| 1321 | /* Use extended attributes. */ | ||
| 1322 | rc = security_sid_to_context(newsid, &context, &len); | ||
| 1323 | if (rc) { | ||
| 1324 | printk(KERN_WARNING "post_create: sid_to_context " | ||
| 1325 | "failed, rc=%d (dev=%s ino=%ld)\n", | ||
| 1326 | -rc, inode->i_sb->s_id, inode->i_ino); | ||
| 1327 | return rc; | ||
| 1328 | } | ||
| 1329 | down(&inode->i_sem); | ||
| 1330 | rc = inode->i_op->setxattr(dentry, | ||
| 1331 | XATTR_NAME_SELINUX, | ||
| 1332 | context, len, 0); | ||
| 1333 | up(&inode->i_sem); | ||
| 1334 | kfree(context); | ||
| 1335 | if (rc < 0) { | ||
| 1336 | printk(KERN_WARNING "post_create: setxattr failed, " | ||
| 1337 | "rc=%d (dev=%s ino=%ld)\n", | ||
| 1338 | -rc, inode->i_sb->s_id, inode->i_ino); | ||
| 1339 | return rc; | ||
| 1340 | } | ||
| 1341 | } | ||
| 1342 | |||
| 1343 | return 0; | ||
| 1344 | } | ||
| 1345 | |||
| 1346 | |||
| 1347 | /* Hook functions begin here. */ | 1268 | /* Hook functions begin here. */ |
| 1348 | 1269 | ||
| 1349 | static int selinux_ptrace(struct task_struct *parent, struct task_struct *child) | 1270 | static int selinux_ptrace(struct task_struct *parent, struct task_struct *child) |
| @@ -1673,6 +1594,7 @@ static inline void flush_unauthorized_files(struct files_struct * files) | |||
| 1673 | struct avc_audit_data ad; | 1594 | struct avc_audit_data ad; |
| 1674 | struct file *file, *devnull = NULL; | 1595 | struct file *file, *devnull = NULL; |
| 1675 | struct tty_struct *tty = current->signal->tty; | 1596 | struct tty_struct *tty = current->signal->tty; |
| 1597 | struct fdtable *fdt; | ||
| 1676 | long j = -1; | 1598 | long j = -1; |
| 1677 | 1599 | ||
| 1678 | if (tty) { | 1600 | if (tty) { |
| @@ -1706,9 +1628,10 @@ static inline void flush_unauthorized_files(struct files_struct * files) | |||
| 1706 | 1628 | ||
| 1707 | j++; | 1629 | j++; |
| 1708 | i = j * __NFDBITS; | 1630 | i = j * __NFDBITS; |
| 1709 | if (i >= files->max_fds || i >= files->max_fdset) | 1631 | fdt = files_fdtable(files); |
| 1632 | if (i >= fdt->max_fds || i >= fdt->max_fdset) | ||
| 1710 | break; | 1633 | break; |
| 1711 | set = files->open_fds->fds_bits[j]; | 1634 | set = fdt->open_fds->fds_bits[j]; |
| 1712 | if (!set) | 1635 | if (!set) |
| 1713 | continue; | 1636 | continue; |
| 1714 | spin_unlock(&files->file_lock); | 1637 | spin_unlock(&files->file_lock); |
| @@ -1729,7 +1652,7 @@ static inline void flush_unauthorized_files(struct files_struct * files) | |||
| 1729 | continue; | 1652 | continue; |
| 1730 | } | 1653 | } |
| 1731 | if (devnull) { | 1654 | if (devnull) { |
| 1732 | atomic_inc(&devnull->f_count); | 1655 | rcuref_inc(&devnull->f_count); |
| 1733 | } else { | 1656 | } else { |
| 1734 | devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR); | 1657 | devnull = dentry_open(dget(selinux_null), mntget(selinuxfs_mount), O_RDWR); |
| 1735 | if (!devnull) { | 1658 | if (!devnull) { |
| @@ -2018,14 +1941,64 @@ static void selinux_inode_free_security(struct inode *inode) | |||
| 2018 | inode_free_security(inode); | 1941 | inode_free_security(inode); |
| 2019 | } | 1942 | } |
| 2020 | 1943 | ||
| 2021 | static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask) | 1944 | static int selinux_inode_init_security(struct inode *inode, struct inode *dir, |
| 1945 | char **name, void **value, | ||
| 1946 | size_t *len) | ||
| 2022 | { | 1947 | { |
| 2023 | return may_create(dir, dentry, SECCLASS_FILE); | 1948 | struct task_security_struct *tsec; |
| 1949 | struct inode_security_struct *dsec; | ||
| 1950 | struct superblock_security_struct *sbsec; | ||
| 1951 | struct inode_security_struct *isec; | ||
| 1952 | u32 newsid, clen; | ||
| 1953 | int rc; | ||
| 1954 | char *namep = NULL, *context; | ||
| 1955 | |||
| 1956 | tsec = current->security; | ||
| 1957 | dsec = dir->i_security; | ||
| 1958 | sbsec = dir->i_sb->s_security; | ||
| 1959 | isec = inode->i_security; | ||
| 1960 | |||
| 1961 | if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { | ||
| 1962 | newsid = tsec->create_sid; | ||
| 1963 | } else { | ||
| 1964 | rc = security_transition_sid(tsec->sid, dsec->sid, | ||
| 1965 | inode_mode_to_security_class(inode->i_mode), | ||
| 1966 | &newsid); | ||
| 1967 | if (rc) { | ||
| 1968 | printk(KERN_WARNING "%s: " | ||
| 1969 | "security_transition_sid failed, rc=%d (dev=%s " | ||
| 1970 | "ino=%ld)\n", | ||
| 1971 | __FUNCTION__, | ||
| 1972 | -rc, inode->i_sb->s_id, inode->i_ino); | ||
| 1973 | return rc; | ||
| 1974 | } | ||
| 1975 | } | ||
| 1976 | |||
| 1977 | inode_security_set_sid(inode, newsid); | ||
| 1978 | |||
| 1979 | if (name) { | ||
| 1980 | namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_KERNEL); | ||
| 1981 | if (!namep) | ||
| 1982 | return -ENOMEM; | ||
| 1983 | *name = namep; | ||
| 1984 | } | ||
| 1985 | |||
| 1986 | if (value && len) { | ||
| 1987 | rc = security_sid_to_context(newsid, &context, &clen); | ||
| 1988 | if (rc) { | ||
| 1989 | kfree(namep); | ||
| 1990 | return rc; | ||
| 1991 | } | ||
| 1992 | *value = context; | ||
| 1993 | *len = clen; | ||
| 1994 | } | ||
| 1995 | |||
| 1996 | return 0; | ||
| 2024 | } | 1997 | } |
| 2025 | 1998 | ||
| 2026 | static void selinux_inode_post_create(struct inode *dir, struct dentry *dentry, int mask) | 1999 | static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask) |
| 2027 | { | 2000 | { |
| 2028 | post_create(dir, dentry); | 2001 | return may_create(dir, dentry, SECCLASS_FILE); |
| 2029 | } | 2002 | } |
| 2030 | 2003 | ||
| 2031 | static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) | 2004 | static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) |
| @@ -2038,11 +2011,6 @@ static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, stru | |||
| 2038 | return may_link(dir, old_dentry, MAY_LINK); | 2011 | return may_link(dir, old_dentry, MAY_LINK); |
| 2039 | } | 2012 | } |
| 2040 | 2013 | ||
| 2041 | static void selinux_inode_post_link(struct dentry *old_dentry, struct inode *inode, struct dentry *new_dentry) | ||
| 2042 | { | ||
| 2043 | return; | ||
| 2044 | } | ||
| 2045 | |||
| 2046 | static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry) | 2014 | static int selinux_inode_unlink(struct inode *dir, struct dentry *dentry) |
| 2047 | { | 2015 | { |
| 2048 | int rc; | 2016 | int rc; |
| @@ -2058,21 +2026,11 @@ static int selinux_inode_symlink(struct inode *dir, struct dentry *dentry, const | |||
| 2058 | return may_create(dir, dentry, SECCLASS_LNK_FILE); | 2026 | return may_create(dir, dentry, SECCLASS_LNK_FILE); |
| 2059 | } | 2027 | } |
| 2060 | 2028 | ||
| 2061 | static void selinux_inode_post_symlink(struct inode *dir, struct dentry *dentry, const char *name) | ||
| 2062 | { | ||
| 2063 | post_create(dir, dentry); | ||
| 2064 | } | ||
| 2065 | |||
| 2066 | static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask) | 2029 | static int selinux_inode_mkdir(struct inode *dir, struct dentry *dentry, int mask) |
| 2067 | { | 2030 | { |
| 2068 | return may_create(dir, dentry, SECCLASS_DIR); | 2031 | return may_create(dir, dentry, SECCLASS_DIR); |
| 2069 | } | 2032 | } |
| 2070 | 2033 | ||
| 2071 | static void selinux_inode_post_mkdir(struct inode *dir, struct dentry *dentry, int mask) | ||
| 2072 | { | ||
| 2073 | post_create(dir, dentry); | ||
| 2074 | } | ||
| 2075 | |||
| 2076 | static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry) | 2034 | static int selinux_inode_rmdir(struct inode *dir, struct dentry *dentry) |
| 2077 | { | 2035 | { |
| 2078 | return may_link(dir, dentry, MAY_RMDIR); | 2036 | return may_link(dir, dentry, MAY_RMDIR); |
| @@ -2089,23 +2047,12 @@ static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, int mod | |||
| 2089 | return may_create(dir, dentry, inode_mode_to_security_class(mode)); | 2047 | return may_create(dir, dentry, inode_mode_to_security_class(mode)); |
| 2090 | } | 2048 | } |
| 2091 | 2049 | ||
| 2092 | static void selinux_inode_post_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev) | ||
| 2093 | { | ||
| 2094 | post_create(dir, dentry); | ||
| 2095 | } | ||
| 2096 | |||
| 2097 | static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry, | 2050 | static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry, |
| 2098 | struct inode *new_inode, struct dentry *new_dentry) | 2051 | struct inode *new_inode, struct dentry *new_dentry) |
| 2099 | { | 2052 | { |
| 2100 | return may_rename(old_inode, old_dentry, new_inode, new_dentry); | 2053 | return may_rename(old_inode, old_dentry, new_inode, new_dentry); |
| 2101 | } | 2054 | } |
| 2102 | 2055 | ||
| 2103 | static void selinux_inode_post_rename(struct inode *old_inode, struct dentry *old_dentry, | ||
| 2104 | struct inode *new_inode, struct dentry *new_dentry) | ||
| 2105 | { | ||
| 2106 | return; | ||
| 2107 | } | ||
| 2108 | |||
| 2109 | static int selinux_inode_readlink(struct dentry *dentry) | 2056 | static int selinux_inode_readlink(struct dentry *dentry) |
| 2110 | { | 2057 | { |
| 2111 | return dentry_has_perm(current, NULL, dentry, FILE__READ); | 2058 | return dentry_has_perm(current, NULL, dentry, FILE__READ); |
| @@ -4298,20 +4245,15 @@ static struct security_operations selinux_ops = { | |||
| 4298 | 4245 | ||
| 4299 | .inode_alloc_security = selinux_inode_alloc_security, | 4246 | .inode_alloc_security = selinux_inode_alloc_security, |
| 4300 | .inode_free_security = selinux_inode_free_security, | 4247 | .inode_free_security = selinux_inode_free_security, |
| 4248 | .inode_init_security = selinux_inode_init_security, | ||
| 4301 | .inode_create = selinux_inode_create, | 4249 | .inode_create = selinux_inode_create, |
| 4302 | .inode_post_create = selinux_inode_post_create, | ||
| 4303 | .inode_link = selinux_inode_link, | 4250 | .inode_link = selinux_inode_link, |
| 4304 | .inode_post_link = selinux_inode_post_link, | ||
| 4305 | .inode_unlink = selinux_inode_unlink, | 4251 | .inode_unlink = selinux_inode_unlink, |
| 4306 | .inode_symlink = selinux_inode_symlink, | 4252 | .inode_symlink = selinux_inode_symlink, |
| 4307 | .inode_post_symlink = selinux_inode_post_symlink, | ||
| 4308 | .inode_mkdir = selinux_inode_mkdir, | 4253 | .inode_mkdir = selinux_inode_mkdir, |
| 4309 | .inode_post_mkdir = selinux_inode_post_mkdir, | ||
| 4310 | .inode_rmdir = selinux_inode_rmdir, | 4254 | .inode_rmdir = selinux_inode_rmdir, |
| 4311 | .inode_mknod = selinux_inode_mknod, | 4255 | .inode_mknod = selinux_inode_mknod, |
| 4312 | .inode_post_mknod = selinux_inode_post_mknod, | ||
| 4313 | .inode_rename = selinux_inode_rename, | 4256 | .inode_rename = selinux_inode_rename, |
| 4314 | .inode_post_rename = selinux_inode_post_rename, | ||
| 4315 | .inode_readlink = selinux_inode_readlink, | 4257 | .inode_readlink = selinux_inode_readlink, |
| 4316 | .inode_follow_link = selinux_inode_follow_link, | 4258 | .inode_follow_link = selinux_inode_follow_link, |
| 4317 | .inode_permission = selinux_inode_permission, | 4259 | .inode_permission = selinux_inode_permission, |
