diff options
author | Vivek Goyal <vgoyal@redhat.com> | 2016-07-13 10:44:49 -0400 |
---|---|---|
committer | Paul Moore <paul@paul-moore.com> | 2016-08-08 20:42:13 -0400 |
commit | 121ab822ef21914adac2fa3730efeeb8fd762473 (patch) | |
tree | 7fd5f6947837b361c249ec976af17bee10b22a2e | |
parent | 56909eb3f559103196ecbf2c08c923e0804980fb (diff) |
security,overlayfs: Provide security hook for copy up of xattrs for overlay file
Provide a security hook which is called when xattrs of a file are being
copied up. This hook is called once for each xattr and LSM can return
0 if the security module wants the xattr to be copied up, 1 if the
security module wants the xattr to be discarded on the copy, -EOPNOTSUPP
if the security module does not handle/manage the xattr, or a -errno
upon an error.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
[PM: whitespace cleanup for checkpatch.pl]
Signed-off-by: Paul Moore <paul@paul-moore.com>
-rw-r--r-- | fs/overlayfs/copy_up.c | 7 | ||||
-rw-r--r-- | include/linux/lsm_hooks.h | 10 | ||||
-rw-r--r-- | include/linux/security.h | 6 | ||||
-rw-r--r-- | security/security.c | 8 |
4 files changed, 31 insertions, 0 deletions
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c index c297b1f5a05e..cd65f12b3464 100644 --- a/fs/overlayfs/copy_up.c +++ b/fs/overlayfs/copy_up.c | |||
@@ -103,6 +103,13 @@ retry: | |||
103 | goto retry; | 103 | goto retry; |
104 | } | 104 | } |
105 | 105 | ||
106 | error = security_inode_copy_up_xattr(name); | ||
107 | if (error < 0 && error != -EOPNOTSUPP) | ||
108 | break; | ||
109 | if (error == 1) { | ||
110 | error = 0; | ||
111 | continue; /* Discard */ | ||
112 | } | ||
106 | error = vfs_setxattr(new, name, value, size, 0); | 113 | error = vfs_setxattr(new, name, value, size, 0); |
107 | if (error) | 114 | if (error) |
108 | break; | 115 | break; |
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index cb69fc829053..57971229551b 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h | |||
@@ -410,6 +410,14 @@ | |||
410 | * @src indicates the union dentry of file that is being copied up. | 410 | * @src indicates the union dentry of file that is being copied up. |
411 | * @new pointer to pointer to return newly allocated creds. | 411 | * @new pointer to pointer to return newly allocated creds. |
412 | * Returns 0 on success or a negative error code on error. | 412 | * Returns 0 on success or a negative error code on error. |
413 | * @inode_copy_up_xattr: | ||
414 | * Filter the xattrs being copied up when a unioned file is copied | ||
415 | * up from a lower layer to the union/overlay layer. | ||
416 | * @name indicates the name of the xattr. | ||
417 | * Returns 0 to accept the xattr, 1 to discard the xattr, -EOPNOTSUPP if | ||
418 | * security module does not know about attribute or a negative error code | ||
419 | * to abort the copy up. Note that the caller is responsible for reading | ||
420 | * and writing the xattrs as this hook is merely a filter. | ||
413 | * | 421 | * |
414 | * Security hooks for file operations | 422 | * Security hooks for file operations |
415 | * | 423 | * |
@@ -1435,6 +1443,7 @@ union security_list_options { | |||
1435 | size_t buffer_size); | 1443 | size_t buffer_size); |
1436 | void (*inode_getsecid)(struct inode *inode, u32 *secid); | 1444 | void (*inode_getsecid)(struct inode *inode, u32 *secid); |
1437 | int (*inode_copy_up)(struct dentry *src, struct cred **new); | 1445 | int (*inode_copy_up)(struct dentry *src, struct cred **new); |
1446 | int (*inode_copy_up_xattr)(const char *name); | ||
1438 | 1447 | ||
1439 | int (*file_permission)(struct file *file, int mask); | 1448 | int (*file_permission)(struct file *file, int mask); |
1440 | int (*file_alloc_security)(struct file *file); | 1449 | int (*file_alloc_security)(struct file *file); |
@@ -1707,6 +1716,7 @@ struct security_hook_heads { | |||
1707 | struct list_head inode_listsecurity; | 1716 | struct list_head inode_listsecurity; |
1708 | struct list_head inode_getsecid; | 1717 | struct list_head inode_getsecid; |
1709 | struct list_head inode_copy_up; | 1718 | struct list_head inode_copy_up; |
1719 | struct list_head inode_copy_up_xattr; | ||
1710 | struct list_head file_permission; | 1720 | struct list_head file_permission; |
1711 | struct list_head file_alloc_security; | 1721 | struct list_head file_alloc_security; |
1712 | struct list_head file_free_security; | 1722 | struct list_head file_free_security; |
diff --git a/include/linux/security.h b/include/linux/security.h index c5b0ccd6c8b6..536fafdfa10a 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -283,6 +283,7 @@ int security_inode_setsecurity(struct inode *inode, const char *name, const void | |||
283 | int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size); | 283 | int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size); |
284 | void security_inode_getsecid(struct inode *inode, u32 *secid); | 284 | void security_inode_getsecid(struct inode *inode, u32 *secid); |
285 | int security_inode_copy_up(struct dentry *src, struct cred **new); | 285 | int security_inode_copy_up(struct dentry *src, struct cred **new); |
286 | int security_inode_copy_up_xattr(const char *name); | ||
286 | int security_file_permission(struct file *file, int mask); | 287 | int security_file_permission(struct file *file, int mask); |
287 | int security_file_alloc(struct file *file); | 288 | int security_file_alloc(struct file *file); |
288 | void security_file_free(struct file *file); | 289 | void security_file_free(struct file *file); |
@@ -764,6 +765,11 @@ static inline int security_inode_copy_up(struct dentry *src, struct cred **new) | |||
764 | return 0; | 765 | return 0; |
765 | } | 766 | } |
766 | 767 | ||
768 | static inline int security_inode_copy_up_xattr(const char *name) | ||
769 | { | ||
770 | return -EOPNOTSUPP; | ||
771 | } | ||
772 | |||
767 | static inline int security_file_permission(struct file *file, int mask) | 773 | static inline int security_file_permission(struct file *file, int mask) |
768 | { | 774 | { |
769 | return 0; | 775 | return 0; |
diff --git a/security/security.c b/security/security.c index f2a7f27bd3e9..a9e2bb9fb9d3 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -754,6 +754,12 @@ int security_inode_copy_up(struct dentry *src, struct cred **new) | |||
754 | } | 754 | } |
755 | EXPORT_SYMBOL(security_inode_copy_up); | 755 | EXPORT_SYMBOL(security_inode_copy_up); |
756 | 756 | ||
757 | int security_inode_copy_up_xattr(const char *name) | ||
758 | { | ||
759 | return call_int_hook(inode_copy_up_xattr, -EOPNOTSUPP, name); | ||
760 | } | ||
761 | EXPORT_SYMBOL(security_inode_copy_up_xattr); | ||
762 | |||
757 | int security_file_permission(struct file *file, int mask) | 763 | int security_file_permission(struct file *file, int mask) |
758 | { | 764 | { |
759 | int ret; | 765 | int ret; |
@@ -1692,6 +1698,8 @@ struct security_hook_heads security_hook_heads = { | |||
1692 | LIST_HEAD_INIT(security_hook_heads.inode_getsecid), | 1698 | LIST_HEAD_INIT(security_hook_heads.inode_getsecid), |
1693 | .inode_copy_up = | 1699 | .inode_copy_up = |
1694 | LIST_HEAD_INIT(security_hook_heads.inode_copy_up), | 1700 | LIST_HEAD_INIT(security_hook_heads.inode_copy_up), |
1701 | .inode_copy_up_xattr = | ||
1702 | LIST_HEAD_INIT(security_hook_heads.inode_copy_up_xattr), | ||
1695 | .file_permission = | 1703 | .file_permission = |
1696 | LIST_HEAD_INIT(security_hook_heads.file_permission), | 1704 | LIST_HEAD_INIT(security_hook_heads.file_permission), |
1697 | .file_alloc_security = | 1705 | .file_alloc_security = |