aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJaegeuk Kim <jaegeuk.kim@samsung.com>2013-06-03 06:46:19 -0400
committerJaegeuk Kim <jaegeuk.kim@samsung.com>2013-06-11 03:01:03 -0400
commit8ae8f1627f39bae505b90cade50cd8a911b8bda6 (patch)
tree959ca29760d6e751bbf5913cc0339b61a23a1a3a /fs
parent5deb82671ae344b28b4e744020afcbc76df1779b (diff)
f2fs: support xattr security labels
This patch adds the support of security labels for f2fs, which will be used by Linus Security Models (LSMs). Quote from http://en.wikipedia.org/wiki/Linux_Security_Modules: "Linux Security Modules (LSM) is a framework that allows the Linux kernel to support a variety of computer security models while avoiding favoritism toward any single security implementation. The framework is licensed under the terms of the GNU General Public License and is standard part of the Linux kernel since Linux 2.6. AppArmor, SELinux, Smack and TOMOYO Linux are the currently accepted modules in the official kernel.". Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/f2fs/Kconfig12
-rw-r--r--fs/f2fs/acl.c2
-rw-r--r--fs/f2fs/dir.c5
-rw-r--r--fs/f2fs/f2fs.h2
-rw-r--r--fs/f2fs/node.c12
-rw-r--r--fs/f2fs/xattr.c64
-rw-r--r--fs/f2fs/xattr.h24
7 files changed, 100 insertions, 21 deletions
diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig
index fd27e7e6326e..e06e0995e00f 100644
--- a/fs/f2fs/Kconfig
+++ b/fs/f2fs/Kconfig
@@ -51,3 +51,15 @@ config F2FS_FS_POSIX_ACL
51 Linux website <http://acl.bestbits.at/>. 51 Linux website <http://acl.bestbits.at/>.
52 52
53 If you don't know what Access Control Lists are, say N 53 If you don't know what Access Control Lists are, say N
54
55config F2FS_FS_SECURITY
56 bool "F2FS Security Labels"
57 depends on F2FS_FS_XATTR
58 help
59 Security labels provide an access control facility to support Linux
60 Security Models (LSMs) accepted by AppArmor, SELinux, Smack and TOMOYO
61 Linux. This option enables an extended attribute handler for file
62 security labels in the f2fs filesystem, so that it requires enabling
63 the extended attribute support in advance.
64
65 If you are not using a security module, say N.
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index 44abc2f286e0..b7826ec1b470 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -250,7 +250,7 @@ static int f2fs_set_acl(struct inode *inode, int type, struct posix_acl *acl)
250 } 250 }
251 } 251 }
252 252
253 error = f2fs_setxattr(inode, name_index, "", value, size); 253 error = f2fs_setxattr(inode, name_index, "", value, size, NULL);
254 254
255 kfree(value); 255 kfree(value);
256 if (!error) 256 if (!error)
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 67e2d1361fa2..eaea5b50d9c1 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -13,6 +13,7 @@
13#include "f2fs.h" 13#include "f2fs.h"
14#include "node.h" 14#include "node.h"
15#include "acl.h" 15#include "acl.h"
16#include "xattr.h"
16 17
17static unsigned long dir_blocks(struct inode *inode) 18static unsigned long dir_blocks(struct inode *inode)
18{ 19{
@@ -334,6 +335,10 @@ static struct page *init_inode_metadata(struct inode *inode,
334 if (err) 335 if (err)
335 goto error; 336 goto error;
336 337
338 err = f2fs_init_security(inode, dir, name, page);
339 if (err)
340 goto error;
341
337 wait_on_page_writeback(page); 342 wait_on_page_writeback(page);
338 } else { 343 } else {
339 page = get_node_page(F2FS_SB(dir->i_sb), inode->i_ino); 344 page = get_node_page(F2FS_SB(dir->i_sb), inode->i_ino);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index d6e63da513cf..4f2c209ae8c1 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -968,7 +968,7 @@ int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int);
968int truncate_inode_blocks(struct inode *, pgoff_t); 968int truncate_inode_blocks(struct inode *, pgoff_t);
969int remove_inode_page(struct inode *); 969int remove_inode_page(struct inode *);
970struct page *new_inode_page(struct inode *, const struct qstr *); 970struct page *new_inode_page(struct inode *, const struct qstr *);
971struct page *new_node_page(struct dnode_of_data *, unsigned int); 971struct page *new_node_page(struct dnode_of_data *, unsigned int, struct page *);
972void ra_node_page(struct f2fs_sb_info *, nid_t); 972void ra_node_page(struct f2fs_sb_info *, nid_t);
973struct page *get_node_page(struct f2fs_sb_info *, pgoff_t); 973struct page *get_node_page(struct f2fs_sb_info *, pgoff_t);
974struct page *get_node_page_ra(struct page *, int); 974struct page *get_node_page_ra(struct page *, int);
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 5a59780b22d0..b02440c5b2eb 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -433,7 +433,7 @@ int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode)
433 } 433 }
434 434
435 dn->nid = nids[i]; 435 dn->nid = nids[i];
436 npage[i] = new_node_page(dn, noffset[i]); 436 npage[i] = new_node_page(dn, noffset[i], NULL);
437 if (IS_ERR(npage[i])) { 437 if (IS_ERR(npage[i])) {
438 alloc_nid_failed(sbi, nids[i]); 438 alloc_nid_failed(sbi, nids[i]);
439 err = PTR_ERR(npage[i]); 439 err = PTR_ERR(npage[i]);
@@ -814,10 +814,11 @@ struct page *new_inode_page(struct inode *inode, const struct qstr *name)
814 set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino); 814 set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino);
815 815
816 /* caller should f2fs_put_page(page, 1); */ 816 /* caller should f2fs_put_page(page, 1); */
817 return new_node_page(&dn, 0); 817 return new_node_page(&dn, 0, NULL);
818} 818}
819 819
820struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs) 820struct page *new_node_page(struct dnode_of_data *dn,
821 unsigned int ofs, struct page *ipage)
821{ 822{
822 struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); 823 struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb);
823 struct address_space *mapping = sbi->node_inode->i_mapping; 824 struct address_space *mapping = sbi->node_inode->i_mapping;
@@ -850,7 +851,10 @@ struct page *new_node_page(struct dnode_of_data *dn, unsigned int ofs)
850 set_cold_node(dn->inode, page); 851 set_cold_node(dn->inode, page);
851 852
852 dn->node_page = page; 853 dn->node_page = page;
853 sync_inode_page(dn); 854 if (ipage)
855 update_inode(dn->inode, ipage);
856 else
857 sync_inode_page(dn);
854 set_page_dirty(page); 858 set_page_dirty(page);
855 if (ofs == 0) 859 if (ofs == 0)
856 inc_valid_inode_count(sbi); 860 inc_valid_inode_count(sbi);
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index ae61f359554f..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
82static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name, 88static 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
105static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list, 113static 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
157static 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
173int 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
148const struct xattr_handler f2fs_xattr_user_handler = { 181const 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
205const 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
172static const struct xattr_handler *f2fs_xattr_handler_map[] = { 213static 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};
@@ -300,7 +347,7 @@ cleanup:
300} 347}
301 348
302int f2fs_setxattr(struct inode *inode, int name_index, const char *name, 349int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
303 const void *value, size_t value_len) 350 const void *value, size_t value_len, struct page *ipage)
304{ 351{
305 struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); 352 struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
306 struct f2fs_inode_info *fi = F2FS_I(inode); 353 struct f2fs_inode_info *fi = F2FS_I(inode);
@@ -339,7 +386,7 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
339 set_new_dnode(&dn, inode, NULL, NULL, fi->i_xattr_nid); 386 set_new_dnode(&dn, inode, NULL, NULL, fi->i_xattr_nid);
340 mark_inode_dirty(inode); 387 mark_inode_dirty(inode);
341 388
342 page = new_node_page(&dn, XATTR_NODE_OFFSET); 389 page = new_node_page(&dn, XATTR_NODE_OFFSET, ipage);
343 if (IS_ERR(page)) { 390 if (IS_ERR(page)) {
344 alloc_nid_failed(sbi, fi->i_xattr_nid); 391 alloc_nid_failed(sbi, fi->i_xattr_nid);
345 fi->i_xattr_nid = 0; 392 fi->i_xattr_nid = 0;
@@ -439,7 +486,10 @@ int f2fs_setxattr(struct inode *inode, int name_index, const char *name,
439 inode->i_ctime = CURRENT_TIME; 486 inode->i_ctime = CURRENT_TIME;
440 clear_inode_flag(fi, FI_ACL_MODE); 487 clear_inode_flag(fi, FI_ACL_MODE);
441 } 488 }
442 update_inode_page(inode); 489 if (ipage)
490 update_inode(inode, ipage);
491 else
492 update_inode_page(inode);
443 mutex_unlock_op(sbi, ilock); 493 mutex_unlock_op(sbi, ilock);
444 494
445 return 0; 495 return 0;
diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h
index 49c9558305e3..3c0817bef25d 100644
--- a/fs/f2fs/xattr.h
+++ b/fs/f2fs/xattr.h
@@ -112,21 +112,19 @@ extern const struct xattr_handler f2fs_xattr_trusted_handler;
112extern const struct xattr_handler f2fs_xattr_acl_access_handler; 112extern const struct xattr_handler f2fs_xattr_acl_access_handler;
113extern const struct xattr_handler f2fs_xattr_acl_default_handler; 113extern const struct xattr_handler f2fs_xattr_acl_default_handler;
114extern const struct xattr_handler f2fs_xattr_advise_handler; 114extern const struct xattr_handler f2fs_xattr_advise_handler;
115extern const struct xattr_handler f2fs_xattr_security_handler;
115 116
116extern const struct xattr_handler *f2fs_xattr_handlers[]; 117extern const struct xattr_handler *f2fs_xattr_handlers[];
117 118
118extern int f2fs_setxattr(struct inode *inode, int name_index, const char *name, 119extern int f2fs_setxattr(struct inode *, int, const char *,
119 const void *value, size_t value_len); 120 const void *, size_t, struct page *);
120extern int f2fs_getxattr(struct inode *inode, int name_index, const char *name, 121extern int f2fs_getxattr(struct inode *, int, const char *, void *, size_t);
121 void *buffer, size_t buffer_size); 122extern ssize_t f2fs_listxattr(struct dentry *, char *, size_t);
122extern ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer,
123 size_t buffer_size);
124
125#else 123#else
126 124
127#define f2fs_xattr_handlers NULL 125#define f2fs_xattr_handlers NULL
128static inline int f2fs_setxattr(struct inode *inode, int name_index, 126static inline int f2fs_setxattr(struct inode *inode, int name_index,
129 const char *name, const void *value, size_t value_len) 127 const char *name, const void *value, size_t value_len)
130{ 128{
131 return -EOPNOTSUPP; 129 return -EOPNOTSUPP;
132} 130}
@@ -142,4 +140,14 @@ static inline ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer,
142} 140}
143#endif 141#endif
144 142
143#ifdef CONFIG_F2FS_FS_SECURITY
144extern int f2fs_init_security(struct inode *, struct inode *,
145 const struct qstr *, struct page *);
146#else
147static inline int f2fs_init_security(struct inode *inode, struct inode *dir,
148 const struct qstr *qstr, struct page *ipage)
149{
150 return 0;
151}
152#endif
145#endif /* __F2FS_XATTR_H__ */ 153#endif /* __F2FS_XATTR_H__ */