From e2d54786e82abbcd3393ddf7fbcae6ce04492405 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Tue, 23 Jul 2019 13:53:48 -0700 Subject: [PATCH] ANDROID: overlayfs: internal getxattr operations without sepolicy checking Check impure, opaque, origin & meta xattr with no sepolicy audit (using __vfs_getxattr) since these operations are internal to overlayfs operations and do not disclose any data. This became an issue for credential override off since sys_admin would have been required by the caller; whereas would have been inherently present for the creator since it performed the mount. This is a change in operations since we do not check in the new ovl_vfs_getxattr function if the credential override is off or not. Reasoning is that the sepolicy check is unnecessary overhead, especially since the check can be expensive. Signed-off-by: Mark Salyzyn Bug: 133515582 Bug: 136124883 Bug: 129319403 Change-Id: I34d99cc46e9e87a79efc8d05f85980bbc137f7eb --- fs/overlayfs/namei.c | 12 +++++++----- fs/overlayfs/overlayfs.h | 2 ++ fs/overlayfs/util.c | 24 +++++++++++++++--------- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index ee31e0eba309..499cd1f4fa85 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c @@ -109,10 +109,11 @@ int ovl_check_fh_len(struct ovl_fh *fh, int fh_len) static struct ovl_fh *ovl_get_fh(struct dentry *dentry, const char *name) { - int res, err; + ssize_t res; + int err; struct ovl_fh *fh = NULL; - res = vfs_getxattr(dentry, name, NULL, 0); + res = ovl_vfs_getxattr(dentry, name, NULL, 0); if (res < 0) { if (res == -ENODATA || res == -EOPNOTSUPP) return NULL; @@ -126,7 +127,7 @@ static struct ovl_fh *ovl_get_fh(struct dentry *dentry, const char *name) if (!fh) return ERR_PTR(-ENOMEM); - res = vfs_getxattr(dentry, name, fh, res); + res = ovl_vfs_getxattr(dentry, name, fh, res); if (res < 0) goto fail; @@ -144,10 +145,11 @@ static struct ovl_fh *ovl_get_fh(struct dentry *dentry, const char *name) return NULL; fail: - pr_warn_ratelimited("overlayfs: failed to get origin (%i)\n", res); + pr_warn_ratelimited("overlayfs: failed to get origin (%zi)\n", res); goto out; invalid: - pr_warn_ratelimited("overlayfs: invalid origin (%*phN)\n", res, fh); + pr_warn_ratelimited("overlayfs: invalid origin (%*phN)\n", + (int)res, fh); goto out; } diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index 25b31fcc8072..3227f21290bd 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -209,6 +209,8 @@ void ovl_drop_write(struct dentry *dentry); struct dentry *ovl_workdir(struct dentry *dentry); const struct cred *ovl_override_creds(struct super_block *sb); void ovl_revert_creds(const struct cred *oldcred); +ssize_t ovl_vfs_getxattr(struct dentry *dentry, const char *name, void *buf, + size_t size); struct super_block *ovl_same_sb(struct super_block *sb); int ovl_can_decode_fh(struct super_block *sb); struct dentry *ovl_indexdir(struct super_block *sb); diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index 3ec8580d05f6..0937b071a633 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -51,6 +51,12 @@ void ovl_revert_creds(const struct cred *old_cred) revert_creds(old_cred); } +ssize_t ovl_vfs_getxattr(struct dentry *dentry, const char *name, void *buf, + size_t size) +{ + return __vfs_getxattr(dentry, d_inode(dentry), name, buf, size); +} + struct super_block *ovl_same_sb(struct super_block *sb) { struct ovl_fs *ofs = sb->s_fs_info; @@ -549,9 +555,9 @@ void ovl_copy_up_end(struct dentry *dentry) bool ovl_check_origin_xattr(struct dentry *dentry) { - int res; + ssize_t res; - res = vfs_getxattr(dentry, OVL_XATTR_ORIGIN, NULL, 0); + res = ovl_vfs_getxattr(dentry, OVL_XATTR_ORIGIN, NULL, 0); /* Zero size value means "copied up but origin unknown" */ if (res >= 0) @@ -562,13 +568,13 @@ bool ovl_check_origin_xattr(struct dentry *dentry) bool ovl_check_dir_xattr(struct dentry *dentry, const char *name) { - int res; + ssize_t res; char val; if (!d_is_dir(dentry)) return false; - res = vfs_getxattr(dentry, name, &val, 1); + res = ovl_vfs_getxattr(dentry, name, &val, 1); if (res == 1 && val == 'y') return true; @@ -852,13 +858,13 @@ int ovl_lock_rename_workdir(struct dentry *workdir, struct dentry *upperdir) /* err < 0, 0 if no metacopy xattr, 1 if metacopy xattr found */ int ovl_check_metacopy_xattr(struct dentry *dentry) { - int res; + ssize_t res; /* Only regular files can have metacopy xattr */ if (!S_ISREG(d_inode(dentry)->i_mode)) return 0; - res = vfs_getxattr(dentry, OVL_XATTR_METACOPY, NULL, 0); + res = ovl_vfs_getxattr(dentry, OVL_XATTR_METACOPY, NULL, 0); if (res < 0) { if (res == -ENODATA || res == -EOPNOTSUPP) return 0; @@ -867,7 +873,7 @@ int ovl_check_metacopy_xattr(struct dentry *dentry) return 1; out: - pr_warn_ratelimited("overlayfs: failed to get metacopy (%i)\n", res); + pr_warn_ratelimited("overlayfs: failed to get metacopy (%zi)\n", res); return res; } @@ -893,7 +899,7 @@ ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value, ssize_t res; char *buf = NULL; - res = vfs_getxattr(dentry, name, NULL, 0); + res = ovl_vfs_getxattr(dentry, name, NULL, 0); if (res < 0) { if (res == -ENODATA || res == -EOPNOTSUPP) return -ENODATA; @@ -905,7 +911,7 @@ ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value, if (!buf) return -ENOMEM; - res = vfs_getxattr(dentry, name, buf, res); + res = ovl_vfs_getxattr(dentry, name, buf, res); if (res < 0) goto fail; }