Commit f9652e10 authored by Al Viro's avatar Al Viro

allow build_open_flags() to return an error

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 50cd2c57
...@@ -110,13 +110,14 @@ SYSCALL_DEFINE1(uselib, const char __user *, library) ...@@ -110,13 +110,14 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
static const struct open_flags uselib_flags = { static const struct open_flags uselib_flags = {
.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
.acc_mode = MAY_READ | MAY_EXEC | MAY_OPEN, .acc_mode = MAY_READ | MAY_EXEC | MAY_OPEN,
.intent = LOOKUP_OPEN .intent = LOOKUP_OPEN,
.lookup_flags = LOOKUP_FOLLOW,
}; };
if (IS_ERR(tmp)) if (IS_ERR(tmp))
goto out; goto out;
file = do_filp_open(AT_FDCWD, tmp, &uselib_flags, LOOKUP_FOLLOW); file = do_filp_open(AT_FDCWD, tmp, &uselib_flags);
putname(tmp); putname(tmp);
error = PTR_ERR(file); error = PTR_ERR(file);
if (IS_ERR(file)) if (IS_ERR(file))
...@@ -756,10 +757,11 @@ struct file *open_exec(const char *name) ...@@ -756,10 +757,11 @@ struct file *open_exec(const char *name)
static const struct open_flags open_exec_flags = { static const struct open_flags open_exec_flags = {
.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
.acc_mode = MAY_EXEC | MAY_OPEN, .acc_mode = MAY_EXEC | MAY_OPEN,
.intent = LOOKUP_OPEN .intent = LOOKUP_OPEN,
.lookup_flags = LOOKUP_FOLLOW,
}; };
file = do_filp_open(AT_FDCWD, &tmp, &open_exec_flags, LOOKUP_FOLLOW); file = do_filp_open(AT_FDCWD, &tmp, &open_exec_flags);
if (IS_ERR(file)) if (IS_ERR(file))
goto out; goto out;
......
...@@ -96,11 +96,12 @@ struct open_flags { ...@@ -96,11 +96,12 @@ struct open_flags {
umode_t mode; umode_t mode;
int acc_mode; int acc_mode;
int intent; int intent;
int lookup_flags;
}; };
extern struct file *do_filp_open(int dfd, struct filename *pathname, extern struct file *do_filp_open(int dfd, struct filename *pathname,
const struct open_flags *op, int flags); const struct open_flags *op);
extern struct file *do_file_open_root(struct dentry *, struct vfsmount *, extern struct file *do_file_open_root(struct dentry *, struct vfsmount *,
const char *, const struct open_flags *, int lookup_flags); const char *, const struct open_flags *);
extern long do_handle_open(int mountdirfd, extern long do_handle_open(int mountdirfd,
struct file_handle __user *ufh, int open_flag); struct file_handle __user *ufh, int open_flag);
......
...@@ -2969,9 +2969,10 @@ static struct file *path_openat(int dfd, struct filename *pathname, ...@@ -2969,9 +2969,10 @@ static struct file *path_openat(int dfd, struct filename *pathname,
} }
struct file *do_filp_open(int dfd, struct filename *pathname, struct file *do_filp_open(int dfd, struct filename *pathname,
const struct open_flags *op, int flags) const struct open_flags *op)
{ {
struct nameidata nd; struct nameidata nd;
int flags = op->lookup_flags;
struct file *filp; struct file *filp;
filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU); filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU);
...@@ -2983,17 +2984,16 @@ struct file *do_filp_open(int dfd, struct filename *pathname, ...@@ -2983,17 +2984,16 @@ struct file *do_filp_open(int dfd, struct filename *pathname,
} }
struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt, struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
const char *name, const struct open_flags *op, int flags) const char *name, const struct open_flags *op)
{ {
struct nameidata nd; struct nameidata nd;
struct file *file; struct file *file;
struct filename filename = { .name = name }; struct filename filename = { .name = name };
int flags = op->lookup_flags | LOOKUP_ROOT;
nd.root.mnt = mnt; nd.root.mnt = mnt;
nd.root.dentry = dentry; nd.root.dentry = dentry;
flags |= LOOKUP_ROOT;
if (dentry->d_inode->i_op->follow_link && op->intent & LOOKUP_OPEN) if (dentry->d_inode->i_op->follow_link && op->intent & LOOKUP_OPEN)
return ERR_PTR(-ELOOP); return ERR_PTR(-ELOOP);
......
...@@ -876,7 +876,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o ...@@ -876,7 +876,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
lookup_flags |= LOOKUP_DIRECTORY; lookup_flags |= LOOKUP_DIRECTORY;
if (!(flags & O_NOFOLLOW)) if (!(flags & O_NOFOLLOW))
lookup_flags |= LOOKUP_FOLLOW; lookup_flags |= LOOKUP_FOLLOW;
return lookup_flags; op->lookup_flags = lookup_flags;
return 0;
} }
/** /**
...@@ -893,8 +894,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o ...@@ -893,8 +894,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
struct file *file_open_name(struct filename *name, int flags, umode_t mode) struct file *file_open_name(struct filename *name, int flags, umode_t mode)
{ {
struct open_flags op; struct open_flags op;
int lookup = build_open_flags(flags, mode, &op); int err = build_open_flags(flags, mode, &op);
return do_filp_open(AT_FDCWD, name, &op, lookup); return err ? ERR_PTR(err) : do_filp_open(AT_FDCWD, name, &op);
} }
/** /**
...@@ -919,37 +920,43 @@ struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt, ...@@ -919,37 +920,43 @@ struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
const char *filename, int flags) const char *filename, int flags)
{ {
struct open_flags op; struct open_flags op;
int lookup = build_open_flags(flags, 0, &op); int err = build_open_flags(flags, 0, &op);
if (err)
return ERR_PTR(err);
if (flags & O_CREAT) if (flags & O_CREAT)
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
if (!filename && (flags & O_DIRECTORY)) if (!filename && (flags & O_DIRECTORY))
if (!dentry->d_inode->i_op->lookup) if (!dentry->d_inode->i_op->lookup)
return ERR_PTR(-ENOTDIR); return ERR_PTR(-ENOTDIR);
return do_file_open_root(dentry, mnt, filename, &op, lookup); return do_file_open_root(dentry, mnt, filename, &op);
} }
EXPORT_SYMBOL(file_open_root); EXPORT_SYMBOL(file_open_root);
long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
{ {
struct open_flags op; struct open_flags op;
int lookup = build_open_flags(flags, mode, &op); int fd = build_open_flags(flags, mode, &op);
struct filename *tmp = getname(filename); struct filename *tmp;
int fd = PTR_ERR(tmp);
if (fd)
if (!IS_ERR(tmp)) { return fd;
fd = get_unused_fd_flags(flags);
if (fd >= 0) { tmp = getname(filename);
struct file *f = do_filp_open(dfd, tmp, &op, lookup); if (IS_ERR(tmp))
if (IS_ERR(f)) { return PTR_ERR(tmp);
put_unused_fd(fd);
fd = PTR_ERR(f); fd = get_unused_fd_flags(flags);
} else { if (fd >= 0) {
fsnotify_open(f); struct file *f = do_filp_open(dfd, tmp, &op);
fd_install(fd, f); if (IS_ERR(f)) {
} put_unused_fd(fd);
fd = PTR_ERR(f);
} else {
fsnotify_open(f);
fd_install(fd, f);
} }
putname(tmp);
} }
putname(tmp);
return fd; return fd;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment