aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hfsplus
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-01-28 11:38:04 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-01-28 11:38:04 -0500
commitbf3d846b783327359ddc4bd4f52627b36abb4d1d (patch)
treec6b8fddbf04a2962dfcf9f487af25033f11b10b9 /fs/hfsplus
parent54c0a4b46150db1571d955d598cd342c9f1d9657 (diff)
parentf6500801522c61782d4990fa1ad96154cb397cd4 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs updates from Al Viro: "Assorted stuff; the biggest pile here is Christoph's ACL series. Plus assorted cleanups and fixes all over the place... There will be another pile later this week" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (43 commits) __dentry_path() fixes vfs: Remove second variable named error in __dentry_path vfs: Is mounted should be testing mnt_ns for NULL or error. Fix race when checking i_size on direct i/o read hfsplus: remove can_set_xattr nfsd: use get_acl and ->set_acl fs: remove generic_acl nfs: use generic posix ACL infrastructure for v3 Posix ACLs gfs2: use generic posix ACL infrastructure jfs: use generic posix ACL infrastructure xfs: use generic posix ACL infrastructure reiserfs: use generic posix ACL infrastructure ocfs2: use generic posix ACL infrastructure jffs2: use generic posix ACL infrastructure hfsplus: use generic posix ACL infrastructure f2fs: use generic posix ACL infrastructure ext2/3/4: use generic posix ACL infrastructure btrfs: use generic posix ACL infrastructure fs: make posix_acl_create more useful fs: make posix_acl_chmod more useful ...
Diffstat (limited to 'fs/hfsplus')
-rw-r--r--fs/hfsplus/acl.h9
-rw-r--r--fs/hfsplus/dir.c1
-rw-r--r--fs/hfsplus/inode.c3
-rw-r--r--fs/hfsplus/posix_acl.c168
-rw-r--r--fs/hfsplus/xattr.c92
-rw-r--r--fs/hfsplus/xattr.h2
6 files changed, 29 insertions, 246 deletions
diff --git a/fs/hfsplus/acl.h b/fs/hfsplus/acl.h
index 07c0d4947527..95c8ed9ec17f 100644
--- a/fs/hfsplus/acl.h
+++ b/fs/hfsplus/acl.h
@@ -12,16 +12,13 @@
12 12
13/* posix_acl.c */ 13/* posix_acl.c */
14struct posix_acl *hfsplus_get_posix_acl(struct inode *inode, int type); 14struct posix_acl *hfsplus_get_posix_acl(struct inode *inode, int type);
15extern int hfsplus_posix_acl_chmod(struct inode *); 15int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl,
16 int type);
16extern int hfsplus_init_posix_acl(struct inode *, struct inode *); 17extern int hfsplus_init_posix_acl(struct inode *, struct inode *);
17 18
18#else /* CONFIG_HFSPLUS_FS_POSIX_ACL */ 19#else /* CONFIG_HFSPLUS_FS_POSIX_ACL */
19#define hfsplus_get_posix_acl NULL 20#define hfsplus_get_posix_acl NULL
20 21#define hfsplus_set_posix_acl NULL
21static inline int hfsplus_posix_acl_chmod(struct inode *inode)
22{
23 return 0;
24}
25 22
26static inline int hfsplus_init_posix_acl(struct inode *inode, struct inode *dir) 23static inline int hfsplus_init_posix_acl(struct inode *inode, struct inode *dir)
27{ 24{
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c
index 4a4fea002673..9ee62985e739 100644
--- a/fs/hfsplus/dir.c
+++ b/fs/hfsplus/dir.c
@@ -532,6 +532,7 @@ const struct inode_operations hfsplus_dir_inode_operations = {
532 .removexattr = hfsplus_removexattr, 532 .removexattr = hfsplus_removexattr,
533#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL 533#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
534 .get_acl = hfsplus_get_posix_acl, 534 .get_acl = hfsplus_get_posix_acl,
535 .set_acl = hfsplus_set_posix_acl,
535#endif 536#endif
536}; 537};
537 538
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c
index 3ebda928229c..4551cbd6bd43 100644
--- a/fs/hfsplus/inode.c
+++ b/fs/hfsplus/inode.c
@@ -261,7 +261,7 @@ static int hfsplus_setattr(struct dentry *dentry, struct iattr *attr)
261 mark_inode_dirty(inode); 261 mark_inode_dirty(inode);
262 262
263 if (attr->ia_valid & ATTR_MODE) { 263 if (attr->ia_valid & ATTR_MODE) {
264 error = hfsplus_posix_acl_chmod(inode); 264 error = posix_acl_chmod(inode, inode->i_mode);
265 if (unlikely(error)) 265 if (unlikely(error))
266 return error; 266 return error;
267 } 267 }
@@ -334,6 +334,7 @@ static const struct inode_operations hfsplus_file_inode_operations = {
334 .removexattr = hfsplus_removexattr, 334 .removexattr = hfsplus_removexattr,
335#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL 335#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
336 .get_acl = hfsplus_get_posix_acl, 336 .get_acl = hfsplus_get_posix_acl,
337 .set_acl = hfsplus_set_posix_acl,
337#endif 338#endif
338}; 339};
339 340
diff --git a/fs/hfsplus/posix_acl.c b/fs/hfsplus/posix_acl.c
index b609cc14c72e..df0c9af68d05 100644
--- a/fs/hfsplus/posix_acl.c
+++ b/fs/hfsplus/posix_acl.c
@@ -17,9 +17,7 @@ struct posix_acl *hfsplus_get_posix_acl(struct inode *inode, int type)
17 char *value = NULL; 17 char *value = NULL;
18 ssize_t size; 18 ssize_t size;
19 19
20 acl = get_cached_acl(inode, type); 20 hfs_dbg(ACL_MOD, "[%s]: ino %lu\n", __func__, inode->i_ino);
21 if (acl != ACL_NOT_CACHED)
22 return acl;
23 21
24 switch (type) { 22 switch (type) {
25 case ACL_TYPE_ACCESS: 23 case ACL_TYPE_ACCESS:
@@ -56,17 +54,15 @@ struct posix_acl *hfsplus_get_posix_acl(struct inode *inode, int type)
56 return acl; 54 return acl;
57} 55}
58 56
59static int hfsplus_set_posix_acl(struct inode *inode, 57int hfsplus_set_posix_acl(struct inode *inode, struct posix_acl *acl,
60 int type, 58 int type)
61 struct posix_acl *acl)
62{ 59{
63 int err; 60 int err;
64 char *xattr_name; 61 char *xattr_name;
65 size_t size = 0; 62 size_t size = 0;
66 char *value = NULL; 63 char *value = NULL;
67 64
68 if (S_ISLNK(inode->i_mode)) 65 hfs_dbg(ACL_MOD, "[%s]: ino %lu\n", __func__, inode->i_ino);
69 return -EOPNOTSUPP;
70 66
71 switch (type) { 67 switch (type) {
72 case ACL_TYPE_ACCESS: 68 case ACL_TYPE_ACCESS:
@@ -115,7 +111,7 @@ end_set_acl:
115int hfsplus_init_posix_acl(struct inode *inode, struct inode *dir) 111int hfsplus_init_posix_acl(struct inode *inode, struct inode *dir)
116{ 112{
117 int err = 0; 113 int err = 0;
118 struct posix_acl *acl = NULL; 114 struct posix_acl *default_acl, *acl;
119 115
120 hfs_dbg(ACL_MOD, 116 hfs_dbg(ACL_MOD,
121 "[%s]: ino %lu, dir->ino %lu\n", 117 "[%s]: ino %lu, dir->ino %lu\n",
@@ -124,151 +120,21 @@ int hfsplus_init_posix_acl(struct inode *inode, struct inode *dir)
124 if (S_ISLNK(inode->i_mode)) 120 if (S_ISLNK(inode->i_mode))
125 return 0; 121 return 0;
126 122
127 acl = hfsplus_get_posix_acl(dir, ACL_TYPE_DEFAULT); 123 err = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
128 if (IS_ERR(acl)) 124 if (err)
129 return PTR_ERR(acl);
130
131 if (acl) {
132 if (S_ISDIR(inode->i_mode)) {
133 err = hfsplus_set_posix_acl(inode,
134 ACL_TYPE_DEFAULT,
135 acl);
136 if (unlikely(err))
137 goto init_acl_cleanup;
138 }
139
140 err = posix_acl_create(&acl, GFP_NOFS, &inode->i_mode);
141 if (unlikely(err < 0))
142 return err;
143
144 if (err > 0)
145 err = hfsplus_set_posix_acl(inode,
146 ACL_TYPE_ACCESS,
147 acl);
148 } else
149 inode->i_mode &= ~current_umask();
150
151init_acl_cleanup:
152 posix_acl_release(acl);
153 return err;
154}
155
156int hfsplus_posix_acl_chmod(struct inode *inode)
157{
158 int err;
159 struct posix_acl *acl;
160
161 hfs_dbg(ACL_MOD, "[%s]: ino %lu\n", __func__, inode->i_ino);
162
163 if (S_ISLNK(inode->i_mode))
164 return -EOPNOTSUPP;
165
166 acl = hfsplus_get_posix_acl(inode, ACL_TYPE_ACCESS);
167 if (IS_ERR(acl) || !acl)
168 return PTR_ERR(acl);
169
170 err = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode);
171 if (unlikely(err))
172 return err; 125 return err;
173 126
174 err = hfsplus_set_posix_acl(inode, ACL_TYPE_ACCESS, acl); 127 if (default_acl) {
175 posix_acl_release(acl); 128 err = hfsplus_set_posix_acl(inode, default_acl,
176 return err; 129 ACL_TYPE_DEFAULT);
177} 130 posix_acl_release(default_acl);
178
179static int hfsplus_xattr_get_posix_acl(struct dentry *dentry,
180 const char *name,
181 void *buffer,
182 size_t size,
183 int type)
184{
185 int err = 0;
186 struct posix_acl *acl;
187
188 hfs_dbg(ACL_MOD,
189 "[%s]: ino %lu, buffer %p, size %zu, type %#x\n",
190 __func__, dentry->d_inode->i_ino, buffer, size, type);
191
192 if (strcmp(name, "") != 0)
193 return -EINVAL;
194
195 acl = hfsplus_get_posix_acl(dentry->d_inode, type);
196 if (IS_ERR(acl))
197 return PTR_ERR(acl);
198 if (acl == NULL)
199 return -ENODATA;
200
201 err = posix_acl_to_xattr(&init_user_ns, acl, buffer, size);
202 posix_acl_release(acl);
203
204 return err;
205}
206
207static int hfsplus_xattr_set_posix_acl(struct dentry *dentry,
208 const char *name,
209 const void *value,
210 size_t size,
211 int flags,
212 int type)
213{
214 int err = 0;
215 struct inode *inode = dentry->d_inode;
216 struct posix_acl *acl = NULL;
217
218 hfs_dbg(ACL_MOD,
219 "[%s]: ino %lu, value %p, size %zu, flags %#x, type %#x\n",
220 __func__, inode->i_ino, value, size, flags, type);
221
222 if (strcmp(name, "") != 0)
223 return -EINVAL;
224
225 if (!inode_owner_or_capable(inode))
226 return -EPERM;
227
228 if (value) {
229 acl = posix_acl_from_xattr(&init_user_ns, value, size);
230 if (IS_ERR(acl))
231 return PTR_ERR(acl);
232 else if (acl) {
233 err = posix_acl_valid(acl);
234 if (err)
235 goto end_xattr_set_acl;
236 }
237 } 131 }
238 132
239 err = hfsplus_set_posix_acl(inode, type, acl); 133 if (acl) {
240 134 if (!err)
241end_xattr_set_acl: 135 err = hfsplus_set_posix_acl(inode, acl,
242 posix_acl_release(acl); 136 ACL_TYPE_ACCESS);
137 posix_acl_release(acl);
138 }
243 return err; 139 return err;
244} 140}
245
246static size_t hfsplus_xattr_list_posix_acl(struct dentry *dentry,
247 char *list,
248 size_t list_size,
249 const char *name,
250 size_t name_len,
251 int type)
252{
253 /*
254 * This method is not used.
255 * It is used hfsplus_listxattr() instead of generic_listxattr().
256 */
257 return -EOPNOTSUPP;
258}
259
260const struct xattr_handler hfsplus_xattr_acl_access_handler = {
261 .prefix = POSIX_ACL_XATTR_ACCESS,
262 .flags = ACL_TYPE_ACCESS,
263 .list = hfsplus_xattr_list_posix_acl,
264 .get = hfsplus_xattr_get_posix_acl,
265 .set = hfsplus_xattr_set_posix_acl,
266};
267
268const struct xattr_handler hfsplus_xattr_acl_default_handler = {
269 .prefix = POSIX_ACL_XATTR_DEFAULT,
270 .flags = ACL_TYPE_DEFAULT,
271 .list = hfsplus_xattr_list_posix_acl,
272 .get = hfsplus_xattr_get_posix_acl,
273 .set = hfsplus_xattr_set_posix_acl,
274};
diff --git a/fs/hfsplus/xattr.c b/fs/hfsplus/xattr.c
index 3c6136f98c73..0b4a5c9b93c4 100644
--- a/fs/hfsplus/xattr.c
+++ b/fs/hfsplus/xattr.c
@@ -7,6 +7,7 @@
7 */ 7 */
8 8
9#include "hfsplus_fs.h" 9#include "hfsplus_fs.h"
10#include <linux/posix_acl_xattr.h>
10#include "xattr.h" 11#include "xattr.h"
11#include "acl.h" 12#include "acl.h"
12 13
@@ -15,8 +16,8 @@ const struct xattr_handler *hfsplus_xattr_handlers[] = {
15 &hfsplus_xattr_user_handler, 16 &hfsplus_xattr_user_handler,
16 &hfsplus_xattr_trusted_handler, 17 &hfsplus_xattr_trusted_handler,
17#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL 18#ifdef CONFIG_HFSPLUS_FS_POSIX_ACL
18 &hfsplus_xattr_acl_access_handler, 19 &posix_acl_access_xattr_handler,
19 &hfsplus_xattr_acl_default_handler, 20 &posix_acl_default_xattr_handler,
20#endif 21#endif
21 &hfsplus_xattr_security_handler, 22 &hfsplus_xattr_security_handler,
22 NULL 23 NULL
@@ -51,82 +52,6 @@ static inline int is_known_namespace(const char *name)
51 return true; 52 return true;
52} 53}
53 54
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
101static int can_set_xattr(struct inode *inode, const char *name,
102 const void *value, size_t value_len)
103{
104 if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
105 return can_set_system_xattr(inode, name, value, value_len);
106
107 if (!strncmp(name, XATTR_MAC_OSX_PREFIX, XATTR_MAC_OSX_PREFIX_LEN)) {
108 /*
109 * This makes sure that we aren't trying to set an
110 * attribute in a different namespace by prefixing it
111 * with "osx."
112 */
113 if (is_known_namespace(name + XATTR_MAC_OSX_PREFIX_LEN))
114 return -EOPNOTSUPP;
115
116 return 0;
117 }
118
119 /*
120 * Don't allow setting an attribute in an unknown namespace.
121 */
122 if (strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) &&
123 strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) &&
124 strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
125 return -EOPNOTSUPP;
126
127 return 0;
128}
129
130static void hfsplus_init_header_node(struct inode *attr_file, 55static void hfsplus_init_header_node(struct inode *attr_file,
131 u32 clump_size, 56 u32 clump_size,
132 char *buf, u16 node_size) 57 char *buf, u16 node_size)
@@ -349,10 +274,6 @@ int __hfsplus_setxattr(struct inode *inode, const char *name,
349 HFSPLUS_IS_RSRC(inode)) 274 HFSPLUS_IS_RSRC(inode))
350 return -EOPNOTSUPP; 275 return -EOPNOTSUPP;
351 276
352 err = can_set_xattr(inode, name, value, size);
353 if (err)
354 return err;
355
356 if (strncmp(name, XATTR_MAC_OSX_PREFIX, 277 if (strncmp(name, XATTR_MAC_OSX_PREFIX,
357 XATTR_MAC_OSX_PREFIX_LEN) == 0) 278 XATTR_MAC_OSX_PREFIX_LEN) == 0)
358 name += XATTR_MAC_OSX_PREFIX_LEN; 279 name += XATTR_MAC_OSX_PREFIX_LEN;
@@ -840,10 +761,6 @@ int hfsplus_removexattr(struct dentry *dentry, const char *name)
840 if (!HFSPLUS_SB(inode->i_sb)->attr_tree) 761 if (!HFSPLUS_SB(inode->i_sb)->attr_tree)
841 return -EOPNOTSUPP; 762 return -EOPNOTSUPP;
842 763
843 err = can_set_xattr(inode, name, NULL, 0);
844 if (err)
845 return err;
846
847 if (strncmp(name, XATTR_MAC_OSX_PREFIX, 764 if (strncmp(name, XATTR_MAC_OSX_PREFIX,
848 XATTR_MAC_OSX_PREFIX_LEN) == 0) 765 XATTR_MAC_OSX_PREFIX_LEN) == 0)
849 name += XATTR_MAC_OSX_PREFIX_LEN; 766 name += XATTR_MAC_OSX_PREFIX_LEN;
@@ -940,6 +857,9 @@ static int hfsplus_osx_setxattr(struct dentry *dentry, const char *name,
940 if (len > HFSPLUS_ATTR_MAX_STRLEN) 857 if (len > HFSPLUS_ATTR_MAX_STRLEN)
941 return -EOPNOTSUPP; 858 return -EOPNOTSUPP;
942 859
860 if (is_known_namespace(name))
861 return -EOPNOTSUPP;
862
943 strcpy(xattr_name, XATTR_MAC_OSX_PREFIX); 863 strcpy(xattr_name, XATTR_MAC_OSX_PREFIX);
944 strcpy(xattr_name + XATTR_MAC_OSX_PREFIX_LEN, name); 864 strcpy(xattr_name + XATTR_MAC_OSX_PREFIX_LEN, name);
945 865
diff --git a/fs/hfsplus/xattr.h b/fs/hfsplus/xattr.h
index 841b5698c0fc..9e214490c313 100644
--- a/fs/hfsplus/xattr.h
+++ b/fs/hfsplus/xattr.h
@@ -14,8 +14,6 @@
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;
17extern const struct xattr_handler hfsplus_xattr_acl_access_handler;
18extern const struct xattr_handler hfsplus_xattr_acl_default_handler;
19extern const struct xattr_handler hfsplus_xattr_security_handler; 17extern const struct xattr_handler hfsplus_xattr_security_handler;
20 18
21extern const struct xattr_handler *hfsplus_xattr_handlers[]; 19extern const struct xattr_handler *hfsplus_xattr_handlers[];