1 From: Andreas Gruenbacher <agruen@suse.de>
2 Subject: Pass struct file down the inode_*xattr security LSM hooks
4 This allows LSMs to also distinguish between file descriptor and path
5 access for the xattr operations. (The other relevant operations are
6 covered by the setattr hook.)
8 Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
9 Signed-off-by: John Johansen <jjohansen@suse.de>
12 fs/xattr.c | 59 +++++++++++++++++++++++----------------------
13 include/linux/security.h | 38 ++++++++++++++++------------
14 include/linux/xattr.h | 9 +++---
15 security/capability.c | 5 ++-
16 security/commoncap.c | 4 +--
17 security/security.c | 17 ++++++------
18 security/selinux/hooks.c | 10 ++++---
19 security/smack/smack_lsm.c | 14 ++++++----
20 8 files changed, 87 insertions(+), 69 deletions(-)
24 @@ -68,7 +68,7 @@ xattr_permission(struct inode *inode, co
27 vfs_setxattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
28 - const void *value, size_t size, int flags)
29 + const void *value, size_t size, int flags, struct file *file)
31 struct inode *inode = dentry->d_inode;
33 @@ -78,7 +78,7 @@ vfs_setxattr(struct dentry *dentry, stru
36 mutex_lock(&inode->i_mutex);
37 - error = security_inode_setxattr(dentry, mnt, name, value, size, flags);
38 + error = security_inode_setxattr(dentry, mnt, name, value, size, flags, file);
42 @@ -132,7 +132,7 @@ EXPORT_SYMBOL_GPL(xattr_getsecurity);
45 vfs_getxattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
46 - void *value, size_t size)
47 + void *value, size_t size, struct file *file)
49 struct inode *inode = dentry->d_inode;
51 @@ -141,7 +141,7 @@ vfs_getxattr(struct dentry *dentry, stru
55 - error = security_inode_getxattr(dentry, mnt, name);
56 + error = security_inode_getxattr(dentry, mnt, name, file);
60 @@ -169,12 +169,12 @@ EXPORT_SYMBOL_GPL(vfs_getxattr);
63 vfs_listxattr(struct dentry *dentry, struct vfsmount *mnt, char *list,
65 + size_t size, struct file *file)
67 struct inode *inode = dentry->d_inode;
70 - error = security_inode_listxattr(dentry, mnt);
71 + error = security_inode_listxattr(dentry, mnt, file);
75 @@ -190,7 +190,8 @@ vfs_listxattr(struct dentry *dentry, str
76 EXPORT_SYMBOL_GPL(vfs_listxattr);
79 -vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, const char *name)
80 +vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
83 struct inode *inode = dentry->d_inode;
85 @@ -202,7 +203,7 @@ vfs_removexattr(struct dentry *dentry, s
89 - error = security_inode_removexattr(dentry, mnt, name);
90 + error = security_inode_removexattr(dentry, mnt, name, file);
94 @@ -222,7 +223,7 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
97 setxattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name,
98 - const void __user *value, size_t size, int flags)
99 + const void __user *value, size_t size, int flags, struct file *file)
103 @@ -249,7 +250,7 @@ setxattr(struct dentry *dentry, struct v
107 - error = vfs_setxattr(dentry, mnt, kname, kvalue, size, flags);
108 + error = vfs_setxattr(dentry, mnt, kname, kvalue, size, flags, file);
112 @@ -266,7 +267,7 @@ SYSCALL_DEFINE5(setxattr, const char __u
114 error = mnt_want_write(path.mnt);
116 - error = setxattr(path.dentry, path.mnt, name, value, size, flags);
117 + error = setxattr(path.dentry, path.mnt, name, value, size, flags, NULL);
118 mnt_drop_write(path.mnt);
121 @@ -285,7 +286,7 @@ SYSCALL_DEFINE5(lsetxattr, const char __
123 error = mnt_want_write(path.mnt);
125 - error = setxattr(path.dentry, path.mnt, name, value, size, flags);
126 + error = setxattr(path.dentry, path.mnt, name, value, size, flags, NULL);
127 mnt_drop_write(path.mnt);
130 @@ -306,7 +307,8 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, cons
131 audit_inode(NULL, dentry);
132 error = mnt_want_write_file(f->f_path.mnt, f);
134 - error = setxattr(dentry, f->f_vfsmnt, name, value, size, flags);
135 + error = setxattr(dentry, f->f_vfsmnt, name, value, size, flags,
137 mnt_drop_write(f->f_path.mnt);
140 @@ -318,7 +320,7 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, cons
143 getxattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name,
144 - void __user *value, size_t size)
145 + void __user *value, size_t size, struct file *file)
149 @@ -338,7 +340,7 @@ getxattr(struct dentry *dentry, struct v
153 - error = vfs_getxattr(dentry, mnt, kname, kvalue, size);
154 + error = vfs_getxattr(dentry, mnt, kname, kvalue, size, file);
156 if (size && copy_to_user(value, kvalue, error))
158 @@ -360,7 +362,7 @@ SYSCALL_DEFINE4(getxattr, const char __u
159 error = user_path(pathname, &path);
162 - error = getxattr(path.dentry, path.mnt, name, value, size);
163 + error = getxattr(path.dentry, path.mnt, name, value, size, NULL);
167 @@ -374,7 +376,7 @@ SYSCALL_DEFINE4(lgetxattr, const char __
168 error = user_lpath(pathname, &path);
171 - error = getxattr(path.dentry, path.mnt, name, value, size);
172 + error = getxattr(path.dentry, path.mnt, name, value, size, NULL);
176 @@ -389,7 +391,7 @@ SYSCALL_DEFINE4(fgetxattr, int, fd, cons
179 audit_inode(NULL, f->f_path.dentry);
180 - error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size);
181 + error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size, f);
185 @@ -399,7 +401,7 @@ SYSCALL_DEFINE4(fgetxattr, int, fd, cons
188 listxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *list,
190 + size_t size, struct file *file)
194 @@ -412,7 +414,7 @@ listxattr(struct dentry *dentry, struct
198 - error = vfs_listxattr(dentry, mnt, klist, size);
199 + error = vfs_listxattr(dentry, mnt, klist, size, file);
201 if (size && copy_to_user(list, klist, error))
203 @@ -434,7 +436,7 @@ SYSCALL_DEFINE3(listxattr, const char __
204 error = user_path(pathname, &path);
207 - error = listxattr(path.dentry, path.mnt, list, size);
208 + error = listxattr(path.dentry, path.mnt, list, size, NULL);
212 @@ -448,7 +450,7 @@ SYSCALL_DEFINE3(llistxattr, const char _
213 error = user_lpath(pathname, &path);
216 - error = listxattr(path.dentry, path.mnt, list, size);
217 + error = listxattr(path.dentry, path.mnt, list, size, NULL);
221 @@ -462,7 +464,7 @@ SYSCALL_DEFINE3(flistxattr, int, fd, cha
224 audit_inode(NULL, f->f_path.dentry);
225 - error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size);
226 + error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size, f);
230 @@ -471,7 +473,8 @@ SYSCALL_DEFINE3(flistxattr, int, fd, cha
231 * Extended attribute REMOVE operations
234 -removexattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name)
235 +removexattr(struct dentry *dentry, struct vfsmount *mnt,
236 + const char __user *name, struct file *file)
239 char kname[XATTR_NAME_MAX + 1];
240 @@ -482,7 +485,7 @@ removexattr(struct dentry *dentry, struc
244 - return vfs_removexattr(dentry, mnt, kname);
245 + return vfs_removexattr(dentry, mnt, kname, file);
248 SYSCALL_DEFINE2(removexattr, const char __user *, pathname,
249 @@ -496,7 +499,7 @@ SYSCALL_DEFINE2(removexattr, const char
251 error = mnt_want_write(path.mnt);
253 - error = removexattr(path.dentry, path.mnt, name);
254 + error = removexattr(path.dentry, path.mnt, name, NULL);
255 mnt_drop_write(path.mnt);
258 @@ -514,7 +517,7 @@ SYSCALL_DEFINE2(lremovexattr, const char
260 error = mnt_want_write(path.mnt);
262 - error = removexattr(path.dentry, path.mnt, name);
263 + error = removexattr(path.dentry, path.mnt, name, NULL);
264 mnt_drop_write(path.mnt);
267 @@ -534,7 +537,7 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, c
268 audit_inode(NULL, dentry);
269 error = mnt_want_write_file(f->f_path.mnt, f);
271 - error = removexattr(dentry, f->f_path.mnt, name);
272 + error = removexattr(dentry, f->f_path.mnt, name, f);
273 mnt_drop_write(f->f_path.mnt);
276 --- a/include/linux/security.h
277 +++ b/include/linux/security.h
278 @@ -56,9 +56,9 @@ extern void cap_bprm_apply_creds(struct
279 extern int cap_bprm_secureexec(struct linux_binprm *bprm);
280 extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
281 const char *name, const void *value, size_t size,
283 + int flags, struct file *file);
284 extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
286 + const char *name, struct file *file);
287 extern int cap_inode_need_killpriv(struct dentry *dentry);
288 extern int cap_inode_killpriv(struct dentry *dentry);
289 extern int cap_task_post_setuid(uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
290 @@ -1396,16 +1396,17 @@ struct security_operations {
291 void (*inode_delete) (struct inode *inode);
292 int (*inode_setxattr) (struct dentry *dentry, struct vfsmount *mnt,
293 const char *name, const void *value, size_t size,
295 + int flags, struct file *file);
296 void (*inode_post_setxattr) (struct dentry *dentry,
297 struct vfsmount *mnt,
298 const char *name, const void *value,
299 size_t size, int flags);
300 int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
302 - int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt);
303 + const char *name, struct file *file);
304 + int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt,
305 + struct file *file);
306 int (*inode_removexattr) (struct dentry *dentry, struct vfsmount *mnt,
308 + const char *name, struct file *file);
309 int (*inode_need_killpriv) (struct dentry *dentry);
310 int (*inode_killpriv) (struct dentry *dentry);
311 int (*inode_getsecurity) (const struct inode *inode, const char *name, void **buffer, bool alloc);
312 @@ -1675,15 +1676,16 @@ int security_inode_getattr(struct vfsmou
313 void security_inode_delete(struct inode *inode);
314 int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
315 const char *name, const void *value,
316 - size_t size, int flags);
317 + size_t size, int flags, struct file *file);
318 void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
319 const char *name, const void *value,
320 size_t size, int flags);
321 int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
323 -int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt);
324 + const char *name, struct file *file);
325 +int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
326 + struct file *file);
327 int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
329 + const char *name, struct file *file);
330 int security_inode_need_killpriv(struct dentry *dentry);
331 int security_inode_killpriv(struct dentry *dentry);
332 int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
333 @@ -2105,9 +2107,10 @@ static inline void security_inode_delete
334 static inline int security_inode_setxattr(struct dentry *dentry,
335 struct vfsmount *mnt,
336 const char *name, const void *value,
337 - size_t size, int flags)
338 + size_t size, int flags,
341 - return cap_inode_setxattr(dentry, mnt, name, value, size, flags);
342 + return cap_inode_setxattr(dentry, mnt, name, value, size, flags, file);
345 static inline void security_inode_post_setxattr(struct dentry *dentry,
346 @@ -2119,22 +2122,25 @@ static inline void security_inode_post_s
348 static inline int security_inode_getxattr(struct dentry *dentry,
349 struct vfsmount *mnt,
357 static inline int security_inode_listxattr(struct dentry *dentry,
358 - struct vfsmount *mnt)
359 + struct vfsmount *mnt,
365 static inline int security_inode_removexattr(struct dentry *dentry,
366 struct vfsmount *mnt,
371 - return cap_inode_removexattr(dentry, mnt, name);
372 + return cap_inode_removexattr(dentry, mnt, name, file);
375 static inline int security_inode_need_killpriv(struct dentry *dentry)
376 --- a/include/linux/xattr.h
377 +++ b/include/linux/xattr.h
380 #include <linux/types.h>
381 #include <linux/mount.h>
382 +#include <linux/fs.h>
385 #define XATTR_OS2_PREFIX "os2."
386 @@ -48,10 +49,10 @@ struct xattr_handler {
389 ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
390 -ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, const char *, void *, size_t);
391 -ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list, size_t size);
392 -int vfs_setxattr(struct dentry *, struct vfsmount *, const char *, const void *, size_t, int);
393 -int vfs_removexattr(struct dentry *, struct vfsmount *mnt, const char *);
394 +ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, const char *, void *, size_t, struct file *file);
395 +ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list, size_t size, struct file *file);
396 +int vfs_setxattr(struct dentry *, struct vfsmount *, const char *, const void *, size_t, int, struct file *file);
397 +int vfs_removexattr(struct dentry *, struct vfsmount *mnt, const char *, struct file *file);
399 ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
400 ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
401 --- a/security/capability.c
402 +++ b/security/capability.c
403 @@ -242,12 +242,13 @@ static void cap_inode_post_setxattr(stru
406 static int cap_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
408 + const char *name, struct file *f)
413 -static int cap_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt)
414 +static int cap_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
419 --- a/security/commoncap.c
420 +++ b/security/commoncap.c
421 @@ -416,7 +416,7 @@ int cap_bprm_secureexec (struct linux_bi
423 int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
424 const char *name, const void *value, size_t size,
426 + int flags, struct file *file)
428 if (!strcmp(name, XATTR_NAME_CAPS)) {
429 if (!capable(CAP_SETFCAP))
430 @@ -430,7 +430,7 @@ int cap_inode_setxattr(struct dentry *de
433 int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
435 + const char *name, struct file *file)
437 if (!strcmp(name, XATTR_NAME_CAPS)) {
438 if (!capable(CAP_SETFCAP))
439 --- a/security/security.c
440 +++ b/security/security.c
441 @@ -473,12 +473,12 @@ void security_inode_delete(struct inode
443 int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
444 const char *name, const void *value, size_t size,
446 + int flags, struct file *file)
448 if (unlikely(IS_PRIVATE(dentry->d_inode)))
450 return security_ops->inode_setxattr(dentry, mnt, name, value, size,
455 void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
456 @@ -492,26 +492,27 @@ void security_inode_post_setxattr(struct
459 int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
461 + const char *name, struct file *file)
463 if (unlikely(IS_PRIVATE(dentry->d_inode)))
465 - return security_ops->inode_getxattr(dentry, mnt, name);
466 + return security_ops->inode_getxattr(dentry, mnt, name, file);
469 -int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt)
470 +int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
473 if (unlikely(IS_PRIVATE(dentry->d_inode)))
475 - return security_ops->inode_listxattr(dentry, mnt);
476 + return security_ops->inode_listxattr(dentry, mnt, file);
479 int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
481 + const char *name, struct file *file)
483 if (unlikely(IS_PRIVATE(dentry->d_inode)))
485 - return security_ops->inode_removexattr(dentry, mnt, name);
486 + return security_ops->inode_removexattr(dentry, mnt, name, file);
489 int security_inode_need_killpriv(struct dentry *dentry)
490 --- a/security/selinux/hooks.c
491 +++ b/security/selinux/hooks.c
492 @@ -2715,7 +2715,7 @@ static int selinux_inode_setotherxattr(s
494 static int selinux_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
495 const char *name, const void *value,
496 - size_t size, int flags)
497 + size_t size, int flags, struct file *file)
499 struct task_security_struct *tsec = current->security;
500 struct inode *inode = dentry->d_inode;
501 @@ -2797,18 +2797,20 @@ static void selinux_inode_post_setxattr(
504 static int selinux_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
506 + const char *name, struct file *file)
508 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
511 -static int selinux_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt)
512 +static int selinux_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
515 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
518 static int selinux_inode_removexattr(struct dentry *dentry,
519 - struct vfsmount *mnt, const char *name)
520 + struct vfsmount *mnt, const char *name,
523 if (strcmp(name, XATTR_NAME_SELINUX))
524 return selinux_inode_setotherxattr(dentry, name);
525 --- a/security/smack/smack_lsm.c
526 +++ b/security/smack/smack_lsm.c
527 @@ -600,6 +600,7 @@ static int smack_inode_getattr(struct vf
533 * This protects the Smack attribute explicitly.
535 @@ -607,7 +608,7 @@ static int smack_inode_getattr(struct vf
537 static int smack_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
538 const char *name, const void *value,
539 - size_t size, int flags)
540 + size_t size, int flags, struct file *file)
544 @@ -619,7 +620,8 @@ static int smack_inode_setxattr(struct d
548 - rc = cap_inode_setxattr(dentry, mnt, name, value, size, flags);
549 + rc = cap_inode_setxattr(dentry, mnt, name, value, size, flags,
553 rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
554 @@ -675,11 +677,12 @@ static void smack_inode_post_setxattr(st
555 * @dentry: the object
560 * Returns 0 if access is permitted, an error code otherwise
562 static int smack_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
564 + const char *name, struct file *file)
566 return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ);
568 @@ -689,13 +692,14 @@ static int smack_inode_getxattr(struct d
569 * @dentry: the object
571 * @name: name of the attribute
574 * Removing the Smack attribute requires CAP_MAC_ADMIN
576 * Returns 0 if access is permitted, an error code otherwise
578 static int smack_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
580 + const char *name, struct file *file)
584 @@ -705,7 +709,7 @@ static int smack_inode_removexattr(struc
585 if (!capable(CAP_MAC_ADMIN))
588 - rc = cap_inode_removexattr(dentry, mnt, name);
589 + rc = cap_inode_removexattr(dentry, mnt, name, file);
592 rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);