| From 82f90ae85db61597709e24c1dbfac7315c08f61f Mon Sep 17 00:00:00 2001 |
| From: Mark Salyzyn <salyzyn@android.com> |
| Date: Mon, 15 Jul 2019 15:46:45 -0700 |
| Subject: [PATCH] FROMLIST: overlayfs: handle XATTR_NOSECURITY flag for get |
| xattr method |
| |
| Because of the overlayfs getxattr recursion, the incoming inode fails |
| to update the selinux sid resulting in avc denials being reported |
| against a target context of u:object_r:unlabeled:s0. |
| |
| Solution is to respond to the XATTR_NOSECURITY flag in get xattr |
| method that calls the __vfs_getxattr handler instead so that the |
| context can be read in, rather than being denied with an -EACCES |
| when vfs_getxattr handler is called. |
| |
| For the use case where access is to be blocked by the security layer. |
| |
| The path then would be security(dentry) -> |
| __vfs_getxattr({dentry...XATTR_NOSECURITY}) -> |
| handler->get({dentry...XATTR_NOSECURITY}) -> |
| __vfs_getxattr({realdentry...XATTR_NOSECURITY}) -> |
| lower_handler->get({realdentry...XATTR_NOSECURITY}) which |
| would report back through the chain data and success as expected, |
| the logging security layer at the top would have the data to |
| determine the access permissions and report back to the logs and |
| the caller that the target context was blocked. |
| |
| For selinux this would solve the cosmetic issue of the selinux log |
| and allow audit2allow to correctly report the rule needed to address |
| the access problem. |
| |
| Signed-off-by: Mark Salyzyn <salyzyn@android.com> |
| Cc: Miklos Szeredi <miklos@szeredi.hu> |
| Cc: Jonathan Corbet <corbet@lwn.net> |
| Cc: Vivek Goyal <vgoyal@redhat.com> |
| Cc: Eric W. Biederman <ebiederm@xmission.com> |
| Cc: Amir Goldstein <amir73il@gmail.com> |
| Cc: Randy Dunlap <rdunlap@infradead.org> |
| Cc: Stephen Smalley <sds@tycho.nsa.gov> |
| Cc: linux-unionfs@vger.kernel.org |
| Cc: linux-doc@vger.kernel.org |
| Cc: linux-kernel@vger.kernel.org |
| Cc: kernel-team@android.com |
| Cc: linux-security-module@vger.kernel.org |
| |
| (cherry pick from https://lore.kernel.org/lkml/20191104215253.141818-3-salyzyn@android.com/) |
| Signed-off-by: Mark Salyzyn <salyzyn@google.com> |
| Bug: 133515582 |
| Bug: 136124883 |
| Bug: 129319403 |
| Change-Id: Ia39543c5ce617976f14d790fb88e471d575ffd65 |
| --- |
| fs/overlayfs/inode.c | 5 +++-- |
| fs/overlayfs/overlayfs.h | 2 +- |
| fs/overlayfs/super.c | 4 ++-- |
| 3 files changed, 6 insertions(+), 5 deletions(-) |
| |
| diff --git a/fs/overlayfs/inode.c b/fs/overlayfs/inode.c |
| index 003cf83bf78a..175192bc44fc 100644 |
| --- a/fs/overlayfs/inode.c |
| +++ b/fs/overlayfs/inode.c |
| @@ -389,7 +389,7 @@ int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name, |
| } |
| |
| int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name, |
| - void *value, size_t size) |
| + void *value, size_t size, int flags) |
| { |
| ssize_t res; |
| const struct cred *old_cred; |
| @@ -397,7 +397,8 @@ int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name, |
| ovl_i_dentry_upper(inode) ?: ovl_dentry_lower(dentry); |
| |
| old_cred = ovl_override_creds(dentry->d_sb); |
| - res = vfs_getxattr(&init_user_ns, realdentry, name, value, size); |
| + res = __vfs_getxattr(realdentry, d_inode(realdentry), name, |
| + value, size, flags); |
| revert_creds(old_cred); |
| return res; |
| } |
| diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h |
| index 95cff83786a5..cc953956c007 100644 |
| --- a/fs/overlayfs/overlayfs.h |
| +++ b/fs/overlayfs/overlayfs.h |
| @@ -454,7 +454,7 @@ int ovl_permission(struct user_namespace *mnt_userns, struct inode *inode, |
| int ovl_xattr_set(struct dentry *dentry, struct inode *inode, const char *name, |
| const void *value, size_t size, int flags); |
| int ovl_xattr_get(struct dentry *dentry, struct inode *inode, const char *name, |
| - void *value, size_t size); |
| + void *value, size_t size, int flags); |
| ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size); |
| struct posix_acl *ovl_get_acl(struct inode *inode, int type); |
| int ovl_update_time(struct inode *inode, struct timespec64 *ts, int flags); |
| diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c |
| index fdd72f1a9c5e..fe66c5b88240 100644 |
| --- a/fs/overlayfs/super.c |
| +++ b/fs/overlayfs/super.c |
| @@ -990,7 +990,7 @@ ovl_posix_acl_xattr_get(const struct xattr_handler *handler, |
| struct dentry *dentry, struct inode *inode, |
| const char *name, void *buffer, size_t size) |
| { |
| - return ovl_xattr_get(dentry, inode, handler->name, buffer, size); |
| + return ovl_xattr_get(dentry, inode, handler->name, buffer, size, flags); |
| } |
| |
| static int __maybe_unused |
| @@ -1072,7 +1072,7 @@ static int ovl_other_xattr_get(const struct xattr_handler *handler, |
| struct dentry *dentry, struct inode *inode, |
| const char *name, void *buffer, size_t size) |
| { |
| - return ovl_xattr_get(dentry, inode, name, buffer, size); |
| + return ovl_xattr_get(dentry, inode, name, buffer, size, flags); |
| } |
| |
| static int ovl_other_xattr_set(const struct xattr_handler *handler, |
| -- |
| 2.17.1 |
| |