allow build_open_flags() to return an error
Change-Id: Ief5582ec8c4aeb4fb7bf9b2abd51b3d65ae9e81c Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
ed2aadd1fb
commit
e1f4fb3251
10
fs/exec.c
10
fs/exec.c
|
@ -111,13 +111,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))
|
||||||
|
@ -778,10 +779,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;
|
||||||
|
|
||||||
|
|
|
@ -95,11 +95,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);
|
||||||
|
|
|
@ -3090,9 +3090,10 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
@ -3104,17 +3105,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);
|
||||||
|
|
||||||
|
|
47
fs/open.c
47
fs/open.c
|
@ -881,7 +881,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -898,8 +899,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -924,37 +925,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 (!IS_ERR(tmp)) {
|
if (fd)
|
||||||
fd = get_unused_fd_flags(flags);
|
return fd;
|
||||||
if (fd >= 0) {
|
|
||||||
struct file *f = do_filp_open(dfd, tmp, &op, lookup);
|
tmp = getname(filename);
|
||||||
if (IS_ERR(f)) {
|
if (IS_ERR(tmp))
|
||||||
put_unused_fd(fd);
|
return PTR_ERR(tmp);
|
||||||
fd = PTR_ERR(f);
|
|
||||||
} else {
|
fd = get_unused_fd_flags(flags);
|
||||||
fsnotify_open(f);
|
if (fd >= 0) {
|
||||||
fd_install(fd, f);
|
struct file *f = do_filp_open(dfd, tmp, &op);
|
||||||
}
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue