ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) { ssize_t res; int off; res = vfs_listxattr(ovl_dentry_real(dentry), list, size); if (res <= 0 || size == 0) return res; if (ovl_path_type(dentry->d_parent) != OVL_PATH_MERGE) return res; /* filter out private xattrs */ for (off = 0; off < res;) { char *s = list + off; size_t slen = strlen(s) + 1; BUG_ON(off + slen > res); if (ovl_is_private_xattr(s)) { res -= slen; memmove(s, s + slen, res - off); } else { off += slen; } } return res; }
int ovl_removexattr(struct dentry *dentry, const char *name) { int err; struct path realpath; enum ovl_path_type type; err = ovl_want_write(dentry); if (err) goto out; if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE && ovl_is_private_xattr(name)) goto out_drop_write; type = ovl_path_real(dentry, &realpath); if (type == OVL_PATH_LOWER) { err = vfs_getxattr(realpath.dentry, name, NULL, 0); if (err < 0) goto out_drop_write; err = ovl_copy_up(dentry); if (err) goto out_drop_write; ovl_path_upper(dentry, &realpath); } err = vfs_removexattr(realpath.dentry, name); out_drop_write: ovl_drop_write(dentry); out: return err; }
int ovl_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { int err; struct dentry *upperdentry; err = ovl_want_write(dentry); if (err) goto out; err = -EPERM; if (ovl_is_private_xattr(name)) goto out_drop_write; err = ovl_copy_up(dentry); if (err) goto out_drop_write; upperdentry = ovl_dentry_upper(dentry); err = vfs_setxattr(upperdentry, name, value, size, flags); out_drop_write: ovl_drop_write(dentry); out: return err; }
ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) { struct path realpath; enum ovl_path_type type = ovl_path_real(dentry, &realpath); ssize_t res; size_t len; char *s; res = vfs_listxattr(realpath.dentry, list, size); if (res <= 0 || size == 0) return res; if (!ovl_need_xattr_filter(dentry, type)) return res; /* filter out private xattrs */ for (s = list, len = res; len;) { size_t slen = strnlen(s, len) + 1; /* underlying fs providing us with an broken xattr list? */ if (WARN_ON(slen > len)) return -EIO; len -= slen; if (ovl_is_private_xattr(s)) { res -= slen; memmove(s, s + slen, len); } else { s += slen; } } return res; }
int ovl_removexattr(struct dentry *dentry, const char *name) { int err; struct path realpath; enum ovl_path_type type; if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE && ovl_is_private_xattr(name)) return -ENODATA; type = ovl_path_real(dentry, &realpath); if (type == OVL_PATH_LOWER) { err = vfs_getxattr(realpath.dentry, name, NULL, 0); if (err < 0) return err; err = ovl_copy_up(dentry); if (err) return err; ovl_path_upper(dentry, &realpath); } return vfs_removexattr(realpath.dentry, name); }
int ovl_removexattr(struct dentry *dentry, const char *name) { int err; struct path realpath; enum ovl_path_type type = ovl_path_real(dentry, &realpath); err = ovl_want_write(dentry); if (err) goto out; err = -ENODATA; if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) goto out_drop_write; if (!OVL_TYPE_UPPER(type)) { err = vfs_getxattr(realpath.dentry, name, NULL, 0); if (err < 0) goto out_drop_write; err = ovl_copy_up(dentry); if (err) goto out_drop_write; ovl_path_upper(dentry, &realpath); } err = vfs_removexattr(realpath.dentry, name); out_drop_write: ovl_drop_write(dentry); out: return err; }
ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) { struct path realpath; enum ovl_path_type type = ovl_path_real(dentry, &realpath); ssize_t res; int off; res = vfs_listxattr(realpath.dentry, list, size); if (res <= 0 || size == 0) return res; if (!ovl_need_xattr_filter(dentry, type)) return res; /* filter out private xattrs */ for (off = 0; off < res;) { char *s = list + off; size_t slen = strlen(s) + 1; BUG_ON(off + slen > res); if (ovl_is_private_xattr(s)) { res -= slen; memmove(s, s + slen, res - off); } else { off += slen; } } return res; }
ssize_t ovl_listxattr(struct dentry *dentry, char *list, size_t size) { struct dentry *realdentry = ovl_dentry_real(dentry); ssize_t res; size_t len; char *s; const struct cred *old_cred; old_cred = ovl_override_creds(dentry->d_sb); res = vfs_listxattr(realdentry, list, size); revert_creds(old_cred); if (res <= 0 || size == 0) return res; /* filter out private xattrs */ for (s = list, len = res; len;) { size_t slen = strnlen(s, len) + 1; /* underlying fs providing us with an broken xattr list? */ if (WARN_ON(slen > len)) return -EIO; len -= slen; if (ovl_is_private_xattr(s)) { res -= slen; memmove(s, s + slen, len); } else { s += slen; } } return res; }
ssize_t ovl_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) { if (ovl_path_type(dentry->d_parent) == OVL_PATH_MERGE && ovl_is_private_xattr(name)) return -ENODATA; return vfs_getxattr(ovl_dentry_real(dentry), name, value, size); }
static bool ovl_can_list(const char *s) { /* List all non-trusted xatts */ if (strncmp(s, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) != 0) return true; /* Never list trusted.overlay, list other trusted for superuser only */ return !ovl_is_private_xattr(s) && capable(CAP_SYS_ADMIN); }
ssize_t ovl_getxattr(struct dentry *dentry, struct inode *inode, const char *name, void *value, size_t size) { struct dentry *realdentry = ovl_dentry_real(dentry); if (ovl_is_private_xattr(name)) return -ENODATA; return vfs_getxattr(realdentry, name, value, size); }
ssize_t ovl_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) { struct path realpath; enum ovl_path_type type = ovl_path_real(dentry, &realpath); if (ovl_need_xattr_filter(dentry, type) && ovl_is_private_xattr(name)) return -ENODATA; return vfs_getxattr(realpath.dentry, name, value, size); }
int ovl_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { int err; struct dentry *upperdentry; if (ovl_is_private_xattr(name)) return -EPERM; err = ovl_copy_up(dentry); if (err) return err; upperdentry = ovl_dentry_upper(dentry); return vfs_setxattr(upperdentry, name, value, size, flags); }