Commit 58ec9059 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'work.namei' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs

Pull vfs name lookup updates from Al Viro:
 "Small namei.c patch series, mostly to simplify the rules for nameidata
  state. It's actually from the previous cycle - but I didn't post it
  for review in time...

  Changes visible outside of fs/namei.c: file_open_root() calling
  conventions change, some freed bits in LOOKUP_... space"

* 'work.namei' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
  namei: make sure nd->depth is always valid
  teach set_nameidata() to handle setting the root as well
  take LOOKUP_{ROOT,ROOT_GRABBED,JUMPED} out of LOOKUP_... space
  switch file_open_root() to struct path
parents d3acb15a 7962c7d1
...@@ -1297,18 +1297,18 @@ to lookup: RCU-walk, REF-walk, and REF-walk with forced revalidation. ...@@ -1297,18 +1297,18 @@ to lookup: RCU-walk, REF-walk, and REF-walk with forced revalidation.
yet. This is primarily used to tell the audit subsystem the full yet. This is primarily used to tell the audit subsystem the full
context of a particular access being audited. context of a particular access being audited.
``LOOKUP_ROOT`` indicates that the ``root`` field in the ``nameidata`` was ``ND_ROOT_PRESET`` indicates that the ``root`` field in the ``nameidata`` was
provided by the caller, so it shouldn't be released when it is no provided by the caller, so it shouldn't be released when it is no
longer needed. longer needed.
``LOOKUP_JUMPED`` means that the current dentry was chosen not because ``ND_JUMPED`` means that the current dentry was chosen not because
it had the right name but for some other reason. This happens when it had the right name but for some other reason. This happens when
following "``..``", following a symlink to ``/``, crossing a mount point following "``..``", following a symlink to ``/``, crossing a mount point
or accessing a "``/proc/$PID/fd/$FD``" symlink (also known as a "magic or accessing a "``/proc/$PID/fd/$FD``" symlink (also known as a "magic
link"). In this case the filesystem has not been asked to revalidate the link"). In this case the filesystem has not been asked to revalidate the
name (with ``d_revalidate()``). In such cases the inode may still need name (with ``d_revalidate()``). In such cases the inode may still need
to be revalidated, so ``d_op->d_weak_revalidate()`` is called if to be revalidated, so ``d_op->d_weak_revalidate()`` is called if
``LOOKUP_JUMPED`` is set when the look completes - which may be at the ``ND_JUMPED`` is set when the look completes - which may be at the
final component or, when creating, unlinking, or renaming, at the penultimate component. final component or, when creating, unlinking, or renaming, at the penultimate component.
Resolution-restriction flags Resolution-restriction flags
......
...@@ -899,3 +899,12 @@ iov_iter_copy_from_user_atomic() is gone; use copy_page_from_iter_atomic(). ...@@ -899,3 +899,12 @@ iov_iter_copy_from_user_atomic() is gone; use copy_page_from_iter_atomic().
The difference is copy_page_from_iter_atomic() advances the iterator and The difference is copy_page_from_iter_atomic() advances the iterator and
you don't need iov_iter_advance() after it. However, if you decide to use you don't need iov_iter_advance() after it. However, if you decide to use
only a part of obtained data, you should do iov_iter_revert(). only a part of obtained data, you should do iov_iter_revert().
---
**mandatory**
Calling conventions for file_open_root() changed; now it takes struct path *
instead of passing mount and dentry separately. For callers that used to
pass <mnt, mnt->mnt_root> pair (i.e. the root of given mount), a new helper
is provided - file_open_root_mnt(). In-tree users adjusted.
...@@ -141,7 +141,7 @@ void mconsole_proc(struct mc_request *req) ...@@ -141,7 +141,7 @@ void mconsole_proc(struct mc_request *req)
mconsole_reply(req, "Proc not available", 1, 0); mconsole_reply(req, "Proc not available", 1, 0);
goto out; goto out;
} }
file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY, 0); file = file_open_root_mnt(mnt, ptr, O_RDONLY, 0);
if (IS_ERR(file)) { if (IS_ERR(file)) {
mconsole_reply(req, "Failed to open file", 1, 0); mconsole_reply(req, "Failed to open file", 1, 0);
printk(KERN_ERR "open /proc/%s: %ld\n", ptr, PTR_ERR(file)); printk(KERN_ERR "open /proc/%s: %ld\n", ptr, PTR_ERR(file));
......
...@@ -755,8 +755,8 @@ void do_coredump(const kernel_siginfo_t *siginfo) ...@@ -755,8 +755,8 @@ void do_coredump(const kernel_siginfo_t *siginfo)
task_lock(&init_task); task_lock(&init_task);
get_fs_root(init_task.fs, &root); get_fs_root(init_task.fs, &root);
task_unlock(&init_task); task_unlock(&init_task);
cprm.file = file_open_root(root.dentry, root.mnt, cprm.file = file_open_root(&root, cn.corename,
cn.corename, open_flags, 0600); open_flags, 0600);
path_put(&root); path_put(&root);
} else { } else {
cprm.file = filp_open(cn.corename, open_flags, 0600); cprm.file = filp_open(cn.corename, open_flags, 0600);
......
...@@ -229,7 +229,7 @@ static long do_handle_open(int mountdirfd, struct file_handle __user *ufh, ...@@ -229,7 +229,7 @@ static long do_handle_open(int mountdirfd, struct file_handle __user *ufh,
path_put(&path); path_put(&path);
return fd; return fd;
} }
file = file_open_root(path.dentry, path.mnt, "", open_flag, 0); file = file_open_root(&path, "", open_flag, 0);
if (IS_ERR(file)) { if (IS_ERR(file)) {
put_unused_fd(fd); put_unused_fd(fd);
retval = PTR_ERR(file); retval = PTR_ERR(file);
......
...@@ -129,7 +129,7 @@ struct open_flags { ...@@ -129,7 +129,7 @@ struct open_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); const struct open_flags *op);
extern struct file *do_file_open_root(struct dentry *, struct vfsmount *, extern struct file *do_file_open_root(const struct path *,
const char *, const struct open_flags *); const char *, const struct open_flags *);
extern struct open_how build_open_how(int flags, umode_t mode); extern struct open_how build_open_how(int flags, umode_t mode);
extern int build_open_flags(const struct open_how *how, struct open_flags *op); extern int build_open_flags(const struct open_how *how, struct open_flags *op);
......
...@@ -160,7 +160,7 @@ int kernel_read_file_from_path_initns(const char *path, loff_t offset, ...@@ -160,7 +160,7 @@ int kernel_read_file_from_path_initns(const char *path, loff_t offset,
get_fs_root(init_task.fs, &root); get_fs_root(init_task.fs, &root);
task_unlock(&init_task); task_unlock(&init_task);
file = file_open_root(root.dentry, root.mnt, path, O_RDONLY, 0); file = file_open_root(&root, path, O_RDONLY, 0);
path_put(&root); path_put(&root);
if (IS_ERR(file)) if (IS_ERR(file))
return PTR_ERR(file); return PTR_ERR(file);
......
...@@ -554,7 +554,7 @@ struct nameidata { ...@@ -554,7 +554,7 @@ struct nameidata {
struct qstr last; struct qstr last;
struct path root; struct path root;
struct inode *inode; /* path.dentry.d_inode */ struct inode *inode; /* path.dentry.d_inode */
unsigned int flags; unsigned int flags, state;
unsigned seq, m_seq, r_seq; unsigned seq, m_seq, r_seq;
int last_type; int last_type;
unsigned depth; unsigned depth;
...@@ -573,10 +573,15 @@ struct nameidata { ...@@ -573,10 +573,15 @@ struct nameidata {
umode_t dir_mode; umode_t dir_mode;
} __randomize_layout; } __randomize_layout;
static void set_nameidata(struct nameidata *p, int dfd, struct filename *name) #define ND_ROOT_PRESET 1
#define ND_ROOT_GRABBED 2
#define ND_JUMPED 4
static void __set_nameidata(struct nameidata *p, int dfd, struct filename *name)
{ {
struct nameidata *old = current->nameidata; struct nameidata *old = current->nameidata;
p->stack = p->internal; p->stack = p->internal;
p->depth = 0;
p->dfd = dfd; p->dfd = dfd;
p->name = name; p->name = name;
p->path.mnt = NULL; p->path.mnt = NULL;
...@@ -586,6 +591,17 @@ static void set_nameidata(struct nameidata *p, int dfd, struct filename *name) ...@@ -586,6 +591,17 @@ static void set_nameidata(struct nameidata *p, int dfd, struct filename *name)
current->nameidata = p; current->nameidata = p;
} }
static inline void set_nameidata(struct nameidata *p, int dfd, struct filename *name,
const struct path *root)
{
__set_nameidata(p, dfd, name);
p->state = 0;
if (unlikely(root)) {
p->state = ND_ROOT_PRESET;
p->root = *root;
}
}
static void restore_nameidata(void) static void restore_nameidata(void)
{ {
struct nameidata *now = current->nameidata, *old = now->saved; struct nameidata *now = current->nameidata, *old = now->saved;
...@@ -645,9 +661,9 @@ static void terminate_walk(struct nameidata *nd) ...@@ -645,9 +661,9 @@ static void terminate_walk(struct nameidata *nd)
path_put(&nd->path); path_put(&nd->path);
for (i = 0; i < nd->depth; i++) for (i = 0; i < nd->depth; i++)
path_put(&nd->stack[i].link); path_put(&nd->stack[i].link);
if (nd->flags & LOOKUP_ROOT_GRABBED) { if (nd->state & ND_ROOT_GRABBED) {
path_put(&nd->root); path_put(&nd->root);
nd->flags &= ~LOOKUP_ROOT_GRABBED; nd->state &= ~ND_ROOT_GRABBED;
} }
} else { } else {
nd->flags &= ~LOOKUP_RCU; nd->flags &= ~LOOKUP_RCU;
...@@ -710,9 +726,9 @@ static bool legitimize_root(struct nameidata *nd) ...@@ -710,9 +726,9 @@ static bool legitimize_root(struct nameidata *nd)
if (!nd->root.mnt && (nd->flags & LOOKUP_IS_SCOPED)) if (!nd->root.mnt && (nd->flags & LOOKUP_IS_SCOPED))
return false; return false;
/* Nothing to do if nd->root is zero or is managed by the VFS user. */ /* Nothing to do if nd->root is zero or is managed by the VFS user. */
if (!nd->root.mnt || (nd->flags & LOOKUP_ROOT)) if (!nd->root.mnt || (nd->state & ND_ROOT_PRESET))
return true; return true;
nd->flags |= LOOKUP_ROOT_GRABBED; nd->state |= ND_ROOT_GRABBED;
return legitimize_path(nd, &nd->root, nd->root_seq); return legitimize_path(nd, &nd->root, nd->root_seq);
} }
...@@ -849,8 +865,9 @@ static int complete_walk(struct nameidata *nd) ...@@ -849,8 +865,9 @@ static int complete_walk(struct nameidata *nd)
* We don't want to zero nd->root for scoped-lookups or * We don't want to zero nd->root for scoped-lookups or
* externally-managed nd->root. * externally-managed nd->root.
*/ */
if (!(nd->flags & (LOOKUP_ROOT | LOOKUP_IS_SCOPED))) if (!(nd->state & ND_ROOT_PRESET))
nd->root.mnt = NULL; if (!(nd->flags & LOOKUP_IS_SCOPED))
nd->root.mnt = NULL;
nd->flags &= ~LOOKUP_CACHED; nd->flags &= ~LOOKUP_CACHED;
if (!try_to_unlazy(nd)) if (!try_to_unlazy(nd))
return -ECHILD; return -ECHILD;
...@@ -877,7 +894,7 @@ static int complete_walk(struct nameidata *nd) ...@@ -877,7 +894,7 @@ static int complete_walk(struct nameidata *nd)
return -EXDEV; return -EXDEV;
} }
if (likely(!(nd->flags & LOOKUP_JUMPED))) if (likely(!(nd->state & ND_JUMPED)))
return 0; return 0;
if (likely(!(dentry->d_flags & DCACHE_OP_WEAK_REVALIDATE))) if (likely(!(dentry->d_flags & DCACHE_OP_WEAK_REVALIDATE)))
...@@ -915,7 +932,7 @@ static int set_root(struct nameidata *nd) ...@@ -915,7 +932,7 @@ static int set_root(struct nameidata *nd)
} while (read_seqcount_retry(&fs->seq, seq)); } while (read_seqcount_retry(&fs->seq, seq));
} else { } else {
get_fs_root(fs, &nd->root); get_fs_root(fs, &nd->root);
nd->flags |= LOOKUP_ROOT_GRABBED; nd->state |= ND_ROOT_GRABBED;
} }
return 0; return 0;
} }
...@@ -948,7 +965,7 @@ static int nd_jump_root(struct nameidata *nd) ...@@ -948,7 +965,7 @@ static int nd_jump_root(struct nameidata *nd)
path_get(&nd->path); path_get(&nd->path);
nd->inode = nd->path.dentry->d_inode; nd->inode = nd->path.dentry->d_inode;
} }
nd->flags |= LOOKUP_JUMPED; nd->state |= ND_JUMPED;
return 0; return 0;
} }
...@@ -976,7 +993,7 @@ int nd_jump_link(struct path *path) ...@@ -976,7 +993,7 @@ int nd_jump_link(struct path *path)
path_put(&nd->path); path_put(&nd->path);
nd->path = *path; nd->path = *path;
nd->inode = nd->path.dentry->d_inode; nd->inode = nd->path.dentry->d_inode;
nd->flags |= LOOKUP_JUMPED; nd->state |= ND_JUMPED;
return 0; return 0;
err: err:
...@@ -1423,7 +1440,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, ...@@ -1423,7 +1440,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
if (mounted) { if (mounted) {
path->mnt = &mounted->mnt; path->mnt = &mounted->mnt;
dentry = path->dentry = mounted->mnt.mnt_root; dentry = path->dentry = mounted->mnt.mnt_root;
nd->flags |= LOOKUP_JUMPED; nd->state |= ND_JUMPED;
*seqp = read_seqcount_begin(&dentry->d_seq); *seqp = read_seqcount_begin(&dentry->d_seq);
*inode = dentry->d_inode; *inode = dentry->d_inode;
/* /*
...@@ -1468,7 +1485,7 @@ static inline int handle_mounts(struct nameidata *nd, struct dentry *dentry, ...@@ -1468,7 +1485,7 @@ static inline int handle_mounts(struct nameidata *nd, struct dentry *dentry,
if (unlikely(nd->flags & LOOKUP_NO_XDEV)) if (unlikely(nd->flags & LOOKUP_NO_XDEV))
ret = -EXDEV; ret = -EXDEV;
else else
nd->flags |= LOOKUP_JUMPED; nd->state |= ND_JUMPED;
} }
if (unlikely(ret)) { if (unlikely(ret)) {
dput(path->dentry); dput(path->dentry);
...@@ -2219,7 +2236,7 @@ static int link_path_walk(const char *name, struct nameidata *nd) ...@@ -2219,7 +2236,7 @@ static int link_path_walk(const char *name, struct nameidata *nd)
case 2: case 2:
if (name[1] == '.') { if (name[1] == '.') {
type = LAST_DOTDOT; type = LAST_DOTDOT;
nd->flags |= LOOKUP_JUMPED; nd->state |= ND_JUMPED;
} }
break; break;
case 1: case 1:
...@@ -2227,7 +2244,7 @@ static int link_path_walk(const char *name, struct nameidata *nd) ...@@ -2227,7 +2244,7 @@ static int link_path_walk(const char *name, struct nameidata *nd)
} }
if (likely(type == LAST_NORM)) { if (likely(type == LAST_NORM)) {
struct dentry *parent = nd->path.dentry; struct dentry *parent = nd->path.dentry;
nd->flags &= ~LOOKUP_JUMPED; nd->state &= ~ND_JUMPED;
if (unlikely(parent->d_flags & DCACHE_OP_HASH)) { if (unlikely(parent->d_flags & DCACHE_OP_HASH)) {
struct qstr this = { { .hash_len = hash_len }, .name = name }; struct qstr this = { { .hash_len = hash_len }, .name = name };
err = parent->d_op->d_hash(parent, &this); err = parent->d_op->d_hash(parent, &this);
...@@ -2301,14 +2318,14 @@ static const char *path_init(struct nameidata *nd, unsigned flags) ...@@ -2301,14 +2318,14 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
if (flags & LOOKUP_RCU) if (flags & LOOKUP_RCU)
rcu_read_lock(); rcu_read_lock();
nd->flags = flags | LOOKUP_JUMPED; nd->flags = flags;
nd->depth = 0; nd->state |= ND_JUMPED;
nd->m_seq = __read_seqcount_begin(&mount_lock.seqcount); nd->m_seq = __read_seqcount_begin(&mount_lock.seqcount);
nd->r_seq = __read_seqcount_begin(&rename_lock.seqcount); nd->r_seq = __read_seqcount_begin(&rename_lock.seqcount);
smp_rmb(); smp_rmb();
if (flags & LOOKUP_ROOT) { if (nd->state & ND_ROOT_PRESET) {
struct dentry *root = nd->root.dentry; struct dentry *root = nd->root.dentry;
struct inode *inode = root->d_inode; struct inode *inode = root->d_inode;
if (*s && unlikely(!d_can_lookup(root))) if (*s && unlikely(!d_can_lookup(root)))
...@@ -2383,7 +2400,7 @@ static const char *path_init(struct nameidata *nd, unsigned flags) ...@@ -2383,7 +2400,7 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
nd->root_seq = nd->seq; nd->root_seq = nd->seq;
} else { } else {
path_get(&nd->root); path_get(&nd->root);
nd->flags |= LOOKUP_ROOT_GRABBED; nd->state |= ND_ROOT_GRABBED;
} }
} }
return s; return s;
...@@ -2422,7 +2439,7 @@ static int path_lookupat(struct nameidata *nd, unsigned flags, struct path *path ...@@ -2422,7 +2439,7 @@ static int path_lookupat(struct nameidata *nd, unsigned flags, struct path *path
; ;
if (!err && unlikely(nd->flags & LOOKUP_MOUNTPOINT)) { if (!err && unlikely(nd->flags & LOOKUP_MOUNTPOINT)) {
err = handle_lookup_down(nd); err = handle_lookup_down(nd);
nd->flags &= ~LOOKUP_JUMPED; // no d_weak_revalidate(), please... nd->state &= ~ND_JUMPED; // no d_weak_revalidate(), please...
} }
if (!err) if (!err)
err = complete_walk(nd); err = complete_walk(nd);
...@@ -2446,11 +2463,7 @@ int filename_lookup(int dfd, struct filename *name, unsigned flags, ...@@ -2446,11 +2463,7 @@ int filename_lookup(int dfd, struct filename *name, unsigned flags,
struct nameidata nd; struct nameidata nd;
if (IS_ERR(name)) if (IS_ERR(name))
return PTR_ERR(name); return PTR_ERR(name);
if (unlikely(root)) { set_nameidata(&nd, dfd, name, root);
nd.root = *root;
flags |= LOOKUP_ROOT;
}
set_nameidata(&nd, dfd, name);
retval = path_lookupat(&nd, flags | LOOKUP_RCU, path); retval = path_lookupat(&nd, flags | LOOKUP_RCU, path);
if (unlikely(retval == -ECHILD)) if (unlikely(retval == -ECHILD))
retval = path_lookupat(&nd, flags, path); retval = path_lookupat(&nd, flags, path);
...@@ -2491,7 +2504,7 @@ static struct filename *filename_parentat(int dfd, struct filename *name, ...@@ -2491,7 +2504,7 @@ static struct filename *filename_parentat(int dfd, struct filename *name,
if (IS_ERR(name)) if (IS_ERR(name))
return name; return name;
set_nameidata(&nd, dfd, name); set_nameidata(&nd, dfd, name, NULL);
retval = path_parentat(&nd, flags | LOOKUP_RCU, parent); retval = path_parentat(&nd, flags | LOOKUP_RCU, parent);
if (unlikely(retval == -ECHILD)) if (unlikely(retval == -ECHILD))
retval = path_parentat(&nd, flags, parent); retval = path_parentat(&nd, flags, parent);
...@@ -3517,7 +3530,7 @@ struct file *do_filp_open(int dfd, struct filename *pathname, ...@@ -3517,7 +3530,7 @@ struct file *do_filp_open(int dfd, struct filename *pathname,
int flags = op->lookup_flags; int flags = op->lookup_flags;
struct file *filp; struct file *filp;
set_nameidata(&nd, dfd, pathname); set_nameidata(&nd, dfd, pathname, NULL);
filp = path_openat(&nd, op, flags | LOOKUP_RCU); filp = path_openat(&nd, op, flags | LOOKUP_RCU);
if (unlikely(filp == ERR_PTR(-ECHILD))) if (unlikely(filp == ERR_PTR(-ECHILD)))
filp = path_openat(&nd, op, flags); filp = path_openat(&nd, op, flags);
...@@ -3527,25 +3540,22 @@ struct file *do_filp_open(int dfd, struct filename *pathname, ...@@ -3527,25 +3540,22 @@ struct file *do_filp_open(int dfd, struct filename *pathname,
return filp; return filp;
} }
struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt, struct file *do_file_open_root(const struct path *root,
const char *name, const struct open_flags *op) const char *name, const struct open_flags *op)
{ {
struct nameidata nd; struct nameidata nd;
struct file *file; struct file *file;
struct filename *filename; struct filename *filename;
int flags = op->lookup_flags | LOOKUP_ROOT; int flags = op->lookup_flags;
nd.root.mnt = mnt;
nd.root.dentry = dentry;
if (d_is_symlink(dentry) && op->intent & LOOKUP_OPEN) if (d_is_symlink(root->dentry) && op->intent & LOOKUP_OPEN)
return ERR_PTR(-ELOOP); return ERR_PTR(-ELOOP);
filename = getname_kernel(name); filename = getname_kernel(name);
if (IS_ERR(filename)) if (IS_ERR(filename))
return ERR_CAST(filename); return ERR_CAST(filename);
set_nameidata(&nd, -1, filename); set_nameidata(&nd, -1, filename, root);
file = path_openat(&nd, op, flags | LOOKUP_RCU); file = path_openat(&nd, op, flags | LOOKUP_RCU);
if (unlikely(file == ERR_PTR(-ECHILD))) if (unlikely(file == ERR_PTR(-ECHILD)))
file = path_openat(&nd, op, flags); file = path_openat(&nd, op, flags);
......
...@@ -280,8 +280,6 @@ TRACE_DEFINE_ENUM(LOOKUP_OPEN); ...@@ -280,8 +280,6 @@ TRACE_DEFINE_ENUM(LOOKUP_OPEN);
TRACE_DEFINE_ENUM(LOOKUP_CREATE); TRACE_DEFINE_ENUM(LOOKUP_CREATE);
TRACE_DEFINE_ENUM(LOOKUP_EXCL); TRACE_DEFINE_ENUM(LOOKUP_EXCL);
TRACE_DEFINE_ENUM(LOOKUP_RENAME_TARGET); TRACE_DEFINE_ENUM(LOOKUP_RENAME_TARGET);
TRACE_DEFINE_ENUM(LOOKUP_JUMPED);
TRACE_DEFINE_ENUM(LOOKUP_ROOT);
TRACE_DEFINE_ENUM(LOOKUP_EMPTY); TRACE_DEFINE_ENUM(LOOKUP_EMPTY);
TRACE_DEFINE_ENUM(LOOKUP_DOWN); TRACE_DEFINE_ENUM(LOOKUP_DOWN);
...@@ -297,8 +295,6 @@ TRACE_DEFINE_ENUM(LOOKUP_DOWN); ...@@ -297,8 +295,6 @@ TRACE_DEFINE_ENUM(LOOKUP_DOWN);
{ LOOKUP_CREATE, "CREATE" }, \ { LOOKUP_CREATE, "CREATE" }, \
{ LOOKUP_EXCL, "EXCL" }, \ { LOOKUP_EXCL, "EXCL" }, \
{ LOOKUP_RENAME_TARGET, "RENAME_TARGET" }, \ { LOOKUP_RENAME_TARGET, "RENAME_TARGET" }, \
{ LOOKUP_JUMPED, "JUMPED" }, \
{ LOOKUP_ROOT, "ROOT" }, \
{ LOOKUP_EMPTY, "EMPTY" }, \ { LOOKUP_EMPTY, "EMPTY" }, \
{ LOOKUP_DOWN, "DOWN" }) { LOOKUP_DOWN, "DOWN" })
......
...@@ -1173,7 +1173,7 @@ struct file *filp_open(const char *filename, int flags, umode_t mode) ...@@ -1173,7 +1173,7 @@ struct file *filp_open(const char *filename, int flags, umode_t mode)
} }
EXPORT_SYMBOL(filp_open); EXPORT_SYMBOL(filp_open);
struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt, struct file *file_open_root(const struct path *root,
const char *filename, int flags, umode_t mode) const char *filename, int flags, umode_t mode)
{ {
struct open_flags op; struct open_flags op;
...@@ -1181,7 +1181,7 @@ struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt, ...@@ -1181,7 +1181,7 @@ struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
int err = build_open_flags(&how, &op); int err = build_open_flags(&how, &op);
if (err) if (err)
return ERR_PTR(err); return ERR_PTR(err);
return do_file_open_root(dentry, mnt, filename, &op); return do_file_open_root(root, filename, &op);
} }
EXPORT_SYMBOL(file_open_root); EXPORT_SYMBOL(file_open_root);
......
...@@ -1807,7 +1807,7 @@ static int process_sysctl_arg(char *param, char *val, ...@@ -1807,7 +1807,7 @@ static int process_sysctl_arg(char *param, char *val,
panic("%s: Failed to allocate path for %s\n", __func__, param); panic("%s: Failed to allocate path for %s\n", __func__, param);
strreplace(path, '.', '/'); strreplace(path, '.', '/');
file = file_open_root((*proc_mnt)->mnt_root, *proc_mnt, path, O_WRONLY, 0); file = file_open_root_mnt(*proc_mnt, path, O_WRONLY, 0);
if (IS_ERR(file)) { if (IS_ERR(file)) {
err = PTR_ERR(file); err = PTR_ERR(file);
if (err == -ENOENT) if (err == -ENOENT)
......
...@@ -2768,8 +2768,14 @@ extern long do_sys_open(int dfd, const char __user *filename, int flags, ...@@ -2768,8 +2768,14 @@ extern long do_sys_open(int dfd, const char __user *filename, int flags,
umode_t mode); umode_t mode);
extern struct file *file_open_name(struct filename *, int, umode_t); extern struct file *file_open_name(struct filename *, int, umode_t);
extern struct file *filp_open(const char *, int, umode_t); extern struct file *filp_open(const char *, int, umode_t);
extern struct file *file_open_root(struct dentry *, struct vfsmount *, extern struct file *file_open_root(const struct path *,
const char *, int, umode_t); const char *, int, umode_t);
static inline struct file *file_open_root_mnt(struct vfsmount *mnt,
const char *name, int flags, umode_t mode)
{
return file_open_root(&(struct path){.mnt = mnt, .dentry = mnt->mnt_root},
name, flags, mode);
}
extern struct file * dentry_open(const struct path *, int, const struct cred *); extern struct file * dentry_open(const struct path *, int, const struct cred *);
extern struct file * open_with_fake_path(const struct path *, int, extern struct file * open_with_fake_path(const struct path *, int,
struct inode*, const struct cred *); struct inode*, const struct cred *);
......
...@@ -36,9 +36,6 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT}; ...@@ -36,9 +36,6 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT};
/* internal use only */ /* internal use only */
#define LOOKUP_PARENT 0x0010 #define LOOKUP_PARENT 0x0010
#define LOOKUP_JUMPED 0x1000
#define LOOKUP_ROOT 0x2000
#define LOOKUP_ROOT_GRABBED 0x0008
/* Scoping flags for lookup. */ /* Scoping flags for lookup. */
#define LOOKUP_NO_SYMLINKS 0x010000 /* No symlink crossing. */ #define LOOKUP_NO_SYMLINKS 0x010000 /* No symlink crossing. */
......
...@@ -26,7 +26,7 @@ static struct vfsmount *blob_to_mnt(const void *data, size_t len, const char *na ...@@ -26,7 +26,7 @@ static struct vfsmount *blob_to_mnt(const void *data, size_t len, const char *na
if (IS_ERR(mnt)) if (IS_ERR(mnt))
return mnt; return mnt;
file = file_open_root(mnt->mnt_root, mnt, name, O_CREAT | O_WRONLY, 0700); file = file_open_root_mnt(mnt, name, O_CREAT | O_WRONLY, 0700);
if (IS_ERR(file)) { if (IS_ERR(file)) {
mntput(mnt); mntput(mnt);
return ERR_CAST(file); return ERR_CAST(file);
......
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