| From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
| From: Mark Salyzyn <salyzyn@android.com> |
| Date: Mon, 15 Jul 2019 15:46:45 -0700 |
| Subject: 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 bc14781886bf..c057e51057f7 100644 |
| --- a/fs/overlayfs/inode.c |
| +++ b/fs/overlayfs/inode.c |
| @@ -363,7 +363,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; |
| @@ -371,7 +371,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(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 6934bcf030f0..ab3d031c422b 100644 |
| --- a/fs/overlayfs/overlayfs.h |
| +++ b/fs/overlayfs/overlayfs.h |
| @@ -356,7 +356,7 @@ int ovl_permission(struct inode *inode, int mask); |
| 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 57f5f948ae0a..c91e7b604631 100644 |
| --- a/fs/overlayfs/super.c |
| +++ b/fs/overlayfs/super.c |
| @@ -857,7 +857,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, int flags) |
| { |
| - 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 |
| @@ -939,7 +939,7 @@ static int ovl_other_xattr_get(const struct xattr_handler *handler, |
| const char *name, void *buffer, size_t size, |
| int flags) |
| { |
| - 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, |