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(-)
22 Index: linux-2.6.27/fs/xattr.c
23 ===================================================================
24 --- linux-2.6.27.orig/fs/xattr.c
25 +++ linux-2.6.27/fs/xattr.c
26 @@ -68,7 +68,7 @@ xattr_permission(struct inode *inode, co
29 vfs_setxattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
30 - const void *value, size_t size, int flags)
31 + const void *value, size_t size, int flags, struct file *file)
33 struct inode *inode = dentry->d_inode;
35 @@ -78,7 +78,7 @@ vfs_setxattr(struct dentry *dentry, stru
38 mutex_lock(&inode->i_mutex);
39 - error = security_inode_setxattr(dentry, mnt, name, value, size, flags);
40 + error = security_inode_setxattr(dentry, mnt, name, value, size, flags, file);
44 @@ -132,7 +132,7 @@ EXPORT_SYMBOL_GPL(xattr_getsecurity);
47 vfs_getxattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
48 - void *value, size_t size)
49 + void *value, size_t size, struct file *file)
51 struct inode *inode = dentry->d_inode;
53 @@ -141,7 +141,7 @@ vfs_getxattr(struct dentry *dentry, stru
57 - error = security_inode_getxattr(dentry, mnt, name);
58 + error = security_inode_getxattr(dentry, mnt, name, file);
62 @@ -169,12 +169,12 @@ EXPORT_SYMBOL_GPL(vfs_getxattr);
65 vfs_listxattr(struct dentry *dentry, struct vfsmount *mnt, char *list,
67 + size_t size, struct file *file)
69 struct inode *inode = dentry->d_inode;
72 - error = security_inode_listxattr(dentry, mnt);
73 + error = security_inode_listxattr(dentry, mnt, file);
77 @@ -190,7 +190,8 @@ vfs_listxattr(struct dentry *dentry, str
78 EXPORT_SYMBOL_GPL(vfs_listxattr);
81 -vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, const char *name)
82 +vfs_removexattr(struct dentry *dentry, struct vfsmount *mnt, const char *name,
85 struct inode *inode = dentry->d_inode;
87 @@ -202,7 +203,7 @@ vfs_removexattr(struct dentry *dentry, s
91 - error = security_inode_removexattr(dentry, mnt, name);
92 + error = security_inode_removexattr(dentry, mnt, name, file);
96 @@ -222,7 +223,7 @@ EXPORT_SYMBOL_GPL(vfs_removexattr);
99 setxattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name,
100 - const void __user *value, size_t size, int flags)
101 + const void __user *value, size_t size, int flags, struct file *file)
105 @@ -249,7 +250,7 @@ setxattr(struct dentry *dentry, struct v
109 - error = vfs_setxattr(dentry, mnt, kname, kvalue, size, flags);
110 + error = vfs_setxattr(dentry, mnt, kname, kvalue, size, flags, file);
114 @@ -266,7 +267,7 @@ SYSCALL_DEFINE5(setxattr, const char __u
116 error = mnt_want_write(path.mnt);
118 - error = setxattr(path.dentry, path.mnt, name, value, size, flags);
119 + error = setxattr(path.dentry, path.mnt, name, value, size, flags, NULL);
120 mnt_drop_write(path.mnt);
123 @@ -285,7 +286,7 @@ SYSCALL_DEFINE5(lsetxattr, const char __
125 error = mnt_want_write(path.mnt);
127 - error = setxattr(path.dentry, path.mnt, name, value, size, flags);
128 + error = setxattr(path.dentry, path.mnt, name, value, size, flags, NULL);
129 mnt_drop_write(path.mnt);
132 @@ -306,7 +307,8 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, cons
133 audit_inode(NULL, dentry);
134 error = mnt_want_write_file(f->f_path.mnt, f);
136 - error = setxattr(dentry, f->f_vfsmnt, name, value, size, flags);
137 + error = setxattr(dentry, f->f_vfsmnt, name, value, size, flags,
139 mnt_drop_write(f->f_path.mnt);
142 @@ -318,7 +320,7 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, cons
145 getxattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name,
146 - void __user *value, size_t size)
147 + void __user *value, size_t size, struct file *file)
151 @@ -338,7 +340,7 @@ getxattr(struct dentry *dentry, struct v
155 - error = vfs_getxattr(dentry, mnt, kname, kvalue, size);
156 + error = vfs_getxattr(dentry, mnt, kname, kvalue, size, file);
158 if (size && copy_to_user(value, kvalue, error))
160 @@ -360,7 +362,7 @@ SYSCALL_DEFINE4(getxattr, const char __u
161 error = user_path(pathname, &path);
164 - error = getxattr(path.dentry, path.mnt, name, value, size);
165 + error = getxattr(path.dentry, path.mnt, name, value, size, NULL);
169 @@ -374,7 +376,7 @@ SYSCALL_DEFINE4(lgetxattr, const char __
170 error = user_lpath(pathname, &path);
173 - error = getxattr(path.dentry, path.mnt, name, value, size);
174 + error = getxattr(path.dentry, path.mnt, name, value, size, NULL);
178 @@ -389,7 +391,7 @@ SYSCALL_DEFINE4(fgetxattr, int, fd, cons
181 audit_inode(NULL, f->f_path.dentry);
182 - error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size);
183 + error = getxattr(f->f_path.dentry, f->f_path.mnt, name, value, size, f);
187 @@ -399,7 +401,7 @@ SYSCALL_DEFINE4(fgetxattr, int, fd, cons
190 listxattr(struct dentry *dentry, struct vfsmount *mnt, char __user *list,
192 + size_t size, struct file *file)
196 @@ -412,7 +414,7 @@ listxattr(struct dentry *dentry, struct
200 - error = vfs_listxattr(dentry, mnt, klist, size);
201 + error = vfs_listxattr(dentry, mnt, klist, size, file);
203 if (size && copy_to_user(list, klist, error))
205 @@ -434,7 +436,7 @@ SYSCALL_DEFINE3(listxattr, const char __
206 error = user_path(pathname, &path);
209 - error = listxattr(path.dentry, path.mnt, list, size);
210 + error = listxattr(path.dentry, path.mnt, list, size, NULL);
214 @@ -448,7 +450,7 @@ SYSCALL_DEFINE3(llistxattr, const char _
215 error = user_lpath(pathname, &path);
218 - error = listxattr(path.dentry, path.mnt, list, size);
219 + error = listxattr(path.dentry, path.mnt, list, size, NULL);
223 @@ -462,7 +464,7 @@ SYSCALL_DEFINE3(flistxattr, int, fd, cha
226 audit_inode(NULL, f->f_path.dentry);
227 - error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size);
228 + error = listxattr(f->f_path.dentry, f->f_path.mnt, list, size, f);
232 @@ -471,7 +473,8 @@ SYSCALL_DEFINE3(flistxattr, int, fd, cha
233 * Extended attribute REMOVE operations
236 -removexattr(struct dentry *dentry, struct vfsmount *mnt, const char __user *name)
237 +removexattr(struct dentry *dentry, struct vfsmount *mnt,
238 + const char __user *name, struct file *file)
241 char kname[XATTR_NAME_MAX + 1];
242 @@ -482,7 +485,7 @@ removexattr(struct dentry *dentry, struc
246 - return vfs_removexattr(dentry, mnt, kname);
247 + return vfs_removexattr(dentry, mnt, kname, file);
250 SYSCALL_DEFINE2(removexattr, const char __user *, pathname,
251 @@ -496,7 +499,7 @@ SYSCALL_DEFINE2(removexattr, const char
253 error = mnt_want_write(path.mnt);
255 - error = removexattr(path.dentry, path.mnt, name);
256 + error = removexattr(path.dentry, path.mnt, name, NULL);
257 mnt_drop_write(path.mnt);
260 @@ -514,7 +517,7 @@ SYSCALL_DEFINE2(lremovexattr, const char
262 error = mnt_want_write(path.mnt);
264 - error = removexattr(path.dentry, path.mnt, name);
265 + error = removexattr(path.dentry, path.mnt, name, NULL);
266 mnt_drop_write(path.mnt);
269 @@ -534,7 +537,7 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, c
270 audit_inode(NULL, dentry);
271 error = mnt_want_write_file(f->f_path.mnt, f);
273 - error = removexattr(dentry, f->f_path.mnt, name);
274 + error = removexattr(dentry, f->f_path.mnt, name, f);
275 mnt_drop_write(f->f_path.mnt);
278 Index: linux-2.6.27/include/linux/security.h
279 ===================================================================
280 --- linux-2.6.27.orig/include/linux/security.h
281 +++ linux-2.6.27/include/linux/security.h
282 @@ -56,9 +56,9 @@ extern void cap_bprm_apply_creds(struct
283 extern int cap_bprm_secureexec(struct linux_binprm *bprm);
284 extern int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
285 const char *name, const void *value, size_t size,
287 + int flags, struct file *file);
288 extern int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
290 + const char *name, struct file *file);
291 extern int cap_inode_need_killpriv(struct dentry *dentry);
292 extern int cap_inode_killpriv(struct dentry *dentry);
293 extern int cap_task_post_setuid(uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
294 @@ -1396,16 +1396,17 @@ struct security_operations {
295 void (*inode_delete) (struct inode *inode);
296 int (*inode_setxattr) (struct dentry *dentry, struct vfsmount *mnt,
297 const char *name, const void *value, size_t size,
299 + int flags, struct file *file);
300 void (*inode_post_setxattr) (struct dentry *dentry,
301 struct vfsmount *mnt,
302 const char *name, const void *value,
303 size_t size, int flags);
304 int (*inode_getxattr) (struct dentry *dentry, struct vfsmount *mnt,
306 - int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt);
307 + const char *name, struct file *file);
308 + int (*inode_listxattr) (struct dentry *dentry, struct vfsmount *mnt,
309 + struct file *file);
310 int (*inode_removexattr) (struct dentry *dentry, struct vfsmount *mnt,
312 + const char *name, struct file *file);
313 int (*inode_need_killpriv) (struct dentry *dentry);
314 int (*inode_killpriv) (struct dentry *dentry);
315 int (*inode_getsecurity) (const struct inode *inode, const char *name, void **buffer, bool alloc);
316 @@ -1675,15 +1676,16 @@ int security_inode_getattr(struct vfsmou
317 void security_inode_delete(struct inode *inode);
318 int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
319 const char *name, const void *value,
320 - size_t size, int flags);
321 + size_t size, int flags, struct file *file);
322 void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
323 const char *name, const void *value,
324 size_t size, int flags);
325 int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
327 -int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt);
328 + const char *name, struct file *file);
329 +int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
330 + struct file *file);
331 int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
333 + const char *name, struct file *file);
334 int security_inode_need_killpriv(struct dentry *dentry);
335 int security_inode_killpriv(struct dentry *dentry);
336 int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc);
337 @@ -2105,9 +2107,10 @@ static inline void security_inode_delete
338 static inline int security_inode_setxattr(struct dentry *dentry,
339 struct vfsmount *mnt,
340 const char *name, const void *value,
341 - size_t size, int flags)
342 + size_t size, int flags,
345 - return cap_inode_setxattr(dentry, mnt, name, value, size, flags);
346 + return cap_inode_setxattr(dentry, mnt, name, value, size, flags, file);
349 static inline void security_inode_post_setxattr(struct dentry *dentry,
350 @@ -2119,22 +2122,25 @@ static inline void security_inode_post_s
352 static inline int security_inode_getxattr(struct dentry *dentry,
353 struct vfsmount *mnt,
361 static inline int security_inode_listxattr(struct dentry *dentry,
362 - struct vfsmount *mnt)
363 + struct vfsmount *mnt,
369 static inline int security_inode_removexattr(struct dentry *dentry,
370 struct vfsmount *mnt,
375 - return cap_inode_removexattr(dentry, mnt, name);
376 + return cap_inode_removexattr(dentry, mnt, name, file);
379 static inline int security_inode_need_killpriv(struct dentry *dentry)
380 Index: linux-2.6.27/include/linux/xattr.h
381 ===================================================================
382 --- linux-2.6.27.orig/include/linux/xattr.h
383 +++ linux-2.6.27/include/linux/xattr.h
386 #include <linux/types.h>
387 #include <linux/mount.h>
388 +#include <linux/fs.h>
391 #define XATTR_OS2_PREFIX "os2."
392 @@ -48,10 +49,10 @@ struct xattr_handler {
395 ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
396 -ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, const char *, void *, size_t);
397 -ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list, size_t size);
398 -int vfs_setxattr(struct dentry *, struct vfsmount *, const char *, const void *, size_t, int);
399 -int vfs_removexattr(struct dentry *, struct vfsmount *mnt, const char *);
400 +ssize_t vfs_getxattr(struct dentry *, struct vfsmount *, const char *, void *, size_t, struct file *file);
401 +ssize_t vfs_listxattr(struct dentry *d, struct vfsmount *, char *list, size_t size, struct file *file);
402 +int vfs_setxattr(struct dentry *, struct vfsmount *, const char *, const void *, size_t, int, struct file *file);
403 +int vfs_removexattr(struct dentry *, struct vfsmount *mnt, const char *, struct file *file);
405 ssize_t generic_getxattr(struct dentry *dentry, const char *name, void *buffer, size_t size);
406 ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
407 Index: linux-2.6.27/security/capability.c
408 ===================================================================
409 --- linux-2.6.27.orig/security/capability.c
410 +++ linux-2.6.27/security/capability.c
411 @@ -242,12 +242,13 @@ static void cap_inode_post_setxattr(stru
414 static int cap_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
416 + const char *name, struct file *f)
421 -static int cap_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt)
422 +static int cap_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
427 Index: linux-2.6.27/security/commoncap.c
428 ===================================================================
429 --- linux-2.6.27.orig/security/commoncap.c
430 +++ linux-2.6.27/security/commoncap.c
431 @@ -416,7 +416,7 @@ int cap_bprm_secureexec (struct linux_bi
433 int cap_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
434 const char *name, const void *value, size_t size,
436 + int flags, struct file *file)
438 if (!strcmp(name, XATTR_NAME_CAPS)) {
439 if (!capable(CAP_SETFCAP))
440 @@ -430,7 +430,7 @@ int cap_inode_setxattr(struct dentry *de
443 int cap_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
445 + const char *name, struct file *file)
447 if (!strcmp(name, XATTR_NAME_CAPS)) {
448 if (!capable(CAP_SETFCAP))
449 Index: linux-2.6.27/security/security.c
450 ===================================================================
451 --- linux-2.6.27.orig/security/security.c
452 +++ linux-2.6.27/security/security.c
453 @@ -470,12 +470,12 @@ void security_inode_delete(struct inode
455 int security_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
456 const char *name, const void *value, size_t size,
458 + int flags, struct file *file)
460 if (unlikely(IS_PRIVATE(dentry->d_inode)))
462 return security_ops->inode_setxattr(dentry, mnt, name, value, size,
467 void security_inode_post_setxattr(struct dentry *dentry, struct vfsmount *mnt,
468 @@ -489,26 +489,27 @@ void security_inode_post_setxattr(struct
471 int security_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
473 + const char *name, struct file *file)
475 if (unlikely(IS_PRIVATE(dentry->d_inode)))
477 - return security_ops->inode_getxattr(dentry, mnt, name);
478 + return security_ops->inode_getxattr(dentry, mnt, name, file);
481 -int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt)
482 +int security_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
485 if (unlikely(IS_PRIVATE(dentry->d_inode)))
487 - return security_ops->inode_listxattr(dentry, mnt);
488 + return security_ops->inode_listxattr(dentry, mnt, file);
491 int security_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
493 + const char *name, struct file *file)
495 if (unlikely(IS_PRIVATE(dentry->d_inode)))
497 - return security_ops->inode_removexattr(dentry, mnt, name);
498 + return security_ops->inode_removexattr(dentry, mnt, name, file);
501 int security_inode_need_killpriv(struct dentry *dentry)
502 Index: linux-2.6.27/security/selinux/hooks.c
503 ===================================================================
504 --- linux-2.6.27.orig/security/selinux/hooks.c
505 +++ linux-2.6.27/security/selinux/hooks.c
506 @@ -2715,7 +2715,7 @@ static int selinux_inode_setotherxattr(s
508 static int selinux_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
509 const char *name, const void *value,
510 - size_t size, int flags)
511 + size_t size, int flags, struct file *file)
513 struct task_security_struct *tsec = current->security;
514 struct inode *inode = dentry->d_inode;
515 @@ -2797,18 +2797,20 @@ static void selinux_inode_post_setxattr(
518 static int selinux_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
520 + const char *name, struct file *file)
522 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
525 -static int selinux_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt)
526 +static int selinux_inode_listxattr(struct dentry *dentry, struct vfsmount *mnt,
529 return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
532 static int selinux_inode_removexattr(struct dentry *dentry,
533 - struct vfsmount *mnt, const char *name)
534 + struct vfsmount *mnt, const char *name,
537 if (strcmp(name, XATTR_NAME_SELINUX))
538 return selinux_inode_setotherxattr(dentry, name);
539 Index: linux-2.6.27/security/smack/smack_lsm.c
540 ===================================================================
541 --- linux-2.6.27.orig/security/smack/smack_lsm.c
542 +++ linux-2.6.27/security/smack/smack_lsm.c
543 @@ -600,6 +600,7 @@ static int smack_inode_getattr(struct vf
549 * This protects the Smack attribute explicitly.
551 @@ -607,7 +608,7 @@ static int smack_inode_getattr(struct vf
553 static int smack_inode_setxattr(struct dentry *dentry, struct vfsmount *mnt,
554 const char *name, const void *value,
555 - size_t size, int flags)
556 + size_t size, int flags, struct file *file)
560 @@ -619,7 +620,8 @@ static int smack_inode_setxattr(struct d
564 - rc = cap_inode_setxattr(dentry, mnt, name, value, size, flags);
565 + rc = cap_inode_setxattr(dentry, mnt, name, value, size, flags,
569 rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);
570 @@ -675,11 +677,12 @@ static void smack_inode_post_setxattr(st
571 * @dentry: the object
576 * Returns 0 if access is permitted, an error code otherwise
578 static int smack_inode_getxattr(struct dentry *dentry, struct vfsmount *mnt,
580 + const char *name, struct file *file)
582 return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ);
584 @@ -689,13 +692,14 @@ static int smack_inode_getxattr(struct d
585 * @dentry: the object
587 * @name: name of the attribute
590 * Removing the Smack attribute requires CAP_MAC_ADMIN
592 * Returns 0 if access is permitted, an error code otherwise
594 static int smack_inode_removexattr(struct dentry *dentry, struct vfsmount *mnt,
596 + const char *name, struct file *file)
600 @@ -705,7 +709,7 @@ static int smack_inode_removexattr(struc
601 if (!capable(CAP_MAC_ADMIN))
604 - rc = cap_inode_removexattr(dentry, mnt, name);
605 + rc = cap_inode_removexattr(dentry, mnt, name, file);
608 rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE);