switch do_filp_open() to struct open_flags
take calculation of open_flags by open(2) arguments into new helper in fs/open.c, move filp_open() over there, have it and do_sys_open() use that helper, switch exec.c callers of do_filp_open() to explicit (and constant) struct open_flags. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
Родитель
c3e380b0b3
Коммит
47c805dc2d
18
fs/exec.c
18
fs/exec.c
|
@ -115,13 +115,16 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
|
|||
struct file *file;
|
||||
char *tmp = getname(library);
|
||||
int error = PTR_ERR(tmp);
|
||||
static const struct open_flags uselib_flags = {
|
||||
.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
|
||||
.acc_mode = MAY_READ | MAY_EXEC | MAY_OPEN,
|
||||
.intent = LOOKUP_OPEN
|
||||
};
|
||||
|
||||
if (IS_ERR(tmp))
|
||||
goto out;
|
||||
|
||||
file = do_filp_open(AT_FDCWD, tmp,
|
||||
O_LARGEFILE | O_RDONLY | __FMODE_EXEC, 0,
|
||||
MAY_READ | MAY_EXEC | MAY_OPEN);
|
||||
file = do_filp_open(AT_FDCWD, tmp, &uselib_flags, LOOKUP_FOLLOW);
|
||||
putname(tmp);
|
||||
error = PTR_ERR(file);
|
||||
if (IS_ERR(file))
|
||||
|
@ -721,10 +724,13 @@ struct file *open_exec(const char *name)
|
|||
{
|
||||
struct file *file;
|
||||
int err;
|
||||
static const struct open_flags open_exec_flags = {
|
||||
.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
|
||||
.acc_mode = MAY_EXEC | MAY_OPEN,
|
||||
.intent = LOOKUP_OPEN
|
||||
};
|
||||
|
||||
file = do_filp_open(AT_FDCWD, name,
|
||||
O_LARGEFILE | O_RDONLY | __FMODE_EXEC, 0,
|
||||
MAY_EXEC | MAY_OPEN);
|
||||
file = do_filp_open(AT_FDCWD, name, &open_exec_flags, LOOKUP_FOLLOW);
|
||||
if (IS_ERR(file))
|
||||
goto out;
|
||||
|
||||
|
|
|
@ -106,6 +106,14 @@ extern void put_super(struct super_block *sb);
|
|||
struct nameidata;
|
||||
extern struct file *nameidata_to_filp(struct nameidata *);
|
||||
extern void release_open_intent(struct nameidata *);
|
||||
struct open_flags {
|
||||
int open_flag;
|
||||
int mode;
|
||||
int acc_mode;
|
||||
int intent;
|
||||
};
|
||||
extern struct file *do_filp_open(int dfd, const char *pathname,
|
||||
const struct open_flags *op, int lookup_flags);
|
||||
|
||||
/*
|
||||
* inode.c
|
||||
|
|
88
fs/namei.c
88
fs/namei.c
|
@ -2169,13 +2169,6 @@ exit:
|
|||
return ERR_PTR(error);
|
||||
}
|
||||
|
||||
struct open_flags {
|
||||
int open_flag;
|
||||
int mode;
|
||||
int acc_mode;
|
||||
int intent;
|
||||
};
|
||||
|
||||
/*
|
||||
* Handle O_CREAT case for do_filp_open
|
||||
*/
|
||||
|
@ -2305,74 +2298,28 @@ exit:
|
|||
* open_to_namei_flags() for more details.
|
||||
*/
|
||||
struct file *do_filp_open(int dfd, const char *pathname,
|
||||
int open_flag, int mode, int acc_mode)
|
||||
const struct open_flags *op, int flags)
|
||||
{
|
||||
struct file *filp;
|
||||
struct nameidata nd;
|
||||
int error;
|
||||
struct path path;
|
||||
int count = 0;
|
||||
int flag = open_to_namei_flags(open_flag);
|
||||
int flags = 0;
|
||||
struct open_flags op;
|
||||
|
||||
if (!(open_flag & O_CREAT))
|
||||
mode = 0;
|
||||
|
||||
/* Must never be set by userspace */
|
||||
open_flag &= ~FMODE_NONOTIFY;
|
||||
|
||||
/*
|
||||
* O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only
|
||||
* check for O_DSYNC if the need any syncing at all we enforce it's
|
||||
* always set instead of having to deal with possibly weird behaviour
|
||||
* for malicious applications setting only __O_SYNC.
|
||||
*/
|
||||
if (open_flag & __O_SYNC)
|
||||
open_flag |= O_DSYNC;
|
||||
|
||||
op.open_flag = open_flag;
|
||||
|
||||
if (!acc_mode)
|
||||
acc_mode = MAY_OPEN | ACC_MODE(open_flag);
|
||||
|
||||
/* O_TRUNC implies we need access checks for write permissions */
|
||||
if (open_flag & O_TRUNC)
|
||||
acc_mode |= MAY_WRITE;
|
||||
|
||||
/* Allow the LSM permission hook to distinguish append
|
||||
access from general write access. */
|
||||
if (open_flag & O_APPEND)
|
||||
acc_mode |= MAY_APPEND;
|
||||
|
||||
op.acc_mode = acc_mode;
|
||||
|
||||
op.intent = LOOKUP_OPEN;
|
||||
if (open_flag & O_CREAT) {
|
||||
op.intent |= LOOKUP_CREATE;
|
||||
if (open_flag & O_EXCL)
|
||||
op.intent |= LOOKUP_EXCL;
|
||||
}
|
||||
|
||||
if (open_flag & O_DIRECTORY)
|
||||
flags |= LOOKUP_DIRECTORY;
|
||||
if (!(open_flag & O_NOFOLLOW))
|
||||
flags |= LOOKUP_FOLLOW;
|
||||
|
||||
filp = get_empty_filp();
|
||||
if (!filp)
|
||||
return ERR_PTR(-ENFILE);
|
||||
|
||||
filp->f_flags = open_flag;
|
||||
filp->f_flags = op->open_flag;
|
||||
nd.intent.open.file = filp;
|
||||
nd.intent.open.flags = flag;
|
||||
nd.intent.open.create_mode = mode;
|
||||
nd.intent.open.flags = open_to_namei_flags(op->open_flag);
|
||||
nd.intent.open.create_mode = op->mode;
|
||||
|
||||
if (open_flag & O_CREAT)
|
||||
if (op->open_flag & O_CREAT)
|
||||
goto creat;
|
||||
|
||||
/* !O_CREAT, simple open */
|
||||
error = do_path_lookup(dfd, pathname, flags | op.intent, &nd);
|
||||
error = do_path_lookup(dfd, pathname, flags | op->intent, &nd);
|
||||
if (unlikely(error))
|
||||
goto out_filp2;
|
||||
error = -ELOOP;
|
||||
|
@ -2386,7 +2333,7 @@ struct file *do_filp_open(int dfd, const char *pathname,
|
|||
goto out_path2;
|
||||
}
|
||||
audit_inode(pathname, nd.path.dentry);
|
||||
filp = finish_open(&nd, open_flag, acc_mode);
|
||||
filp = finish_open(&nd, op->open_flag, op->acc_mode);
|
||||
out2:
|
||||
release_open_intent(&nd);
|
||||
return filp;
|
||||
|
@ -2416,7 +2363,7 @@ reval:
|
|||
/*
|
||||
* We have the parent and last component.
|
||||
*/
|
||||
filp = do_last(&nd, &path, &op, pathname);
|
||||
filp = do_last(&nd, &path, op, pathname);
|
||||
while (unlikely(!filp)) { /* trailing symlink */
|
||||
struct path link = path;
|
||||
struct inode *linki = link.dentry->d_inode;
|
||||
|
@ -2443,7 +2390,7 @@ reval:
|
|||
if (unlikely(error))
|
||||
filp = ERR_PTR(error);
|
||||
else
|
||||
filp = do_last(&nd, &path, &op, pathname);
|
||||
filp = do_last(&nd, &path, op, pathname);
|
||||
if (!IS_ERR(cookie) && linki->i_op->put_link)
|
||||
linki->i_op->put_link(link.dentry, &nd, cookie);
|
||||
path_put(&link);
|
||||
|
@ -2465,23 +2412,6 @@ out_filp:
|
|||
goto out;
|
||||
}
|
||||
|
||||
/**
|
||||
* filp_open - open file and return file pointer
|
||||
*
|
||||
* @filename: path to open
|
||||
* @flags: open flags as per the open(2) second argument
|
||||
* @mode: mode for the new file if O_CREAT is set, else ignored
|
||||
*
|
||||
* This is the helper to open a file from kernelspace if you really
|
||||
* have to. But in generally you should not do this, so please move
|
||||
* along, nothing to see here..
|
||||
*/
|
||||
struct file *filp_open(const char *filename, int flags, int mode)
|
||||
{
|
||||
return do_filp_open(AT_FDCWD, filename, flags, mode, 0);
|
||||
}
|
||||
EXPORT_SYMBOL(filp_open);
|
||||
|
||||
/**
|
||||
* lookup_create - lookup a dentry, creating it if it doesn't exist
|
||||
* @nd: nameidata info
|
||||
|
|
73
fs/open.c
73
fs/open.c
|
@ -890,15 +890,86 @@ void fd_install(unsigned int fd, struct file *file)
|
|||
|
||||
EXPORT_SYMBOL(fd_install);
|
||||
|
||||
static inline int build_open_flags(int flags, int mode, struct open_flags *op)
|
||||
{
|
||||
int lookup_flags = 0;
|
||||
int acc_mode;
|
||||
|
||||
if (!(flags & O_CREAT))
|
||||
mode = 0;
|
||||
op->mode = mode;
|
||||
|
||||
/* Must never be set by userspace */
|
||||
flags &= ~FMODE_NONOTIFY;
|
||||
|
||||
/*
|
||||
* O_SYNC is implemented as __O_SYNC|O_DSYNC. As many places only
|
||||
* check for O_DSYNC if the need any syncing at all we enforce it's
|
||||
* always set instead of having to deal with possibly weird behaviour
|
||||
* for malicious applications setting only __O_SYNC.
|
||||
*/
|
||||
if (flags & __O_SYNC)
|
||||
flags |= O_DSYNC;
|
||||
|
||||
op->open_flag = flags;
|
||||
|
||||
acc_mode = MAY_OPEN | ACC_MODE(flags);
|
||||
|
||||
/* O_TRUNC implies we need access checks for write permissions */
|
||||
if (flags & O_TRUNC)
|
||||
acc_mode |= MAY_WRITE;
|
||||
|
||||
/* Allow the LSM permission hook to distinguish append
|
||||
access from general write access. */
|
||||
if (flags & O_APPEND)
|
||||
acc_mode |= MAY_APPEND;
|
||||
|
||||
op->acc_mode = acc_mode;
|
||||
|
||||
op->intent = LOOKUP_OPEN;
|
||||
if (flags & O_CREAT) {
|
||||
op->intent |= LOOKUP_CREATE;
|
||||
if (flags & O_EXCL)
|
||||
op->intent |= LOOKUP_EXCL;
|
||||
}
|
||||
|
||||
if (flags & O_DIRECTORY)
|
||||
lookup_flags |= LOOKUP_DIRECTORY;
|
||||
if (!(flags & O_NOFOLLOW))
|
||||
lookup_flags |= LOOKUP_FOLLOW;
|
||||
return lookup_flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* filp_open - open file and return file pointer
|
||||
*
|
||||
* @filename: path to open
|
||||
* @flags: open flags as per the open(2) second argument
|
||||
* @mode: mode for the new file if O_CREAT is set, else ignored
|
||||
*
|
||||
* This is the helper to open a file from kernelspace if you really
|
||||
* have to. But in generally you should not do this, so please move
|
||||
* along, nothing to see here..
|
||||
*/
|
||||
struct file *filp_open(const char *filename, int flags, int mode)
|
||||
{
|
||||
struct open_flags op;
|
||||
int lookup = build_open_flags(flags, mode, &op);
|
||||
return do_filp_open(AT_FDCWD, filename, &op, lookup);
|
||||
}
|
||||
EXPORT_SYMBOL(filp_open);
|
||||
|
||||
long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
|
||||
{
|
||||
struct open_flags op;
|
||||
int lookup = build_open_flags(flags, mode, &op);
|
||||
char *tmp = getname(filename);
|
||||
int fd = PTR_ERR(tmp);
|
||||
|
||||
if (!IS_ERR(tmp)) {
|
||||
fd = get_unused_fd_flags(flags);
|
||||
if (fd >= 0) {
|
||||
struct file *f = do_filp_open(dfd, tmp, flags, mode, 0);
|
||||
struct file *f = do_filp_open(dfd, tmp, &op, lookup);
|
||||
if (IS_ERR(f)) {
|
||||
put_unused_fd(fd);
|
||||
fd = PTR_ERR(f);
|
||||
|
|
|
@ -2205,8 +2205,6 @@ extern struct file *create_read_pipe(struct file *f, int flags);
|
|||
extern struct file *create_write_pipe(int flags);
|
||||
extern void free_write_pipe(struct file *);
|
||||
|
||||
extern struct file *do_filp_open(int dfd, const char *pathname,
|
||||
int open_flag, int mode, int acc_mode);
|
||||
extern int may_open(struct path *, int, int);
|
||||
|
||||
extern int kernel_read(struct file *, loff_t, char *, unsigned long);
|
||||
|
|
Загрузка…
Ссылка в новой задаче