diff options
-rw-r--r-- | include/linux/security.h | 41 | ||||
-rw-r--r-- | security/dummy.c | 7 | ||||
-rw-r--r-- | security/selinux/hooks.c | 59 | ||||
-rw-r--r-- | security/selinux/include/objsec.h | 1 |
4 files changed, 108 insertions, 0 deletions
diff --git a/include/linux/security.h b/include/linux/security.h index 7aab6ab7c57f..d4f3b7a94ea6 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -250,6 +250,25 @@ struct swap_info_struct; | |||
250 | * @inode contains the inode structure. | 250 | * @inode contains the inode structure. |
251 | * Deallocate the inode security structure and set @inode->i_security to | 251 | * Deallocate the inode security structure and set @inode->i_security to |
252 | * NULL. | 252 | * NULL. |
253 | * @inode_init_security: | ||
254 | * Obtain the security attribute name suffix and value to set on a newly | ||
255 | * created inode and set up the incore security field for the new inode. | ||
256 | * This hook is called by the fs code as part of the inode creation | ||
257 | * transaction and provides for atomic labeling of the inode, unlike | ||
258 | * the post_create/mkdir/... hooks called by the VFS. The hook function | ||
259 | * is expected to allocate the name and value via kmalloc, with the caller | ||
260 | * being responsible for calling kfree after using them. | ||
261 | * If the security module does not use security attributes or does | ||
262 | * not wish to put a security attribute on this particular inode, | ||
263 | * then it should return -EOPNOTSUPP to skip this processing. | ||
264 | * @inode contains the inode structure of the newly created inode. | ||
265 | * @dir contains the inode structure of the parent directory. | ||
266 | * @name will be set to the allocated name suffix (e.g. selinux). | ||
267 | * @value will be set to the allocated attribute value. | ||
268 | * @len will be set to the length of the value. | ||
269 | * Returns 0 if @name and @value have been successfully set, | ||
270 | * -EOPNOTSUPP if no security attribute is needed, or | ||
271 | * -ENOMEM on memory allocation failure. | ||
253 | * @inode_create: | 272 | * @inode_create: |
254 | * Check permission to create a regular file. | 273 | * Check permission to create a regular file. |
255 | * @dir contains inode structure of the parent of the new file. | 274 | * @dir contains inode structure of the parent of the new file. |
@@ -1080,6 +1099,8 @@ struct security_operations { | |||
1080 | 1099 | ||
1081 | int (*inode_alloc_security) (struct inode *inode); | 1100 | int (*inode_alloc_security) (struct inode *inode); |
1082 | void (*inode_free_security) (struct inode *inode); | 1101 | void (*inode_free_security) (struct inode *inode); |
1102 | int (*inode_init_security) (struct inode *inode, struct inode *dir, | ||
1103 | char **name, void **value, size_t *len); | ||
1083 | int (*inode_create) (struct inode *dir, | 1104 | int (*inode_create) (struct inode *dir, |
1084 | struct dentry *dentry, int mode); | 1105 | struct dentry *dentry, int mode); |
1085 | void (*inode_post_create) (struct inode *dir, | 1106 | void (*inode_post_create) (struct inode *dir, |
@@ -1442,6 +1463,17 @@ static inline void security_inode_free (struct inode *inode) | |||
1442 | return; | 1463 | return; |
1443 | security_ops->inode_free_security (inode); | 1464 | security_ops->inode_free_security (inode); |
1444 | } | 1465 | } |
1466 | |||
1467 | static inline int security_inode_init_security (struct inode *inode, | ||
1468 | struct inode *dir, | ||
1469 | char **name, | ||
1470 | void **value, | ||
1471 | size_t *len) | ||
1472 | { | ||
1473 | if (unlikely (IS_PRIVATE (inode))) | ||
1474 | return -EOPNOTSUPP; | ||
1475 | return security_ops->inode_init_security (inode, dir, name, value, len); | ||
1476 | } | ||
1445 | 1477 | ||
1446 | static inline int security_inode_create (struct inode *dir, | 1478 | static inline int security_inode_create (struct inode *dir, |
1447 | struct dentry *dentry, | 1479 | struct dentry *dentry, |
@@ -2171,6 +2203,15 @@ static inline int security_inode_alloc (struct inode *inode) | |||
2171 | 2203 | ||
2172 | static inline void security_inode_free (struct inode *inode) | 2204 | static inline void security_inode_free (struct inode *inode) |
2173 | { } | 2205 | { } |
2206 | |||
2207 | static inline int security_inode_init_security (struct inode *inode, | ||
2208 | struct inode *dir, | ||
2209 | char **name, | ||
2210 | void **value, | ||
2211 | size_t *len) | ||
2212 | { | ||
2213 | return -EOPNOTSUPP; | ||
2214 | } | ||
2174 | 2215 | ||
2175 | static inline int security_inode_create (struct inode *dir, | 2216 | static inline int security_inode_create (struct inode *dir, |
2176 | struct dentry *dentry, | 2217 | struct dentry *dentry, |
diff --git a/security/dummy.c b/security/dummy.c index 6ff887586479..e8a00fa80469 100644 --- a/security/dummy.c +++ b/security/dummy.c | |||
@@ -258,6 +258,12 @@ static void dummy_inode_free_security (struct inode *inode) | |||
258 | return; | 258 | return; |
259 | } | 259 | } |
260 | 260 | ||
261 | static int dummy_inode_init_security (struct inode *inode, struct inode *dir, | ||
262 | char **name, void **value, size_t *len) | ||
263 | { | ||
264 | return -EOPNOTSUPP; | ||
265 | } | ||
266 | |||
261 | static int dummy_inode_create (struct inode *inode, struct dentry *dentry, | 267 | static int dummy_inode_create (struct inode *inode, struct dentry *dentry, |
262 | int mask) | 268 | int mask) |
263 | { | 269 | { |
@@ -886,6 +892,7 @@ void security_fixup_ops (struct security_operations *ops) | |||
886 | set_to_dummy_if_null(ops, sb_post_pivotroot); | 892 | set_to_dummy_if_null(ops, sb_post_pivotroot); |
887 | set_to_dummy_if_null(ops, inode_alloc_security); | 893 | set_to_dummy_if_null(ops, inode_alloc_security); |
888 | set_to_dummy_if_null(ops, inode_free_security); | 894 | set_to_dummy_if_null(ops, inode_free_security); |
895 | set_to_dummy_if_null(ops, inode_init_security); | ||
889 | set_to_dummy_if_null(ops, inode_create); | 896 | set_to_dummy_if_null(ops, inode_create); |
890 | set_to_dummy_if_null(ops, inode_post_create); | 897 | set_to_dummy_if_null(ops, inode_post_create); |
891 | set_to_dummy_if_null(ops, inode_link); | 898 | set_to_dummy_if_null(ops, inode_link); |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 8641f8894b4c..63701fe0e1ad 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -1274,6 +1274,7 @@ static int post_create(struct inode *dir, | |||
1274 | struct inode *inode; | 1274 | struct inode *inode; |
1275 | struct inode_security_struct *dsec; | 1275 | struct inode_security_struct *dsec; |
1276 | struct superblock_security_struct *sbsec; | 1276 | struct superblock_security_struct *sbsec; |
1277 | struct inode_security_struct *isec; | ||
1277 | u32 newsid; | 1278 | u32 newsid; |
1278 | char *context; | 1279 | char *context; |
1279 | unsigned int len; | 1280 | unsigned int len; |
@@ -1293,6 +1294,11 @@ static int post_create(struct inode *dir, | |||
1293 | return 0; | 1294 | return 0; |
1294 | } | 1295 | } |
1295 | 1296 | ||
1297 | isec = inode->i_security; | ||
1298 | |||
1299 | if (isec->security_attr_init) | ||
1300 | return 0; | ||
1301 | |||
1296 | if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { | 1302 | if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { |
1297 | newsid = tsec->create_sid; | 1303 | newsid = tsec->create_sid; |
1298 | } else { | 1304 | } else { |
@@ -2018,6 +2024,58 @@ static void selinux_inode_free_security(struct inode *inode) | |||
2018 | inode_free_security(inode); | 2024 | inode_free_security(inode); |
2019 | } | 2025 | } |
2020 | 2026 | ||
2027 | static int selinux_inode_init_security(struct inode *inode, struct inode *dir, | ||
2028 | char **name, void **value, | ||
2029 | size_t *len) | ||
2030 | { | ||
2031 | struct task_security_struct *tsec; | ||
2032 | struct inode_security_struct *dsec; | ||
2033 | struct superblock_security_struct *sbsec; | ||
2034 | struct inode_security_struct *isec; | ||
2035 | u32 newsid; | ||
2036 | int rc; | ||
2037 | char *namep, *context; | ||
2038 | |||
2039 | tsec = current->security; | ||
2040 | dsec = dir->i_security; | ||
2041 | sbsec = dir->i_sb->s_security; | ||
2042 | isec = inode->i_security; | ||
2043 | |||
2044 | if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) { | ||
2045 | newsid = tsec->create_sid; | ||
2046 | } else { | ||
2047 | rc = security_transition_sid(tsec->sid, dsec->sid, | ||
2048 | inode_mode_to_security_class(inode->i_mode), | ||
2049 | &newsid); | ||
2050 | if (rc) { | ||
2051 | printk(KERN_WARNING "%s: " | ||
2052 | "security_transition_sid failed, rc=%d (dev=%s " | ||
2053 | "ino=%ld)\n", | ||
2054 | __FUNCTION__, | ||
2055 | -rc, inode->i_sb->s_id, inode->i_ino); | ||
2056 | return rc; | ||
2057 | } | ||
2058 | } | ||
2059 | |||
2060 | inode_security_set_sid(inode, newsid); | ||
2061 | |||
2062 | namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_KERNEL); | ||
2063 | if (!namep) | ||
2064 | return -ENOMEM; | ||
2065 | *name = namep; | ||
2066 | |||
2067 | rc = security_sid_to_context(newsid, &context, len); | ||
2068 | if (rc) { | ||
2069 | kfree(namep); | ||
2070 | return rc; | ||
2071 | } | ||
2072 | *value = context; | ||
2073 | |||
2074 | isec->security_attr_init = 1; | ||
2075 | |||
2076 | return 0; | ||
2077 | } | ||
2078 | |||
2021 | static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask) | 2079 | static int selinux_inode_create(struct inode *dir, struct dentry *dentry, int mask) |
2022 | { | 2080 | { |
2023 | return may_create(dir, dentry, SECCLASS_FILE); | 2081 | return may_create(dir, dentry, SECCLASS_FILE); |
@@ -4298,6 +4356,7 @@ static struct security_operations selinux_ops = { | |||
4298 | 4356 | ||
4299 | .inode_alloc_security = selinux_inode_alloc_security, | 4357 | .inode_alloc_security = selinux_inode_alloc_security, |
4300 | .inode_free_security = selinux_inode_free_security, | 4358 | .inode_free_security = selinux_inode_free_security, |
4359 | .inode_init_security = selinux_inode_init_security, | ||
4301 | .inode_create = selinux_inode_create, | 4360 | .inode_create = selinux_inode_create, |
4302 | .inode_post_create = selinux_inode_post_create, | 4361 | .inode_post_create = selinux_inode_post_create, |
4303 | .inode_link = selinux_inode_link, | 4362 | .inode_link = selinux_inode_link, |
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 887937c8134a..c515bc0b58a1 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h | |||
@@ -46,6 +46,7 @@ struct inode_security_struct { | |||
46 | unsigned char initialized; /* initialization flag */ | 46 | unsigned char initialized; /* initialization flag */ |
47 | struct semaphore sem; | 47 | struct semaphore sem; |
48 | unsigned char inherit; /* inherit SID from parent entry */ | 48 | unsigned char inherit; /* inherit SID from parent entry */ |
49 | unsigned char security_attr_init; /* security attributes init flag */ | ||
49 | }; | 50 | }; |
50 | 51 | ||
51 | struct file_security_struct { | 52 | struct file_security_struct { |