aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-01-11 16:32:10 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-11 16:32:10 -0500
commitddf1d6238dd13a3bd948e8fcb1109798ef0af49b (patch)
treedaa25447e4b791b2868a0338f872975ec480862b /fs/xfs
parent32fb378437a1d716e72a442237d7ead1f435ecf0 (diff)
parent764a5c6b1fa4306dd7573c1d80914254909cd036 (diff)
Merge branch 'work.xattr' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs xattr updates from Al Viro: "Andreas' xattr cleanup series. It's a followup to his xattr work that went in last cycle; -0.5KLoC" * 'work.xattr' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: xattr handlers: Simplify list operation ocfs2: Replace list xattr handler operations nfs: Move call to security_inode_listsecurity into nfs_listxattr xfs: Change how listxattr generates synthetic attributes tmpfs: listxattr should include POSIX ACL xattrs tmpfs: Use xattr handler infrastructure btrfs: Use xattr handler infrastructure vfs: Distinguish between full xattr names and proper prefixes posix acls: Remove duplicate xattr name definitions gfs2: Remove gfs2_xattr_acl_chmod vfs: Remove vfs_xattr_cmp
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_acl.c23
-rw-r--r--fs/xfs/xfs_acl.h4
-rw-r--r--fs/xfs/xfs_xattr.c143
3 files changed, 59 insertions, 111 deletions
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c
index 6bb470fbb8e8..2d5df1f23bbc 100644
--- a/fs/xfs/xfs_acl.c
+++ b/fs/xfs/xfs_acl.c
@@ -252,29 +252,6 @@ xfs_set_mode(struct inode *inode, umode_t mode)
252 return error; 252 return error;
253} 253}
254 254
255static int
256xfs_acl_exists(struct inode *inode, unsigned char *name)
257{
258 int len = XFS_ACL_MAX_SIZE(XFS_M(inode->i_sb));
259
260 return (xfs_attr_get(XFS_I(inode), name, NULL, &len,
261 ATTR_ROOT|ATTR_KERNOVAL) == 0);
262}
263
264int
265posix_acl_access_exists(struct inode *inode)
266{
267 return xfs_acl_exists(inode, SGI_ACL_FILE);
268}
269
270int
271posix_acl_default_exists(struct inode *inode)
272{
273 if (!S_ISDIR(inode->i_mode))
274 return 0;
275 return xfs_acl_exists(inode, SGI_ACL_DEFAULT);
276}
277
278int 255int
279xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type) 256xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type)
280{ 257{
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h
index 52f8255d6bdf..286fa89217f5 100644
--- a/fs/xfs/xfs_acl.h
+++ b/fs/xfs/xfs_acl.h
@@ -24,16 +24,12 @@ struct posix_acl;
24#ifdef CONFIG_XFS_POSIX_ACL 24#ifdef CONFIG_XFS_POSIX_ACL
25extern struct posix_acl *xfs_get_acl(struct inode *inode, int type); 25extern struct posix_acl *xfs_get_acl(struct inode *inode, int type);
26extern int xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type); 26extern int xfs_set_acl(struct inode *inode, struct posix_acl *acl, int type);
27extern int posix_acl_access_exists(struct inode *inode);
28extern int posix_acl_default_exists(struct inode *inode);
29#else 27#else
30static inline struct posix_acl *xfs_get_acl(struct inode *inode, int type) 28static inline struct posix_acl *xfs_get_acl(struct inode *inode, int type)
31{ 29{
32 return NULL; 30 return NULL;
33} 31}
34# define xfs_set_acl NULL 32# define xfs_set_acl NULL
35# define posix_acl_access_exists(inode) 0
36# define posix_acl_default_exists(inode) 0
37#endif /* CONFIG_XFS_POSIX_ACL */ 33#endif /* CONFIG_XFS_POSIX_ACL */
38 34
39extern void xfs_forget_acl(struct inode *inode, const char *name, int xflags); 35extern void xfs_forget_acl(struct inode *inode, const char *name, int xflags);
diff --git a/fs/xfs/xfs_xattr.c b/fs/xfs/xfs_xattr.c
index 839b35ca21c6..110f1d7d86b0 100644
--- a/fs/xfs/xfs_xattr.c
+++ b/fs/xfs/xfs_xattr.c
@@ -39,9 +39,6 @@ xfs_xattr_get(const struct xattr_handler *handler, struct dentry *dentry,
39 struct xfs_inode *ip = XFS_I(d_inode(dentry)); 39 struct xfs_inode *ip = XFS_I(d_inode(dentry));
40 int error, asize = size; 40 int error, asize = size;
41 41
42 if (strcmp(name, "") == 0)
43 return -EINVAL;
44
45 /* Convert Linux syscall to XFS internal ATTR flags */ 42 /* Convert Linux syscall to XFS internal ATTR flags */
46 if (!size) { 43 if (!size) {
47 xflags |= ATTR_KERNOVAL; 44 xflags |= ATTR_KERNOVAL;
@@ -84,9 +81,6 @@ xfs_xattr_set(const struct xattr_handler *handler, struct dentry *dentry,
84 struct xfs_inode *ip = XFS_I(d_inode(dentry)); 81 struct xfs_inode *ip = XFS_I(d_inode(dentry));
85 int error; 82 int error;
86 83
87 if (strcmp(name, "") == 0)
88 return -EINVAL;
89
90 /* Convert Linux syscall to XFS internal ATTR flags */ 84 /* Convert Linux syscall to XFS internal ATTR flags */
91 if (flags & XATTR_CREATE) 85 if (flags & XATTR_CREATE)
92 xflags |= ATTR_CREATE; 86 xflags |= ATTR_CREATE;
@@ -135,47 +129,19 @@ const struct xattr_handler *xfs_xattr_handlers[] = {
135 NULL 129 NULL
136}; 130};
137 131
138static unsigned int xfs_xattr_prefix_len(int flags)
139{
140 if (flags & XFS_ATTR_SECURE)
141 return sizeof("security");
142 else if (flags & XFS_ATTR_ROOT)
143 return sizeof("trusted");
144 else
145 return sizeof("user");
146}
147
148static const char *xfs_xattr_prefix(int flags)
149{
150 if (flags & XFS_ATTR_SECURE)
151 return xfs_xattr_security_handler.prefix;
152 else if (flags & XFS_ATTR_ROOT)
153 return xfs_xattr_trusted_handler.prefix;
154 else
155 return xfs_xattr_user_handler.prefix;
156}
157
158static int 132static int
159xfs_xattr_put_listent( 133__xfs_xattr_put_listent(
160 struct xfs_attr_list_context *context, 134 struct xfs_attr_list_context *context,
161 int flags, 135 char *prefix,
162 unsigned char *name, 136 int prefix_len,
163 int namelen, 137 unsigned char *name,
164 int valuelen, 138 int namelen)
165 unsigned char *value)
166{ 139{
167 unsigned int prefix_len = xfs_xattr_prefix_len(flags);
168 char *offset; 140 char *offset;
169 int arraytop; 141 int arraytop;
170 142
171 ASSERT(context->count >= 0); 143 if (!context->alist)
172 144 goto compute_size;
173 /*
174 * Only show root namespace entries if we are actually allowed to
175 * see them.
176 */
177 if ((flags & XFS_ATTR_ROOT) && !capable(CAP_SYS_ADMIN))
178 return 0;
179 145
180 arraytop = context->count + prefix_len + namelen + 1; 146 arraytop = context->count + prefix_len + namelen + 1;
181 if (arraytop > context->firstu) { 147 if (arraytop > context->firstu) {
@@ -183,17 +149,19 @@ xfs_xattr_put_listent(
183 return 1; 149 return 1;
184 } 150 }
185 offset = (char *)context->alist + context->count; 151 offset = (char *)context->alist + context->count;
186 strncpy(offset, xfs_xattr_prefix(flags), prefix_len); 152 strncpy(offset, prefix, prefix_len);
187 offset += prefix_len; 153 offset += prefix_len;
188 strncpy(offset, (char *)name, namelen); /* real name */ 154 strncpy(offset, (char *)name, namelen); /* real name */
189 offset += namelen; 155 offset += namelen;
190 *offset = '\0'; 156 *offset = '\0';
157
158compute_size:
191 context->count += prefix_len + namelen + 1; 159 context->count += prefix_len + namelen + 1;
192 return 0; 160 return 0;
193} 161}
194 162
195static int 163static int
196xfs_xattr_put_listent_sizes( 164xfs_xattr_put_listent(
197 struct xfs_attr_list_context *context, 165 struct xfs_attr_list_context *context,
198 int flags, 166 int flags,
199 unsigned char *name, 167 unsigned char *name,
@@ -201,24 +169,55 @@ xfs_xattr_put_listent_sizes(
201 int valuelen, 169 int valuelen,
202 unsigned char *value) 170 unsigned char *value)
203{ 171{
204 context->count += xfs_xattr_prefix_len(flags) + namelen + 1; 172 char *prefix;
205 return 0; 173 int prefix_len;
206}
207 174
208static int 175 ASSERT(context->count >= 0);
209list_one_attr(const char *name, const size_t len, void *data,
210 size_t size, ssize_t *result)
211{
212 char *p = data + *result;
213 176
214 *result += len; 177 if (flags & XFS_ATTR_ROOT) {
215 if (!size) 178#ifdef CONFIG_XFS_POSIX_ACL
216 return 0; 179 if (namelen == SGI_ACL_FILE_SIZE &&
217 if (*result > size) 180 strncmp(name, SGI_ACL_FILE,
218 return -ERANGE; 181 SGI_ACL_FILE_SIZE) == 0) {
182 int ret = __xfs_xattr_put_listent(
183 context, XATTR_SYSTEM_PREFIX,
184 XATTR_SYSTEM_PREFIX_LEN,
185 XATTR_POSIX_ACL_ACCESS,
186 strlen(XATTR_POSIX_ACL_ACCESS));
187 if (ret)
188 return ret;
189 } else if (namelen == SGI_ACL_DEFAULT_SIZE &&
190 strncmp(name, SGI_ACL_DEFAULT,
191 SGI_ACL_DEFAULT_SIZE) == 0) {
192 int ret = __xfs_xattr_put_listent(
193 context, XATTR_SYSTEM_PREFIX,
194 XATTR_SYSTEM_PREFIX_LEN,
195 XATTR_POSIX_ACL_DEFAULT,
196 strlen(XATTR_POSIX_ACL_DEFAULT));
197 if (ret)
198 return ret;
199 }
200#endif
219 201
220 strcpy(p, name); 202 /*
221 return 0; 203 * Only show root namespace entries if we are actually allowed to
204 * see them.
205 */
206 if (!capable(CAP_SYS_ADMIN))
207 return 0;
208
209 prefix = XATTR_TRUSTED_PREFIX;
210 prefix_len = XATTR_TRUSTED_PREFIX_LEN;
211 } else if (flags & XFS_ATTR_SECURE) {
212 prefix = XATTR_SECURITY_PREFIX;
213 prefix_len = XATTR_SECURITY_PREFIX_LEN;
214 } else {
215 prefix = XATTR_USER_PREFIX;
216 prefix_len = XATTR_USER_PREFIX_LEN;
217 }
218
219 return __xfs_xattr_put_listent(context, prefix, prefix_len, name,
220 namelen);
222} 221}
223 222
224ssize_t 223ssize_t
@@ -227,7 +226,6 @@ xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size)
227 struct xfs_attr_list_context context; 226 struct xfs_attr_list_context context;
228 struct attrlist_cursor_kern cursor = { 0 }; 227 struct attrlist_cursor_kern cursor = { 0 };
229 struct inode *inode = d_inode(dentry); 228 struct inode *inode = d_inode(dentry);
230 int error;
231 229
232 /* 230 /*
233 * First read the regular on-disk attributes. 231 * First read the regular on-disk attributes.
@@ -236,37 +234,14 @@ xfs_vn_listxattr(struct dentry *dentry, char *data, size_t size)
236 context.dp = XFS_I(inode); 234 context.dp = XFS_I(inode);
237 context.cursor = &cursor; 235 context.cursor = &cursor;
238 context.resynch = 1; 236 context.resynch = 1;
239 context.alist = data; 237 context.alist = size ? data : NULL;
240 context.bufsize = size; 238 context.bufsize = size;
241 context.firstu = context.bufsize; 239 context.firstu = context.bufsize;
242 240 context.put_listent = xfs_xattr_put_listent;
243 if (size)
244 context.put_listent = xfs_xattr_put_listent;
245 else
246 context.put_listent = xfs_xattr_put_listent_sizes;
247 241
248 xfs_attr_list_int(&context); 242 xfs_attr_list_int(&context);
249 if (context.count < 0) 243 if (context.count < 0)
250 return -ERANGE; 244 return -ERANGE;
251 245
252 /*
253 * Then add the two synthetic ACL attributes.
254 */
255 if (posix_acl_access_exists(inode)) {
256 error = list_one_attr(POSIX_ACL_XATTR_ACCESS,
257 strlen(POSIX_ACL_XATTR_ACCESS) + 1,
258 data, size, &context.count);
259 if (error)
260 return error;
261 }
262
263 if (posix_acl_default_exists(inode)) {
264 error = list_one_attr(POSIX_ACL_XATTR_DEFAULT,
265 strlen(POSIX_ACL_XATTR_DEFAULT) + 1,
266 data, size, &context.count);
267 if (error)
268 return error;
269 }
270
271 return context.count; 246 return context.count;
272} 247}