diff options
Diffstat (limited to 'fs/f2fs/xattr.c')
-rw-r--r-- | fs/f2fs/xattr.c | 68 |
1 files changed, 61 insertions, 7 deletions
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c index 0b02dce31356..3ab07ecd86ca 100644 --- a/fs/f2fs/xattr.c +++ b/fs/f2fs/xattr.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | #include <linux/rwsem.h> | 21 | #include <linux/rwsem.h> |
22 | #include <linux/f2fs_fs.h> | 22 | #include <linux/f2fs_fs.h> |
23 | #include <linux/security.h> | ||
23 | #include "f2fs.h" | 24 | #include "f2fs.h" |
24 | #include "xattr.h" | 25 | #include "xattr.h" |
25 | 26 | ||
@@ -43,6 +44,10 @@ static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list, | |||
43 | prefix = XATTR_TRUSTED_PREFIX; | 44 | prefix = XATTR_TRUSTED_PREFIX; |
44 | prefix_len = XATTR_TRUSTED_PREFIX_LEN; | 45 | prefix_len = XATTR_TRUSTED_PREFIX_LEN; |
45 | break; | 46 | break; |
47 | case F2FS_XATTR_INDEX_SECURITY: | ||
48 | prefix = XATTR_SECURITY_PREFIX; | ||
49 | prefix_len = XATTR_SECURITY_PREFIX_LEN; | ||
50 | break; | ||
46 | default: | 51 | default: |
47 | return -EINVAL; | 52 | return -EINVAL; |
48 | } | 53 | } |
@@ -50,7 +55,7 @@ static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list, | |||
50 | total_len = prefix_len + name_len + 1; | 55 | total_len = prefix_len + name_len + 1; |
51 | if (list && total_len <= list_size) { | 56 | if (list && total_len <= list_size) { |
52 | memcpy(list, prefix, prefix_len); | 57 | memcpy(list, prefix, prefix_len); |
53 | memcpy(list+prefix_len, name, name_len); | 58 | memcpy(list + prefix_len, name, name_len); |
54 | list[prefix_len + name_len] = '\0'; | 59 | list[prefix_len + name_len] = '\0'; |
55 | } | 60 | } |
56 | return total_len; | 61 | return total_len; |
@@ -70,13 +75,14 @@ static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name, | |||
70 | if (!capable(CAP_SYS_ADMIN)) | 75 | if (!capable(CAP_SYS_ADMIN)) |
71 | return -EPERM; | 76 | return -EPERM; |
72 | break; | 77 | break; |
78 | case F2FS_XATTR_INDEX_SECURITY: | ||
79 | break; | ||
73 | default: | 80 | default: |
74 | return -EINVAL; | 81 | return -EINVAL; |
75 | } | 82 | } |
76 | if (strcmp(name, "") == 0) | 83 | if (strcmp(name, "") == 0) |
77 | return -EINVAL; | 84 | return -EINVAL; |
78 | return f2fs_getxattr(dentry->d_inode, type, name, | 85 | return f2fs_getxattr(dentry->d_inode, type, name, buffer, size); |
79 | buffer, size); | ||
80 | } | 86 | } |
81 | 87 | ||
82 | static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name, | 88 | static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name, |
@@ -93,13 +99,15 @@ static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name, | |||
93 | if (!capable(CAP_SYS_ADMIN)) | 99 | if (!capable(CAP_SYS_ADMIN)) |
94 | return -EPERM; | 100 | return -EPERM; |
95 | break; | 101 | break; |
102 | case F2FS_XATTR_INDEX_SECURITY: | ||
103 | break; | ||
96 | default: | 104 | default: |
97 | return -EINVAL; | 105 | return -EINVAL; |
98 | } | 106 | } |
99 | if (strcmp(name, "") == 0) | 107 | if (strcmp(name, "") == 0) |
100 | return -EINVAL; | 108 | return -EINVAL; |
101 | 109 | ||
102 | return f2fs_setxattr(dentry->d_inode, type, name, value, size); | 110 | return f2fs_setxattr(dentry->d_inode, type, name, value, size, NULL); |
103 | } | 111 | } |
104 | 112 | ||
105 | static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list, | 113 | static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list, |
@@ -145,6 +153,31 @@ static int f2fs_xattr_advise_set(struct dentry *dentry, const char *name, | |||
145 | return 0; | 153 | return 0; |
146 | } | 154 | } |
147 | 155 | ||
156 | #ifdef CONFIG_F2FS_FS_SECURITY | ||
157 | static int f2fs_initxattrs(struct inode *inode, const struct xattr *xattr_array, | ||
158 | void *page) | ||
159 | { | ||
160 | const struct xattr *xattr; | ||
161 | int err = 0; | ||
162 | |||
163 | for (xattr = xattr_array; xattr->name != NULL; xattr++) { | ||
164 | err = f2fs_setxattr(inode, F2FS_XATTR_INDEX_SECURITY, | ||
165 | xattr->name, xattr->value, | ||
166 | xattr->value_len, (struct page *)page); | ||
167 | if (err < 0) | ||
168 | break; | ||
169 | } | ||
170 | return err; | ||
171 | } | ||
172 | |||
173 | int f2fs_init_security(struct inode *inode, struct inode *dir, | ||
174 | const struct qstr *qstr, struct page *ipage) | ||
175 | { | ||
176 | return security_inode_init_security(inode, dir, qstr, | ||
177 | &f2fs_initxattrs, ipage); | ||
178 | } | ||
179 | #endif | ||
180 | |||
148 | const struct xattr_handler f2fs_xattr_user_handler = { | 181 | const struct xattr_handler f2fs_xattr_user_handler = { |
149 | .prefix = XATTR_USER_PREFIX, | 182 | .prefix = XATTR_USER_PREFIX, |
150 | .flags = F2FS_XATTR_INDEX_USER, | 183 | .flags = F2FS_XATTR_INDEX_USER, |
@@ -169,6 +202,14 @@ const struct xattr_handler f2fs_xattr_advise_handler = { | |||
169 | .set = f2fs_xattr_advise_set, | 202 | .set = f2fs_xattr_advise_set, |
170 | }; | 203 | }; |
171 | 204 | ||
205 | const struct xattr_handler f2fs_xattr_security_handler = { | ||
206 | .prefix = XATTR_SECURITY_PREFIX, | ||
207 | .flags = F2FS_XATTR_INDEX_SECURITY, | ||
208 | .list = f2fs_xattr_generic_list, | ||
209 | .get = f2fs_xattr_generic_get, | ||
210 | .set = f2fs_xattr_generic_set, | ||
211 | }; | ||
212 | |||
172 | static const struct xattr_handler *f2fs_xattr_handler_map[] = { | 213 | static const struct xattr_handler *f2fs_xattr_handler_map[] = { |
173 | [F2FS_XATTR_INDEX_USER] = &f2fs_xattr_user_handler, | 214 | [F2FS_XATTR_INDEX_USER] = &f2fs_xattr_user_handler, |
174 | #ifdef CONFIG_F2FS_FS_POSIX_ACL | 215 | #ifdef CONFIG_F2FS_FS_POSIX_ACL |
@@ -176,6 +217,9 @@ static const struct xattr_handler *f2fs_xattr_handler_map[] = { | |||
176 | [F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &f2fs_xattr_acl_default_handler, | 217 | [F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &f2fs_xattr_acl_default_handler, |
177 | #endif | 218 | #endif |
178 | [F2FS_XATTR_INDEX_TRUSTED] = &f2fs_xattr_trusted_handler, | 219 | [F2FS_XATTR_INDEX_TRUSTED] = &f2fs_xattr_trusted_handler, |
220 | #ifdef CONFIG_F2FS_FS_SECURITY | ||
221 | [F2FS_XATTR_INDEX_SECURITY] = &f2fs_xattr_security_handler, | ||
222 | #endif | ||
179 | [F2FS_XATTR_INDEX_ADVISE] = &f2fs_xattr_advise_handler, | 223 | [F2FS_XATTR_INDEX_ADVISE] = &f2fs_xattr_advise_handler, |
180 | }; | 224 | }; |
181 | 225 | ||
@@ -186,6 +230,9 @@ const struct xattr_handler *f2fs_xattr_handlers[] = { | |||
186 | &f2fs_xattr_acl_default_handler, | 230 | &f2fs_xattr_acl_default_handler, |
187 | #endif | 231 | #endif |
188 | &f2fs_xattr_trusted_handler, | 232 | &f2fs_xattr_trusted_handler, |
233 | #ifdef CONFIG_F2FS_FS_SECURITY | ||
234 | &f2fs_xattr_security_handler, | ||
235 | #endif | ||
189 | &f2fs_xattr_advise_handler, | 236 | &f2fs_xattr_advise_handler, |
190 | NULL, | 237 | NULL, |
191 | }; | 238 | }; |
@@ -218,6 +265,8 @@ int f2fs_getxattr(struct inode *inode, int name_index, const char *name, | |||
218 | return -ENODATA; | 265 | return -ENODATA; |
219 | 266 | ||
220 | page = get_node_page(sbi, fi->i_xattr_nid); | 267 | page = get_node_page(sbi, fi->i_xattr_nid); |
268 | if (IS_ERR(page)) | ||
269 | return PTR_ERR(page); | ||
221 | base_addr = page_address(page); | 270 | base_addr = page_address(page); |
222 | 271 | ||
223 | list_for_each_xattr(entry, base_addr) { | 272 | list_for_each_xattr(entry, base_addr) { |
@@ -268,6 +317,8 @@ ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) | |||
268 | return 0; | 317 | return 0; |
269 | 318 | ||
270 | page = get_node_page(sbi, fi->i_xattr_nid); | 319 | page = get_node_page(sbi, fi->i_xattr_nid); |
320 | if (IS_ERR(page)) | ||
321 | return PTR_ERR(page); | ||
271 | base_addr = page_address(page); | 322 | base_addr = page_address(page); |
272 | 323 | ||
273 | list_for_each_xattr(entry, base_addr) { | 324 | list_for_each_xattr(entry, base_addr) { |
@@ -296,7 +347,7 @@ cleanup: | |||
296 | } | 347 | } |
297 | 348 | ||
298 | int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | 349 | int f2fs_setxattr(struct inode *inode, int name_index, const char *name, |
299 | const void *value, size_t value_len) | 350 | const void *value, size_t value_len, struct page *ipage) |
300 | { | 351 | { |
301 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); | 352 | struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); |
302 | struct f2fs_inode_info *fi = F2FS_I(inode); | 353 | struct f2fs_inode_info *fi = F2FS_I(inode); |
@@ -335,7 +386,7 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | |||
335 | set_new_dnode(&dn, inode, NULL, NULL, fi->i_xattr_nid); | 386 | set_new_dnode(&dn, inode, NULL, NULL, fi->i_xattr_nid); |
336 | mark_inode_dirty(inode); | 387 | mark_inode_dirty(inode); |
337 | 388 | ||
338 | page = new_node_page(&dn, XATTR_NODE_OFFSET); | 389 | page = new_node_page(&dn, XATTR_NODE_OFFSET, ipage); |
339 | if (IS_ERR(page)) { | 390 | if (IS_ERR(page)) { |
340 | alloc_nid_failed(sbi, fi->i_xattr_nid); | 391 | alloc_nid_failed(sbi, fi->i_xattr_nid); |
341 | fi->i_xattr_nid = 0; | 392 | fi->i_xattr_nid = 0; |
@@ -435,7 +486,10 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name, | |||
435 | inode->i_ctime = CURRENT_TIME; | 486 | inode->i_ctime = CURRENT_TIME; |
436 | clear_inode_flag(fi, FI_ACL_MODE); | 487 | clear_inode_flag(fi, FI_ACL_MODE); |
437 | } | 488 | } |
438 | update_inode_page(inode); | 489 | if (ipage) |
490 | update_inode(inode, ipage); | ||
491 | else | ||
492 | update_inode_page(inode); | ||
439 | mutex_unlock_op(sbi, ilock); | 493 | mutex_unlock_op(sbi, ilock); |
440 | 494 | ||
441 | return 0; | 495 | return 0; |