diff options
Diffstat (limited to 'fs/btrfs/xattr.c')
-rw-r--r-- | fs/btrfs/xattr.c | 48 |
1 files changed, 45 insertions, 3 deletions
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c index 7f332e27089..a9d3bf4d268 100644 --- a/fs/btrfs/xattr.c +++ b/fs/btrfs/xattr.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/rwsem.h> | 22 | #include <linux/rwsem.h> |
23 | #include <linux/xattr.h> | 23 | #include <linux/xattr.h> |
24 | #include <linux/security.h> | ||
24 | #include "ctree.h" | 25 | #include "ctree.h" |
25 | #include "btrfs_inode.h" | 26 | #include "btrfs_inode.h" |
26 | #include "transaction.h" | 27 | #include "transaction.h" |
@@ -45,9 +46,12 @@ ssize_t __btrfs_getxattr(struct inode *inode, const char *name, | |||
45 | /* lookup the xattr by name */ | 46 | /* lookup the xattr by name */ |
46 | di = btrfs_lookup_xattr(NULL, root, path, inode->i_ino, name, | 47 | di = btrfs_lookup_xattr(NULL, root, path, inode->i_ino, name, |
47 | strlen(name), 0); | 48 | strlen(name), 0); |
48 | if (!di || IS_ERR(di)) { | 49 | if (!di) { |
49 | ret = -ENODATA; | 50 | ret = -ENODATA; |
50 | goto out; | 51 | goto out; |
52 | } else if (IS_ERR(di)) { | ||
53 | ret = PTR_ERR(di); | ||
54 | goto out; | ||
51 | } | 55 | } |
52 | 56 | ||
53 | leaf = path->nodes[0]; | 57 | leaf = path->nodes[0]; |
@@ -62,6 +66,14 @@ ssize_t __btrfs_getxattr(struct inode *inode, const char *name, | |||
62 | ret = -ERANGE; | 66 | ret = -ERANGE; |
63 | goto out; | 67 | goto out; |
64 | } | 68 | } |
69 | |||
70 | /* | ||
71 | * The way things are packed into the leaf is like this | ||
72 | * |struct btrfs_dir_item|name|data| | ||
73 | * where name is the xattr name, so security.foo, and data is the | ||
74 | * content of the xattr. data_ptr points to the location in memory | ||
75 | * where the data starts in the in memory leaf | ||
76 | */ | ||
65 | data_ptr = (unsigned long)((char *)(di + 1) + | 77 | data_ptr = (unsigned long)((char *)(di + 1) + |
66 | btrfs_dir_name_len(leaf, di)); | 78 | btrfs_dir_name_len(leaf, di)); |
67 | read_extent_buffer(leaf, buffer, data_ptr, | 79 | read_extent_buffer(leaf, buffer, data_ptr, |
@@ -86,7 +98,7 @@ int __btrfs_setxattr(struct inode *inode, const char *name, | |||
86 | if (!path) | 98 | if (!path) |
87 | return -ENOMEM; | 99 | return -ENOMEM; |
88 | 100 | ||
89 | trans = btrfs_start_transaction(root, 1); | 101 | trans = btrfs_join_transaction(root, 1); |
90 | btrfs_set_trans_block_group(trans, inode); | 102 | btrfs_set_trans_block_group(trans, inode); |
91 | 103 | ||
92 | /* first lets see if we already have this xattr */ | 104 | /* first lets see if we already have this xattr */ |
@@ -176,7 +188,6 @@ ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size) | |||
176 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 188 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
177 | if (ret < 0) | 189 | if (ret < 0) |
178 | goto err; | 190 | goto err; |
179 | ret = 0; | ||
180 | advance = 0; | 191 | advance = 0; |
181 | while (1) { | 192 | while (1) { |
182 | leaf = path->nodes[0]; | 193 | leaf = path->nodes[0]; |
@@ -320,3 +331,34 @@ int btrfs_removexattr(struct dentry *dentry, const char *name) | |||
320 | return -EOPNOTSUPP; | 331 | return -EOPNOTSUPP; |
321 | return __btrfs_setxattr(dentry->d_inode, name, NULL, 0, XATTR_REPLACE); | 332 | return __btrfs_setxattr(dentry->d_inode, name, NULL, 0, XATTR_REPLACE); |
322 | } | 333 | } |
334 | |||
335 | int btrfs_xattr_security_init(struct inode *inode, struct inode *dir) | ||
336 | { | ||
337 | int err; | ||
338 | size_t len; | ||
339 | void *value; | ||
340 | char *suffix; | ||
341 | char *name; | ||
342 | |||
343 | err = security_inode_init_security(inode, dir, &suffix, &value, &len); | ||
344 | if (err) { | ||
345 | if (err == -EOPNOTSUPP) | ||
346 | return 0; | ||
347 | return err; | ||
348 | } | ||
349 | |||
350 | name = kmalloc(XATTR_SECURITY_PREFIX_LEN + strlen(suffix) + 1, | ||
351 | GFP_NOFS); | ||
352 | if (!name) { | ||
353 | err = -ENOMEM; | ||
354 | } else { | ||
355 | strcpy(name, XATTR_SECURITY_PREFIX); | ||
356 | strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix); | ||
357 | err = __btrfs_setxattr(inode, name, value, len, 0); | ||
358 | kfree(name); | ||
359 | } | ||
360 | |||
361 | kfree(suffix); | ||
362 | kfree(value); | ||
363 | return err; | ||
364 | } | ||