Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 234250
b: refs/heads/master
c: 47c805d
h: refs/heads/master
v: v3
  • Loading branch information
Al Viro committed Mar 14, 2011
1 parent a055a34 commit 9a31ad4
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 89 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c3e380b0b3cfa613189fb91513efd88a65e1d9d8
refs/heads/master: 47c805dc2d2dff686962f5f0baa6bac2d703ba19
18 changes: 12 additions & 6 deletions trunk/fs/exec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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;

Expand Down
8 changes: 8 additions & 0 deletions trunk/fs/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
88 changes: 9 additions & 79 deletions trunk/fs/namei.c
Original file line number Diff line number Diff line change
Expand Up @@ -2169,13 +2169,6 @@ static struct file *finish_open(struct nameidata *nd,
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
*/
Expand Down Expand Up @@ -2305,74 +2298,28 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
* 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;
Expand All @@ -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;
Expand Down Expand Up @@ -2416,7 +2363,7 @@ struct file *do_filp_open(int dfd, const char *pathname,
/*
* 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;
Expand All @@ -2443,7 +2390,7 @@ struct file *do_filp_open(int dfd, const char *pathname,
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);
Expand All @@ -2465,23 +2412,6 @@ struct file *do_filp_open(int dfd, const char *pathname,
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
Expand Down
73 changes: 72 additions & 1 deletion trunk/fs/open.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 0 additions & 2 deletions trunk/include/linux/fs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 9a31ad4

Please sign in to comment.