aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfsplus
diff options
context:
space:
mode:
Diffstat (limited to 'fs/hfsplus')
-rw-r--r--fs/hfsplus/Makefile2
-rw-r--r--fs/hfsplus/dir.c4
-rw-r--r--fs/hfsplus/inode.c11
-rw-r--r--fs/hfsplus/xattr.c62
-rw-r--r--fs/hfsplus/xattr.h33
-rw-r--r--fs/hfsplus/xattr_security.c13
6 files changed, 99 insertions, 26 deletions
diff --git a/fs/hfsplus/Makefile b/fs/hfsplus/Makefile
index 09d278bb7b91..683fca2e5e65 100644
--- a/fs/hfsplus/Makefile
+++ b/fs/hfsplus/Makefile
@@ -7,3 +7,5 @@ obj-$(CONFIG_HFSPLUS_FS) += hfsplus.o
7hfsplus-objs := super.o options.o inode.o ioctl.o extents.o catalog.o dir.o btree.o \ 7hfsplus-objs := super.o options.o inode.o ioctl.o extents.o catalog.o dir.o btree.o \
8 bnode.o brec.o bfind.o tables.o unicode.o wrapper.o bitmap.o part_tbl.o \ 8 bnode.o brec.o bfind.o tables.o unicode.o wrapper.o bitmap.o part_tbl.o \
9 attributes.o xattr.o xattr_user.o xattr_security.o xattr_trusted.o 9 attributes.o xattr.o xattr_user.o xattr_security.o xattr_trusted.o
10
11hfsplus-$(CONFIG_HFSPLUS_FS_POSIX_ACL) += posix_acl.o
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index d8ce4bd17fc5..4a4fea002673 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -16,6 +16,7 @@
16#include "hfsplus_fs.h" 16#include "hfsplus_fs.h"
17#include "hfsplus_raw.h" 17#include "hfsplus_raw.h"
18#include "xattr.h" 18#include "xattr.h"
19#include "acl.h"
19 20
20static inline void hfsplus_instantiate(struct dentry *dentry, 21static inline void hfsplus_instantiate(struct dentry *dentry,
21 struct inode *inode, u32 cnid) 22 struct inode *inode, u32 cnid)
@@ -529,6 +530,9 @@ const struct inode_operations hfsplus_dir_inode_operations = {
529 .getxattr = generic_getxattr, 530 .getxattr = generic_getxattr,
530 .listxattr = hfsplus_listxattr, 531 .listxattr = hfsplus_listxattr,
531 .removexattr = hfsplus_removexattr, 532 .removexattr = hfsplus_removexattr,
533#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
534 .get_acl = hfsplus_get_posix_acl,
535#endif
532}; 536};
533 537
534const struct file_operations hfsplus_dir_operations = { 538const struct file_operations hfsplus_dir_operations = {
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index f833d35630ab..4d2edaea891c 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -19,6 +19,7 @@
19#include "hfsplus_fs.h" 19#include "hfsplus_fs.h"
20#include "hfsplus_raw.h" 20#include "hfsplus_raw.h"
21#include "xattr.h" 21#include "xattr.h"
22#include "acl.h"
22 23
23static int hfsplus_readpage(struct file *file, struct page *page) 24static int hfsplus_readpage(struct file *file, struct page *page)
24{ 25{
@@ -316,6 +317,13 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr)
316 317
317 setattr_copy(inode, attr); 318 setattr_copy(inode, attr);
318 mark_inode_dirty(inode); 319 mark_inode_dirty(inode);
320
321 if (attr->ia_valid & ATTR_MODE) {
322 error = hfsplus_posix_acl_chmod(inode);
323 if (unlikely(error))
324 return error;
325 }
326
319 return 0; 327 return 0;
320} 328}
321 329
@@ -383,6 +391,9 @@ static const struct inode_operations hfsplus_file_inode_operations = {
383 .getxattr = generic_getxattr, 391 .getxattr = generic_getxattr,
384 .listxattr = hfsplus_listxattr, 392 .listxattr = hfsplus_listxattr,
385 .removexattr = hfsplus_removexattr, 393 .removexattr = hfsplus_removexattr,
394#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
395 .get_acl = hfsplus_get_posix_acl,
396#endif
386}; 397};
387 398
388static const struct file_operations hfsplus_file_operations = { 399static const struct file_operations hfsplus_file_operations = {
diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c
index f66346155df5..bd8471fb9a6a 100644
--- a/fs/hfsplus/xattr.c
+++ b/fs/hfsplus/xattr.c
@@ -8,11 +8,16 @@
8 8
9#include "hfsplus_fs.h" 9#include "hfsplus_fs.h"
10#include "xattr.h" 10#include "xattr.h"
11#include "acl.h"
11 12
12const struct xattr_handler *hfsplus_xattr_handlers[] = { 13const struct xattr_handler *hfsplus_xattr_handlers[] = {
13 &hfsplus_xattr_osx_handler, 14 &hfsplus_xattr_osx_handler,
14 &hfsplus_xattr_user_handler, 15 &hfsplus_xattr_user_handler,
15 &hfsplus_xattr_trusted_handler, 16 &hfsplus_xattr_trusted_handler,
17#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
18 &hfsplus_xattr_acl_access_handler,
19 &hfsplus_xattr_acl_default_handler,
20#endif
16 &hfsplus_xattr_security_handler, 21 &hfsplus_xattr_security_handler,
17 NULL 22 NULL
18}; 23};
@@ -46,11 +51,58 @@ static inline int is_known_namespace(const char *name)
46 return true; 51 return true;
47} 52}
48 53
54static int can_set_system_xattr(struct inode *inode, const char *name,
55 const void *value, size_t size)
56{
57#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
58 struct posix_acl *acl;
59 int err;
60
61 if (!inode_owner_or_capable(inode))
62 return -EPERM;
63
64 /*
65 * POSIX_ACL_XATTR_ACCESS is tied to i_mode
66 */
67 if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0) {
68 acl = posix_acl_from_xattr(&init_user_ns, value, size);
69 if (IS_ERR(acl))
70 return PTR_ERR(acl);
71 if (acl) {
72 err = posix_acl_equiv_mode(acl, &inode->i_mode);
73 posix_acl_release(acl);
74 if (err < 0)
75 return err;
76 mark_inode_dirty(inode);
77 }
78 /*
79 * We're changing the ACL. Get rid of the cached one
80 */
81 forget_cached_acl(inode, ACL_TYPE_ACCESS);
82
83 return 0;
84 } else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0) {
85 acl = posix_acl_from_xattr(&init_user_ns, value, size);
86 if (IS_ERR(acl))
87 return PTR_ERR(acl);
88 posix_acl_release(acl);
89
90 /*
91 * We're changing the default ACL. Get rid of the cached one
92 */
93 forget_cached_acl(inode, ACL_TYPE_DEFAULT);
94
95 return 0;
96 }
97#endif /* CONFIG_HFSPLUS_FS_POSIX_ACL */
98 return -EOPNOTSUPP;
99}
100
49static int can_set_xattr(struct inode *inode, const char *name, 101static int can_set_xattr(struct inode *inode, const char *name,
50 const void *value, size_t value_len) 102 const void *value, size_t value_len)
51{ 103{
52 if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN)) 104 if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
53 return -EOPNOTSUPP; /* TODO: implement ACL support */ 105 return can_set_system_xattr(inode, name, value, value_len);
54 106
55 if (!strncmp(name, XATTR_MAC_OSX_PREFIX, XATTR_MAC_OSX_PREFIX_LEN)) { 107 if (!strncmp(name, XATTR_MAC_OSX_PREFIX, XATTR_MAC_OSX_PREFIX_LEN)) {
56 /* 108 /*
@@ -253,11 +305,10 @@ static int copy_name(char *buffer, const char *xattr_name, int name_len)
253 return len; 305 return len;
254} 306}
255 307
256static ssize_t hfsplus_getxattr_finder_info(struct dentry *dentry, 308static ssize_t hfsplus_getxattr_finder_info(struct inode *inode,
257 void *value, size_t size) 309 void *value, size_t size)
258{ 310{
259 ssize_t res = 0; 311 ssize_t res = 0;
260 struct inode *inode = dentry->d_inode;
261 struct hfs_find_data fd; 312 struct hfs_find_data fd;
262 u16 entry_type; 313 u16 entry_type;
263 u16 folder_rec_len = sizeof(struct DInfo) + sizeof(struct DXInfo); 314 u16 folder_rec_len = sizeof(struct DInfo) + sizeof(struct DXInfo);
@@ -304,10 +355,9 @@ end_getxattr_finder_info:
304 return res; 355 return res;
305} 356}
306 357
307ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name, 358ssize_t __hfsplus_getxattr(struct inode *inode, const char *name,
308 void *value, size_t size) 359 void *value, size_t size)
309{ 360{
310 struct inode *inode = dentry->d_inode;
311 struct hfs_find_data fd; 361 struct hfs_find_data fd;
312 hfsplus_attr_entry *entry; 362 hfsplus_attr_entry *entry;
313 __be32 xattr_record_type; 363 __be32 xattr_record_type;
@@ -333,7 +383,7 @@ ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name,
333 } 383 }
334 384
335 if (!strcmp_xattr_finder_info(name)) 385 if (!strcmp_xattr_finder_info(name))
336 return hfsplus_getxattr_finder_info(dentry, value, size); 386 return hfsplus_getxattr_finder_info(inode, value, size);
337 387
338 if (!HFSPLUS_SB(inode->i_sb)->attr_tree) 388 if (!HFSPLUS_SB(inode->i_sb)->attr_tree)
339 return -EOPNOTSUPP; 389 return -EOPNOTSUPP;
diff --git a/fs/hfsplus/xattr.h b/fs/hfsplus/xattr.h
index 847b695b984d..841b5698c0fc 100644
--- a/fs/hfsplus/xattr.h
+++ b/fs/hfsplus/xattr.h
@@ -14,8 +14,8 @@
14extern const struct xattr_handler hfsplus_xattr_osx_handler; 14extern const struct xattr_handler hfsplus_xattr_osx_handler;
15extern const struct xattr_handler hfsplus_xattr_user_handler; 15extern const struct xattr_handler hfsplus_xattr_user_handler;
16extern const struct xattr_handler hfsplus_xattr_trusted_handler; 16extern const struct xattr_handler hfsplus_xattr_trusted_handler;
17/*extern const struct xattr_handler hfsplus_xattr_acl_access_handler;*/ 17extern const struct xattr_handler hfsplus_xattr_acl_access_handler;
18/*extern const struct xattr_handler hfsplus_xattr_acl_default_handler;*/ 18extern const struct xattr_handler hfsplus_xattr_acl_default_handler;
19extern const struct xattr_handler hfsplus_xattr_security_handler; 19extern const struct xattr_handler hfsplus_xattr_security_handler;
20 20
21extern const struct xattr_handler *hfsplus_xattr_handlers[]; 21extern const struct xattr_handler *hfsplus_xattr_handlers[];
@@ -29,9 +29,17 @@ static inline int hfsplus_setxattr(struct dentry *dentry, const char *name,
29 return __hfsplus_setxattr(dentry->d_inode, name, value, size, flags); 29 return __hfsplus_setxattr(dentry->d_inode, name, value, size, flags);
30} 30}
31 31
32ssize_t hfsplus_getxattr(struct dentry *dentry, const char *name, 32ssize_t __hfsplus_getxattr(struct inode *inode, const char *name,
33 void *value, size_t size); 33 void *value, size_t size);
34 34
35static inline ssize_t hfsplus_getxattr(struct dentry *dentry,
36 const char *name,
37 void *value,
38 size_t size)
39{
40 return __hfsplus_getxattr(dentry->d_inode, name, value, size);
41}
42
35ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size); 43ssize_t hfsplus_listxattr(struct dentry *dentry, char *buffer, size_t size);
36 44
37int hfsplus_removexattr(struct dentry *dentry, const char *name); 45int hfsplus_removexattr(struct dentry *dentry, const char *name);
@@ -39,22 +47,7 @@ int hfsplus_removexattr(struct dentry *dentry, const char *name);
39int hfsplus_init_security(struct inode *inode, struct inode *dir, 47int hfsplus_init_security(struct inode *inode, struct inode *dir,
40 const struct qstr *qstr); 48 const struct qstr *qstr);
41 49
42static inline int hfsplus_init_acl(struct inode *inode, struct inode *dir) 50int hfsplus_init_inode_security(struct inode *inode, struct inode *dir,
43{ 51 const struct qstr *qstr);
44 /*TODO: implement*/
45 return 0;
46}
47
48static inline int hfsplus_init_inode_security(struct inode *inode,
49 struct inode *dir,
50 const struct qstr *qstr)
51{
52 int err;
53
54 err = hfsplus_init_acl(inode, dir);
55 if (!err)
56 err = hfsplus_init_security(inode, dir, qstr);
57 return err;
58}
59 52
60#endif 53#endif
diff --git a/fs/hfsplus/xattr_security.c b/fs/hfsplus/xattr_security.c
index 83b842f113c5..00722765ea79 100644
--- a/fs/hfsplus/xattr_security.c
+++ b/fs/hfsplus/xattr_security.c
@@ -9,6 +9,7 @@
9#include <linux/security.h> 9#include <linux/security.h>
10#include "hfsplus_fs.h" 10#include "hfsplus_fs.h"
11#include "xattr.h" 11#include "xattr.h"
12#include "acl.h"
12 13
13static int hfsplus_security_getxattr(struct dentry *dentry, const char *name, 14static int hfsplus_security_getxattr(struct dentry *dentry, const char *name,
14 void *buffer, size_t size, int type) 15 void *buffer, size_t size, int type)
@@ -96,6 +97,18 @@ int hfsplus_init_security(struct inode *inode, struct inode *dir,
96 &hfsplus_initxattrs, NULL); 97 &hfsplus_initxattrs, NULL);
97} 98}
98 99
100int hfsplus_init_inode_security(struct inode *inode,
101 struct inode *dir,
102 const struct qstr *qstr)
103{
104 int err;
105
106 err = hfsplus_init_posix_acl(inode, dir);
107 if (!err)
108 err = hfsplus_init_security(inode, dir, qstr);
109 return err;
110}
111
99const struct xattr_handler hfsplus_xattr_security_handler = { 112const struct xattr_handler hfsplus_xattr_security_handler = {
100 .prefix = XATTR_SECURITY_PREFIX, 113 .prefix = XATTR_SECURITY_PREFIX,
101 .list = hfsplus_security_listxattr, 114 .list = hfsplus_security_listxattr,