mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
overlayfs fixes for 7.4-rc2
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE9zuTYTs0RXF+Ke33EVvVyTe/1WoFAmrsdYYACgkQEVvVyTe/ 1Wpjzg/+Lr21Tf5jrjrRE9Pgim8LMSqKwR0GV9WnYmHGMrQ6bk5vG0O5QnwFMZnf M4lxDvzyoYmaW2U7EILRz9YKAjoUT/5XRf40NN9OMFy/1mvKJCCk5zm7uxOGixf5 nQW86p/ihzsIMxPGmKEAhFONAme92dLbyK355eCcOCFVryaFryrEkemicncMZMPt TO/+/Xm/f8ydxSzx0MjBHcM93Po/GwRYdvsRtG7H/Ov+4PoqtS0PTnMr1/lip6lA M+kX2ocG+GRjokQ1Jm8fIO437ZCZLDjNgi5lpUa+tmuQDsIfCTYdCk7a1hjgDlsb vENrQH0vf72ZM6IzayKnmJO3MKLvGRVj16WdS+3JTrnPu9BicjpRSfk/Koy1b7eS T/ahZPxoGBKPTKBdeLLddDGsSNfVtrRIys35oNjPC9Po83Su3FHrO7qp8iYf9caN 2G5YFzvowC7pOsRMVpwuQzJYC56H+ID2mcyORUmJaQqIW+g/zXCaMcjZeGDDHb4i ipvXtcbRD73DOAS1cb4SOYMMK3XtAWSpB/dOttV9mw4rpDhuS3HwCDGVqbyozfGT ePOE7UQJZZ15AH3FtdUeuXT0DI/fkB4Z4U0kyfoQIPGdDuakbLWNl6GpQm8b0B8K JgIHY35lx/j4rM/NrB325jb1zknDjl381wHzHT2/b9eaFzorvIE= =XTA5 -----END PGP SIGNATURE----- Merge tag 'ovl-fixes-7.4-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs Pull overlayfs fixes from Amir Goldstein: - Fix a self deadlock of a fanotify permission event listener that also watches the layers, when it reads an overlay directory - Three casefold fixes, found by Chris Mason's AI review - Fix a decode of a modified file handle with nfs_export=on, which could read the stale lower data of a copied up file, also found by Chris Mason's AI review - Fix an overlay selftest after an errno change * tag 'ovl-fixes-7.4-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/overlayfs/vfs: selftests/fscontext_ns: expect EINVAL for overlay descendant userns create ovl: look up the index by the decoded origin ovl: inherit FMODE_NONOTIFY when reading directory layers ovl: inherit FMODE_NONOTIFY when opening directory realfiles ovl: fix whiteout creation in casefolded directories ovl: do not let chattr change the casefold flag ovl: fail the mount if the casefold flag has changed
This commit is contained in:
commit
ce8f728086
|
|
@ -731,7 +731,8 @@ When decoding an overlay file handle, the following steps are followed:
|
|||
|
||||
1. Find underlying layer by UUID and path type information.
|
||||
2. Decode the underlying filesystem file handle to underlying dentry.
|
||||
3. For a lower file handle, lookup the handle in index directory by name.
|
||||
3. For a lower file handle, encode the decoded underlying inode again and
|
||||
lookup that handle in index directory by name.
|
||||
4. If a whiteout is found in index, return ESTALE. This represents an
|
||||
overlay object that was deleted after its file handle was encoded.
|
||||
5. For a non-directory, instantiate a disconnected overlay dentry from the
|
||||
|
|
|
|||
|
|
@ -1172,6 +1172,7 @@ struct file *dentry_open_nonotify(const struct path *path, int flags,
|
|||
}
|
||||
return f;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dentry_open_nonotify);
|
||||
|
||||
/**
|
||||
* kernel_file_open - open a file for kernel internal use
|
||||
|
|
|
|||
|
|
@ -74,39 +74,34 @@ static struct dentry *ovl_start_creating_temp(struct ovl_fs *ofs,
|
|||
&QSTR(name));
|
||||
}
|
||||
|
||||
/*
|
||||
* The whiteout is the source of a rename, so it has to be hashed.
|
||||
* ovl_create_temp() takes care of that for a casefolded workdir.
|
||||
*/
|
||||
static struct dentry *ovl_whiteout(struct ovl_fs *ofs)
|
||||
{
|
||||
int err;
|
||||
struct dentry *whiteout, *link;
|
||||
struct dentry *workdir = ofs->workdir;
|
||||
struct inode *wdir = workdir->d_inode;
|
||||
char name[OVL_TEMPNAME_SIZE];
|
||||
|
||||
guard(mutex)(&ofs->whiteout_lock);
|
||||
|
||||
if (!ofs->whiteout) {
|
||||
whiteout = ovl_start_creating_temp(ofs, workdir, name);
|
||||
whiteout = ovl_create_temp(ofs, workdir, &(struct ovl_cattr) {
|
||||
.mode = S_IFCHR | WHITEOUT_MODE,
|
||||
.rdev = WHITEOUT_DEV });
|
||||
if (IS_ERR(whiteout))
|
||||
return whiteout;
|
||||
err = ovl_do_whiteout(ofs, wdir, whiteout);
|
||||
if (!err)
|
||||
ofs->whiteout = dget(whiteout);
|
||||
end_creating(whiteout);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
ofs->whiteout = whiteout;
|
||||
}
|
||||
|
||||
if (!ofs->no_shared_whiteout) {
|
||||
link = ovl_start_creating_temp(ofs, workdir, name);
|
||||
if (IS_ERR(link))
|
||||
link = ovl_create_temp(ofs, workdir, &(struct ovl_cattr) {
|
||||
.hardlink = ofs->whiteout });
|
||||
if (!IS_ERR(link))
|
||||
return link;
|
||||
err = ovl_do_link(ofs, ofs->whiteout, wdir, link);
|
||||
if (!err)
|
||||
whiteout = dget(link);
|
||||
end_creating(link);
|
||||
if (!err)
|
||||
return whiteout;
|
||||
|
||||
err = PTR_ERR(link);
|
||||
if (err != -EMLINK) {
|
||||
pr_warn("Failed to link whiteout - disabling whiteout inode sharing(nlink=%u, err=%u)\n",
|
||||
ofs->whiteout->d_inode->i_nlink,
|
||||
|
|
@ -120,9 +115,10 @@ static struct dentry *ovl_whiteout(struct ovl_fs *ofs)
|
|||
}
|
||||
|
||||
int ovl_cleanup_and_whiteout(struct ovl_fs *ofs, struct dentry *dir,
|
||||
struct dentry *dentry)
|
||||
struct dentry *dentry, const struct qstr *name)
|
||||
{
|
||||
struct dentry *whiteout;
|
||||
struct qstr last = QSTR_LEN(name->name, name->len);
|
||||
struct renamedata rd = {};
|
||||
int err;
|
||||
int flags = 0;
|
||||
|
|
@ -139,9 +135,17 @@ int ovl_cleanup_and_whiteout(struct ovl_fs *ofs, struct dentry *dir,
|
|||
rd.old_parent = ofs->workdir;
|
||||
rd.new_parent = dir;
|
||||
rd.flags = flags;
|
||||
err = start_renaming_two_dentries(&rd, whiteout, dentry);
|
||||
/*
|
||||
* The caller looked up @dentry by @name without a lock on @dir, and a
|
||||
* casefolded directory leaves a negative dentry unhashed. Nothing tells
|
||||
* if such a dentry is still valid, so look up @name again with @dir locked.
|
||||
*/
|
||||
err = start_renaming_dentry(&rd, 0, whiteout, &last);
|
||||
if (!err) {
|
||||
err = ovl_do_rename_rd(&rd);
|
||||
if (d_inode(rd.new_dentry) != d_inode(dentry))
|
||||
err = -ESTALE;
|
||||
else
|
||||
err = ovl_do_rename_rd(&rd);
|
||||
end_renaming(&rd);
|
||||
}
|
||||
if (err)
|
||||
|
|
@ -847,7 +851,7 @@ static int ovl_remove_and_whiteout(struct dentry *dentry,
|
|||
goto out_dput_upper;
|
||||
}
|
||||
|
||||
err = ovl_cleanup_and_whiteout(ofs, upperdir, upper);
|
||||
err = ovl_cleanup_and_whiteout(ofs, upperdir, upper, &dentry->d_name);
|
||||
if (!err)
|
||||
ovl_dir_modified(dentry->d_parent, true);
|
||||
|
||||
|
|
|
|||
|
|
@ -713,9 +713,9 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb,
|
|||
}
|
||||
}
|
||||
|
||||
/* Then lookup indexed upper/whiteout by origin fh */
|
||||
/* Then lookup indexed upper/whiteout by origin */
|
||||
if (ovl_indexdir(sb)) {
|
||||
index = ovl_get_index_fh(ofs, fh);
|
||||
index = ovl_get_index_origin(ofs, origin.dentry);
|
||||
err = PTR_ERR(index);
|
||||
if (IS_ERR(index)) {
|
||||
index = NULL;
|
||||
|
|
|
|||
|
|
@ -658,6 +658,14 @@ int ovl_fileattr_set(const struct mnt_idmap *idmap,
|
|||
unsigned int flags;
|
||||
int err;
|
||||
|
||||
/*
|
||||
* Lookup refuses a directory that does not agree with the casefold
|
||||
* state of the mount. Only FS_IOC_SETFLAGS can ask for a change.
|
||||
*/
|
||||
if (S_ISDIR(inode->i_mode) && fa->flags_valid &&
|
||||
!!(fa->flags & FS_CASEFOLD_FL) != OVL_FS(inode->i_sb)->casefold)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
err = ovl_copy_up(dentry);
|
||||
if (!err) {
|
||||
ovl_path_real(dentry, &upperpath);
|
||||
|
|
|
|||
|
|
@ -781,14 +781,21 @@ int ovl_get_index_name(struct ovl_fs *ofs, struct dentry *origin,
|
|||
return err;
|
||||
}
|
||||
|
||||
/* Lookup index by file handle for NFS export */
|
||||
struct dentry *ovl_get_index_fh(struct ovl_fs *ofs, struct ovl_fh *fh)
|
||||
/*
|
||||
* Lookup index by decoded origin for NFS export.
|
||||
*
|
||||
* The name of an index is the hex of the file handle that copy up encoded.
|
||||
* The bytes of the handle to decode cannot be used as the name, because a
|
||||
* lower fs may decode many handles to the same inode. For example, it may
|
||||
* ignore the fid type, extra fid bytes or a zero generation.
|
||||
*/
|
||||
struct dentry *ovl_get_index_origin(struct ovl_fs *ofs, struct dentry *origin)
|
||||
{
|
||||
struct dentry *index;
|
||||
struct qstr name;
|
||||
int err;
|
||||
|
||||
err = ovl_get_index_name_fh(fh, &name);
|
||||
err = ovl_get_index_name(ofs, origin, &name);
|
||||
if (err)
|
||||
return ERR_PTR(err);
|
||||
|
||||
|
|
|
|||
|
|
@ -396,14 +396,6 @@ static inline int ovl_do_rename(struct ovl_fs *ofs, struct dentry *olddir,
|
|||
return ovl_do_rename_rd(&rd);
|
||||
}
|
||||
|
||||
static inline int ovl_do_whiteout(struct ovl_fs *ofs,
|
||||
struct inode *dir, struct dentry *dentry)
|
||||
{
|
||||
int err = vfs_whiteout(ovl_upper_mnt_idmap(ofs), dir, dentry);
|
||||
pr_debug("whiteout(%pd2) = %i\n", dentry, err);
|
||||
return err;
|
||||
}
|
||||
|
||||
static inline struct file *ovl_do_tmpfile(struct ovl_fs *ofs,
|
||||
struct dentry *dentry, umode_t mode)
|
||||
{
|
||||
|
|
@ -539,7 +531,14 @@ void ovl_dir_modified(struct dentry *dentry, bool impurity);
|
|||
u64 ovl_inode_version_get(struct inode *inode);
|
||||
bool ovl_is_whiteout(struct dentry *dentry);
|
||||
bool ovl_path_is_whiteout(struct ovl_fs *ofs, const struct path *path);
|
||||
struct file *ovl_path_open(const struct path *path, int flags);
|
||||
struct file *ovl_path_open_realfile(const struct file *user_file,
|
||||
const struct path *path, int flags);
|
||||
|
||||
static inline struct file *ovl_path_open(const struct path *path, int flags)
|
||||
{
|
||||
return ovl_path_open_realfile(NULL, path, flags);
|
||||
}
|
||||
|
||||
int ovl_copy_up_start(struct dentry *dentry, int flags);
|
||||
void ovl_copy_up_end(struct dentry *dentry);
|
||||
bool ovl_already_copied_up(struct dentry *dentry, int flags);
|
||||
|
|
@ -751,7 +750,7 @@ int ovl_verify_index(struct ovl_fs *ofs, struct dentry *index);
|
|||
int ovl_get_index_name_fh(const struct ovl_fh *fh, struct qstr *name);
|
||||
int ovl_get_index_name(struct ovl_fs *ofs, struct dentry *origin,
|
||||
struct qstr *name);
|
||||
struct dentry *ovl_get_index_fh(struct ovl_fs *ofs, struct ovl_fh *fh);
|
||||
struct dentry *ovl_get_index_origin(struct ovl_fs *ofs, struct dentry *origin);
|
||||
struct dentry *ovl_lookup_index(struct ovl_fs *ofs, struct dentry *upper,
|
||||
struct dentry *origin, bool verify);
|
||||
int ovl_path_next(int idx, struct dentry *dentry, struct path *path,
|
||||
|
|
@ -899,7 +898,7 @@ static inline void ovl_copyflags(struct inode *from, struct inode *to)
|
|||
/* dir.c */
|
||||
extern const struct inode_operations ovl_dir_inode_operations;
|
||||
int ovl_cleanup_and_whiteout(struct ovl_fs *ofs, struct dentry *dir,
|
||||
struct dentry *dentry);
|
||||
struct dentry *dentry, const struct qstr *name);
|
||||
struct ovl_cattr {
|
||||
dev_t rdev;
|
||||
umode_t mode;
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ struct ovl_dir_cache {
|
|||
|
||||
struct ovl_readdir_data {
|
||||
struct dir_context ctx;
|
||||
const struct file *user_file;
|
||||
struct dentry *dentry;
|
||||
bool is_lowest;
|
||||
struct rb_root *root;
|
||||
|
|
@ -377,7 +378,8 @@ static inline int ovl_dir_read(const struct path *realpath,
|
|||
struct file *realfile;
|
||||
int err;
|
||||
|
||||
realfile = ovl_path_open(realpath, O_RDONLY | O_LARGEFILE);
|
||||
realfile = ovl_path_open_realfile(rdd->user_file, realpath,
|
||||
O_RDONLY | O_LARGEFILE);
|
||||
if (IS_ERR(realfile))
|
||||
return PTR_ERR(realfile);
|
||||
|
||||
|
|
@ -421,13 +423,14 @@ static void ovl_dir_reset(struct file *file)
|
|||
}
|
||||
|
||||
static int ovl_dir_read_merged(struct dentry *dentry, struct list_head *list,
|
||||
struct rb_root *root)
|
||||
struct rb_root *root, const struct file *user_file)
|
||||
{
|
||||
int err;
|
||||
struct path realpath;
|
||||
struct ovl_readdir_data rdd = {
|
||||
.ctx.actor = ovl_fill_merge,
|
||||
.ctx.count = INT_MAX,
|
||||
.user_file = user_file,
|
||||
.dentry = dentry,
|
||||
.list = list,
|
||||
.root = root,
|
||||
|
|
@ -498,9 +501,10 @@ static struct ovl_dir_cache *ovl_dir_cache_check(struct inode *inode,
|
|||
return cache;
|
||||
}
|
||||
|
||||
static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry)
|
||||
static struct ovl_dir_cache *ovl_dir_cache_get(struct file *file)
|
||||
{
|
||||
int res;
|
||||
struct dentry *dentry = file->f_path.dentry;
|
||||
struct ovl_dir_cache *cache;
|
||||
struct inode *inode = d_inode(dentry);
|
||||
|
||||
|
|
@ -521,7 +525,7 @@ static struct ovl_dir_cache *ovl_cache_get(struct dentry *dentry)
|
|||
INIT_LIST_HEAD(&cache->entries);
|
||||
cache->root = RB_ROOT;
|
||||
|
||||
res = ovl_dir_read_merged(dentry, &cache->entries, &cache->root);
|
||||
res = ovl_dir_read_merged(dentry, &cache->entries, &cache->root, file);
|
||||
if (res) {
|
||||
ovl_cache_free(&cache->entries);
|
||||
kfree(cache);
|
||||
|
|
@ -665,8 +669,8 @@ static bool ovl_fill_plain(struct dir_context *ctx, const char *name,
|
|||
return true;
|
||||
}
|
||||
|
||||
static int ovl_dir_read_impure(const struct path *path, struct list_head *list,
|
||||
struct rb_root *root)
|
||||
static int ovl_dir_read_impure(const struct path *path, struct list_head *list,
|
||||
struct rb_root *root, const struct file *user_file)
|
||||
{
|
||||
int err;
|
||||
struct path realpath;
|
||||
|
|
@ -674,6 +678,7 @@ static int ovl_dir_read_impure(const struct path *path, struct list_head *list,
|
|||
struct ovl_readdir_data rdd = {
|
||||
.ctx.actor = ovl_fill_plain,
|
||||
.ctx.count = INT_MAX,
|
||||
.user_file = user_file,
|
||||
.list = list,
|
||||
.root = root,
|
||||
};
|
||||
|
|
@ -710,9 +715,10 @@ static int ovl_dir_read_impure(const struct path *path, struct list_head *list,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static struct ovl_dir_cache *ovl_cache_get_impure(const struct path *path)
|
||||
static struct ovl_dir_cache *ovl_cache_get_impure(struct file *file)
|
||||
{
|
||||
int res;
|
||||
const struct path *path = &file->f_path;
|
||||
struct dentry *dentry = path->dentry;
|
||||
struct inode *inode = d_inode(dentry);
|
||||
struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
|
||||
|
|
@ -731,7 +737,7 @@ static struct ovl_dir_cache *ovl_cache_get_impure(const struct path *path)
|
|||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
cache->is_refcounted = false;
|
||||
res = ovl_dir_read_impure(path, &cache->entries, &cache->root);
|
||||
res = ovl_dir_read_impure(path, &cache->entries, &cache->root, file);
|
||||
if (res) {
|
||||
ovl_cache_free(&cache->entries);
|
||||
kfree(cache);
|
||||
|
|
@ -852,7 +858,7 @@ static int ovl_iterate_real(struct file *file, struct dir_context *ctx)
|
|||
dput(parent);
|
||||
|
||||
if (ovl_is_impure_dir(file)) {
|
||||
rdt.cache = ovl_cache_get_impure(&file->f_path);
|
||||
rdt.cache = ovl_cache_get_impure(file);
|
||||
if (IS_ERR(rdt.cache))
|
||||
return PTR_ERR(rdt.cache);
|
||||
}
|
||||
|
|
@ -866,14 +872,13 @@ static int ovl_iterate_real(struct file *file, struct dir_context *ctx)
|
|||
static int ovl_iterate_merged(struct file *file, struct dir_context *ctx)
|
||||
{
|
||||
struct ovl_dir_file *od = file->private_data;
|
||||
struct dentry *dentry = file->f_path.dentry;
|
||||
struct ovl_cache_entry *p;
|
||||
int err;
|
||||
|
||||
if (!od->cache) {
|
||||
struct ovl_dir_cache *cache;
|
||||
|
||||
cache = ovl_cache_get(dentry);
|
||||
cache = ovl_dir_cache_get(file);
|
||||
if (IS_ERR(cache))
|
||||
return PTR_ERR(cache);
|
||||
|
||||
|
|
@ -994,7 +999,8 @@ static struct file *ovl_dir_open_realfile(const struct file *file,
|
|||
const struct path *realpath)
|
||||
{
|
||||
with_ovl_creds(file_inode(file)->i_sb)
|
||||
return ovl_path_open(realpath, O_RDONLY | (file->f_flags & O_LARGEFILE));
|
||||
return ovl_path_open_realfile(file, realpath,
|
||||
O_RDONLY | (file->f_flags & O_LARGEFILE));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1119,7 +1125,7 @@ int ovl_check_empty_dir(struct dentry *dentry, struct list_head *list)
|
|||
struct rb_root root = RB_ROOT;
|
||||
|
||||
with_ovl_creds(dentry->d_sb)
|
||||
err = ovl_dir_read_merged(dentry, list, &root);
|
||||
err = ovl_dir_read_merged(dentry, list, &root, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
|
@ -1343,7 +1349,8 @@ int ovl_indexdir_cleanup(struct ovl_fs *ofs)
|
|||
* Whiteout orphan index to block future open by
|
||||
* handle after overlay nlink dropped to zero.
|
||||
*/
|
||||
err = ovl_cleanup_and_whiteout(ofs, indexdir, index);
|
||||
err = ovl_cleanup_and_whiteout(ofs, indexdir, index,
|
||||
&QSTR_LEN(p->name, p->len));
|
||||
} else {
|
||||
/* Cleanup orphan index entries */
|
||||
err = ovl_cleanup(ofs, indexdir, index);
|
||||
|
|
|
|||
|
|
@ -1387,7 +1387,6 @@ static struct dentry *ovl_get_root(struct super_block *sb,
|
|||
ovl_dentry_set_flag(OVL_E_CONNECTED, root);
|
||||
ovl_set_upperdata(d_inode(root));
|
||||
ovl_inode_init(d_inode(root), &oip, ino, fsid);
|
||||
WARN_ON(!!IS_CASEFOLDED(d_inode(root)) != ofs->casefold);
|
||||
ovl_dentry_init_flags(root, upperdentry, oe, DCACHE_OP_WEAK_REVALIDATE);
|
||||
/* root keeps a reference of upperdentry */
|
||||
dget(upperdentry);
|
||||
|
|
@ -1571,6 +1570,17 @@ static int ovl_fill_super_creds(struct fs_context *fc, struct super_block *sb)
|
|||
if (!sb->s_root)
|
||||
goto out_free_oe;
|
||||
|
||||
/*
|
||||
* The casefold flag of an empty layer root may have changed since the
|
||||
* mount options were parsed. The root inode owns oe by now.
|
||||
*/
|
||||
if (!!IS_CASEFOLDED(d_inode(sb->s_root)) != ofs->casefold) {
|
||||
pr_err("casefold flag of the root directory has changed\n");
|
||||
dput(sb->s_root);
|
||||
sb->s_root = NULL;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_oe:
|
||||
|
|
|
|||
|
|
@ -654,7 +654,8 @@ bool ovl_path_is_whiteout(struct ovl_fs *ofs, const struct path *path)
|
|||
ovl_path_check_xwhiteout_xattr(ofs, path);
|
||||
}
|
||||
|
||||
struct file *ovl_path_open(const struct path *path, int flags)
|
||||
struct file *ovl_path_open_realfile(const struct file *user_file,
|
||||
const struct path *path, int flags)
|
||||
{
|
||||
struct inode *inode = d_inode(path->dentry);
|
||||
const struct mnt_idmap *real_idmap = mnt_idmap(path->mnt);
|
||||
|
|
@ -682,6 +683,14 @@ struct file *ovl_path_open(const struct path *path, int flags)
|
|||
if (inode_owner_or_capable(real_idmap, inode))
|
||||
flags |= O_NOATIME;
|
||||
|
||||
/*
|
||||
* Directory opens use dentry_open() here, not backing_file_open().
|
||||
* Inherit FMODE_NONOTIFY from a fanotify permission fd so a listener
|
||||
* that also watches the real filesystem does not deadlock.
|
||||
*/
|
||||
if (user_file && FMODE_FSNOTIFY_NONE(user_file->f_mode))
|
||||
return dentry_open_nonotify(path, flags, current_cred());
|
||||
|
||||
return dentry_open(path, flags, current_cred());
|
||||
}
|
||||
|
||||
|
|
@ -1118,7 +1127,7 @@ static void ovl_cleanup_index(struct dentry *dentry)
|
|||
} else if (ovl_index_all(dentry->d_sb)) {
|
||||
/* Whiteout orphan index to block future open by handle */
|
||||
err = ovl_cleanup_and_whiteout(OVL_FS(dentry->d_sb),
|
||||
indexdir, index);
|
||||
indexdir, index, &name);
|
||||
} else {
|
||||
/* Cleanup orphan index entries */
|
||||
err = ovl_cleanup(ofs, indexdir, index);
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ FIXTURE_VARIANT_ADD(fscontext_ns, binfmt_misc) {
|
|||
|
||||
FIXTURE_VARIANT_ADD(fscontext_ns, overlay) {
|
||||
.fsname = "overlay",
|
||||
.expected_errno = EIO,
|
||||
.expected_errno = EINVAL,
|
||||
};
|
||||
|
||||
TEST_F(fscontext_ns, create_from_descendant_userns)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user