mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
ovl: pass correct flags for opening real directory
The three instances of ovl_path_open() in overlayfs/readdir.c do three different things: - pass f_flags from overlay file - pass O_RDONLY | O_DIRECTORY - pass just O_RDONLY The value of f_flags can be (other than O_RDONLY): O_WRONLY - not possible for a directory O_RDWR - not possible for a directory O_CREAT - masked out by dentry_open() O_EXCL - masked out by dentry_open() O_NOCTTY - masked out by dentry_open() O_TRUNC - masked out by dentry_open() O_APPEND - no effect on directory ops O_NDELAY - no effect on directory ops O_NONBLOCK - no effect on directory ops __O_SYNC - no effect on directory ops O_DSYNC - no effect on directory ops FASYNC - no effect on directory ops O_DIRECT - no effect on directory ops O_LARGEFILE - ? O_DIRECTORY - only affects lookup O_NOFOLLOW - only affects lookup O_NOATIME - overlay sets this unconditionally in ovl_path_open() O_CLOEXEC - only affects fd allocation O_PATH - no effect on directory ops __O_TMPFILE - not possible for a directory Fon non-merge directories we use the underlying filesystem's iterate; in this case honor O_LARGEFILE from the original file to make sure that open doesn't get rejected. For merge directories it's safe to pass O_LARGEFILE unconditionally since userspace will only see the artificial offsets created by overlayfs. Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
21d8d66abf
commit
130fdbc3d1
|
|
@ -297,7 +297,7 @@ static inline int ovl_dir_read(struct path *realpath,
|
||||||
struct file *realfile;
|
struct file *realfile;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
realfile = ovl_path_open(realpath, O_RDONLY | O_DIRECTORY);
|
realfile = ovl_path_open(realpath, O_RDONLY | O_LARGEFILE);
|
||||||
if (IS_ERR(realfile))
|
if (IS_ERR(realfile))
|
||||||
return PTR_ERR(realfile);
|
return PTR_ERR(realfile);
|
||||||
|
|
||||||
|
|
@ -831,6 +831,12 @@ static loff_t ovl_dir_llseek(struct file *file, loff_t offset, int origin)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct file *ovl_dir_open_realfile(struct file *file,
|
||||||
|
struct path *realpath)
|
||||||
|
{
|
||||||
|
return ovl_path_open(realpath, O_RDONLY | (file->f_flags & O_LARGEFILE));
|
||||||
|
}
|
||||||
|
|
||||||
static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end,
|
static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end,
|
||||||
int datasync)
|
int datasync)
|
||||||
{
|
{
|
||||||
|
|
@ -853,7 +859,7 @@ static int ovl_dir_fsync(struct file *file, loff_t start, loff_t end,
|
||||||
struct path upperpath;
|
struct path upperpath;
|
||||||
|
|
||||||
ovl_path_upper(dentry, &upperpath);
|
ovl_path_upper(dentry, &upperpath);
|
||||||
realfile = ovl_path_open(&upperpath, O_RDONLY);
|
realfile = ovl_dir_open_realfile(file, &upperpath);
|
||||||
|
|
||||||
inode_lock(inode);
|
inode_lock(inode);
|
||||||
if (!od->upperfile) {
|
if (!od->upperfile) {
|
||||||
|
|
@ -904,7 +910,7 @@ static int ovl_dir_open(struct inode *inode, struct file *file)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
type = ovl_path_real(file->f_path.dentry, &realpath);
|
type = ovl_path_real(file->f_path.dentry, &realpath);
|
||||||
realfile = ovl_path_open(&realpath, file->f_flags);
|
realfile = ovl_dir_open_realfile(file, &realpath);
|
||||||
if (IS_ERR(realfile)) {
|
if (IS_ERR(realfile)) {
|
||||||
kfree(od);
|
kfree(od);
|
||||||
return PTR_ERR(realfile);
|
return PTR_ERR(realfile);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user