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 <salyzyn@google.com> Bug: 133515582 Bug: 136124883 Bug: 129319403 Change-Id: I34d99cc46e9e87a79efc8d05f85980bbc137f7eb
This commit is contained in:
@@ -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)
|
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;
|
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 < 0) {
|
||||||
if (res == -ENODATA || res == -EOPNOTSUPP)
|
if (res == -ENODATA || res == -EOPNOTSUPP)
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -126,7 +127,7 @@ static struct ovl_fh *ovl_get_fh(struct dentry *dentry, const char *name)
|
|||||||
if (!fh)
|
if (!fh)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
res = vfs_getxattr(dentry, name, fh, res);
|
res = ovl_vfs_getxattr(dentry, name, fh, res);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@@ -144,10 +145,11 @@ static struct ovl_fh *ovl_get_fh(struct dentry *dentry, const char *name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
fail:
|
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;
|
goto out;
|
||||||
invalid:
|
invalid:
|
||||||
pr_warn_ratelimited("overlayfs: invalid origin (%*phN)\n", res, fh);
|
pr_warn_ratelimited("overlayfs: invalid origin (%*phN)\n",
|
||||||
|
(int)res, fh);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -209,6 +209,8 @@ void ovl_drop_write(struct dentry *dentry);
|
|||||||
struct dentry *ovl_workdir(struct dentry *dentry);
|
struct dentry *ovl_workdir(struct dentry *dentry);
|
||||||
const struct cred *ovl_override_creds(struct super_block *sb);
|
const struct cred *ovl_override_creds(struct super_block *sb);
|
||||||
void ovl_revert_creds(const struct cred *oldcred);
|
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);
|
struct super_block *ovl_same_sb(struct super_block *sb);
|
||||||
int ovl_can_decode_fh(struct super_block *sb);
|
int ovl_can_decode_fh(struct super_block *sb);
|
||||||
struct dentry *ovl_indexdir(struct super_block *sb);
|
struct dentry *ovl_indexdir(struct super_block *sb);
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ void ovl_revert_creds(const struct cred *old_cred)
|
|||||||
revert_creds(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 super_block *ovl_same_sb(struct super_block *sb)
|
||||||
{
|
{
|
||||||
struct ovl_fs *ofs = sb->s_fs_info;
|
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)
|
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" */
|
/* Zero size value means "copied up but origin unknown" */
|
||||||
if (res >= 0)
|
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)
|
bool ovl_check_dir_xattr(struct dentry *dentry, const char *name)
|
||||||
{
|
{
|
||||||
int res;
|
ssize_t res;
|
||||||
char val;
|
char val;
|
||||||
|
|
||||||
if (!d_is_dir(dentry))
|
if (!d_is_dir(dentry))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
res = vfs_getxattr(dentry, name, &val, 1);
|
res = ovl_vfs_getxattr(dentry, name, &val, 1);
|
||||||
if (res == 1 && val == 'y')
|
if (res == 1 && val == 'y')
|
||||||
return true;
|
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 */
|
/* err < 0, 0 if no metacopy xattr, 1 if metacopy xattr found */
|
||||||
int ovl_check_metacopy_xattr(struct dentry *dentry)
|
int ovl_check_metacopy_xattr(struct dentry *dentry)
|
||||||
{
|
{
|
||||||
int res;
|
ssize_t res;
|
||||||
|
|
||||||
/* Only regular files can have metacopy xattr */
|
/* Only regular files can have metacopy xattr */
|
||||||
if (!S_ISREG(d_inode(dentry)->i_mode))
|
if (!S_ISREG(d_inode(dentry)->i_mode))
|
||||||
return 0;
|
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 < 0) {
|
||||||
if (res == -ENODATA || res == -EOPNOTSUPP)
|
if (res == -ENODATA || res == -EOPNOTSUPP)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -867,7 +873,7 @@ int ovl_check_metacopy_xattr(struct dentry *dentry)
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
out:
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -893,7 +899,7 @@ ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value,
|
|||||||
ssize_t res;
|
ssize_t res;
|
||||||
char *buf = NULL;
|
char *buf = NULL;
|
||||||
|
|
||||||
res = vfs_getxattr(dentry, name, NULL, 0);
|
res = ovl_vfs_getxattr(dentry, name, NULL, 0);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
if (res == -ENODATA || res == -EOPNOTSUPP)
|
if (res == -ENODATA || res == -EOPNOTSUPP)
|
||||||
return -ENODATA;
|
return -ENODATA;
|
||||||
@@ -905,7 +911,7 @@ ssize_t ovl_getxattr(struct dentry *dentry, char *name, char **value,
|
|||||||
if (!buf)
|
if (!buf)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
res = vfs_getxattr(dentry, name, buf, res);
|
res = ovl_vfs_getxattr(dentry, name, buf, res);
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user