Skip to content

Commit 73d049a

Browse files
author
Al Viro
committed
open-style analog of vfs_path_lookup()
new function: file_open_root(dentry, mnt, name, flags) opens the file vfs_path_lookup would arrive to. Note that name can be empty; in that case the usual requirement that dentry should be a directory is lifted. open-coded equivalents switched to it, may_open() got down exactly one caller and became static. Signed-off-by: Al Viro <[email protected]>
1 parent 5b6ca02 commit 73d049a

File tree

7 files changed

+77
-84
lines changed

7 files changed

+77
-84
lines changed

arch/um/drivers/mconsole_kern.c

+2-19
Original file line numberDiff line numberDiff line change
@@ -124,35 +124,18 @@ void mconsole_log(struct mc_request *req)
124124
#if 0
125125
void mconsole_proc(struct mc_request *req)
126126
{
127-
struct nameidata nd;
128127
struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt;
129128
struct file *file;
130-
int n, err;
129+
int n;
131130
char *ptr = req->request.data, *buf;
132131
mm_segment_t old_fs = get_fs();
133132

134133
ptr += strlen("proc");
135134
ptr = skip_spaces(ptr);
136135

137-
err = vfs_path_lookup(mnt->mnt_root, mnt, ptr, LOOKUP_FOLLOW, &nd);
138-
if (err) {
139-
mconsole_reply(req, "Failed to look up file", 1, 0);
140-
goto out;
141-
}
142-
143-
err = may_open(&nd.path, MAY_READ, O_RDONLY);
144-
if (result) {
145-
mconsole_reply(req, "Failed to open file", 1, 0);
146-
path_put(&nd.path);
147-
goto out;
148-
}
149-
150-
file = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY,
151-
current_cred());
152-
err = PTR_ERR(file);
136+
file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY);
153137
if (IS_ERR(file)) {
154138
mconsole_reply(req, "Failed to open file", 1, 0);
155-
path_put(&nd.path);
156139
goto out;
157140
}
158141

fs/internal.h

+2
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ struct open_flags {
114114
};
115115
extern struct file *do_filp_open(int dfd, const char *pathname,
116116
const struct open_flags *op, int lookup_flags);
117+
extern struct file *do_file_open_root(struct dentry *, struct vfsmount *,
118+
const char *, const struct open_flags *, int lookup_flags);
117119

118120
/*
119121
* inode.c

fs/namei.c

+52-28
Original file line numberDiff line numberDiff line change
@@ -1487,11 +1487,13 @@ static int path_init(int dfd, const char *name, unsigned int flags,
14871487
nd->depth = 0;
14881488
if (flags & LOOKUP_ROOT) {
14891489
struct inode *inode = nd->root.dentry->d_inode;
1490-
if (!inode->i_op->lookup)
1491-
return -ENOTDIR;
1492-
retval = inode_permission(inode, MAY_EXEC);
1493-
if (retval)
1494-
return retval;
1490+
if (*name) {
1491+
if (!inode->i_op->lookup)
1492+
return -ENOTDIR;
1493+
retval = inode_permission(inode, MAY_EXEC);
1494+
if (retval)
1495+
return retval;
1496+
}
14951497
nd->path = nd->root;
14961498
nd->inode = inode;
14971499
if (flags & LOOKUP_RCU) {
@@ -1937,7 +1939,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
19371939
return error;
19381940
}
19391941

1940-
int may_open(struct path *path, int acc_mode, int flag)
1942+
static int may_open(struct path *path, int acc_mode, int flag)
19411943
{
19421944
struct dentry *dentry = path->dentry;
19431945
struct inode *inode = dentry->d_inode;
@@ -2250,11 +2252,10 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
22502252
}
22512253

22522254
static struct file *path_openat(int dfd, const char *pathname,
2253-
const struct open_flags *op, int flags)
2255+
struct nameidata *nd, const struct open_flags *op, int flags)
22542256
{
22552257
struct file *base = NULL;
22562258
struct file *filp;
2257-
struct nameidata nd;
22582259
struct path path;
22592260
int count = 0;
22602261
int error;
@@ -2264,27 +2265,27 @@ static struct file *path_openat(int dfd, const char *pathname,
22642265
return ERR_PTR(-ENFILE);
22652266

22662267
filp->f_flags = op->open_flag;
2267-
nd.intent.open.file = filp;
2268-
nd.intent.open.flags = open_to_namei_flags(op->open_flag);
2269-
nd.intent.open.create_mode = op->mode;
2268+
nd->intent.open.file = filp;
2269+
nd->intent.open.flags = open_to_namei_flags(op->open_flag);
2270+
nd->intent.open.create_mode = op->mode;
22702271

2271-
error = path_init(dfd, pathname, flags | LOOKUP_PARENT, &nd, &base);
2272+
error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base);
22722273
if (unlikely(error))
22732274
goto out_filp;
22742275

22752276
current->total_link_count = 0;
2276-
error = link_path_walk(pathname, &nd);
2277+
error = link_path_walk(pathname, nd);
22772278
if (unlikely(error))
22782279
goto out_filp;
22792280

2280-
filp = do_last(&nd, &path, op, pathname);
2281+
filp = do_last(nd, &path, op, pathname);
22812282
while (unlikely(!filp)) { /* trailing symlink */
22822283
struct path link = path;
22832284
struct inode *linki = link.dentry->d_inode;
22842285
void *cookie;
2285-
if (!(nd.flags & LOOKUP_FOLLOW) || count++ == 32) {
2286-
path_put_conditional(&path, &nd);
2287-
path_put(&nd.path);
2286+
if (!(nd->flags & LOOKUP_FOLLOW) || count++ == 32) {
2287+
path_put_conditional(&path, nd);
2288+
path_put(&nd->path);
22882289
filp = ERR_PTR(-ELOOP);
22892290
break;
22902291
}
@@ -2299,23 +2300,23 @@ static struct file *path_openat(int dfd, const char *pathname,
22992300
* have to putname() it when we are done. Procfs-like symlinks
23002301
* just set LAST_BIND.
23012302
*/
2302-
nd.flags |= LOOKUP_PARENT;
2303-
nd.flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
2304-
error = __do_follow_link(&link, &nd, &cookie);
2303+
nd->flags |= LOOKUP_PARENT;
2304+
nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
2305+
error = __do_follow_link(&link, nd, &cookie);
23052306
if (unlikely(error))
23062307
filp = ERR_PTR(error);
23072308
else
2308-
filp = do_last(&nd, &path, op, pathname);
2309+
filp = do_last(nd, &path, op, pathname);
23092310
if (!IS_ERR(cookie) && linki->i_op->put_link)
2310-
linki->i_op->put_link(link.dentry, &nd, cookie);
2311+
linki->i_op->put_link(link.dentry, nd, cookie);
23112312
path_put(&link);
23122313
}
23132314
out:
2314-
if (nd.root.mnt && !(nd.flags & LOOKUP_ROOT))
2315-
path_put(&nd.root);
2315+
if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT))
2316+
path_put(&nd->root);
23162317
if (base)
23172318
fput(base);
2318-
release_open_intent(&nd);
2319+
release_open_intent(nd);
23192320
return filp;
23202321

23212322
out_filp:
@@ -2326,16 +2327,39 @@ static struct file *path_openat(int dfd, const char *pathname,
23262327
struct file *do_filp_open(int dfd, const char *pathname,
23272328
const struct open_flags *op, int flags)
23282329
{
2330+
struct nameidata nd;
23292331
struct file *filp;
23302332

2331-
filp = path_openat(dfd, pathname, op, flags | LOOKUP_RCU);
2333+
filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU);
23322334
if (unlikely(filp == ERR_PTR(-ECHILD)))
2333-
filp = path_openat(dfd, pathname, op, flags);
2335+
filp = path_openat(dfd, pathname, &nd, op, flags);
23342336
if (unlikely(filp == ERR_PTR(-ESTALE)))
2335-
filp = path_openat(dfd, pathname, op, flags | LOOKUP_REVAL);
2337+
filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_REVAL);
23362338
return filp;
23372339
}
23382340

2341+
struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
2342+
const char *name, const struct open_flags *op, int flags)
2343+
{
2344+
struct nameidata nd;
2345+
struct file *file;
2346+
2347+
nd.root.mnt = mnt;
2348+
nd.root.dentry = dentry;
2349+
2350+
flags |= LOOKUP_ROOT;
2351+
2352+
if (dentry->d_inode->i_op->follow_link)
2353+
return ERR_PTR(-ELOOP);
2354+
2355+
file = path_openat(-1, name, &nd, op, flags | LOOKUP_RCU);
2356+
if (unlikely(file == ERR_PTR(-ECHILD)))
2357+
file = path_openat(-1, name, &nd, op, flags);
2358+
if (unlikely(file == ERR_PTR(-ESTALE)))
2359+
file = path_openat(-1, name, &nd, op, flags | LOOKUP_REVAL);
2360+
return file;
2361+
}
2362+
23392363
/**
23402364
* lookup_create - lookup a dentry, creating it if it doesn't exist
23412365
* @nd: nameidata info

fs/nfsctl.c

+4-17
Original file line numberDiff line numberDiff line change
@@ -22,30 +22,17 @@
2222

2323
static struct file *do_open(char *name, int flags)
2424
{
25-
struct nameidata nd;
2625
struct vfsmount *mnt;
27-
int error;
26+
struct file *file;
2827

2928
mnt = do_kern_mount("nfsd", 0, "nfsd", NULL);
3029
if (IS_ERR(mnt))
3130
return (struct file *)mnt;
3231

33-
error = vfs_path_lookup(mnt->mnt_root, mnt, name, 0, &nd);
34-
mntput(mnt); /* drop do_kern_mount reference */
35-
if (error)
36-
return ERR_PTR(error);
37-
38-
if (flags == O_RDWR)
39-
error = may_open(&nd.path, MAY_READ|MAY_WRITE, flags);
40-
else
41-
error = may_open(&nd.path, MAY_WRITE, flags);
32+
file = file_open_root(mnt->mnt_root, mnt, name, flags);
4233

43-
if (!error)
44-
return dentry_open(nd.path.dentry, nd.path.mnt, flags,
45-
current_cred());
46-
47-
path_put(&nd.path);
48-
return ERR_PTR(error);
34+
mntput(mnt); /* drop do_kern_mount reference */
35+
return file;
4936
}
5037

5138
static struct {

fs/open.c

+14
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,20 @@ struct file *filp_open(const char *filename, int flags, int mode)
959959
}
960960
EXPORT_SYMBOL(filp_open);
961961

962+
struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
963+
const char *filename, int flags)
964+
{
965+
struct open_flags op;
966+
int lookup = build_open_flags(flags, 0, &op);
967+
if (flags & O_CREAT)
968+
return ERR_PTR(-EINVAL);
969+
if (!filename && (flags & O_DIRECTORY))
970+
if (!dentry->d_inode->i_op->lookup)
971+
return ERR_PTR(-ENOTDIR);
972+
return do_file_open_root(dentry, mnt, filename, &op, lookup);
973+
}
974+
EXPORT_SYMBOL(file_open_root);
975+
962976
long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
963977
{
964978
struct open_flags op;

include/linux/fs.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -1990,6 +1990,8 @@ extern int do_fallocate(struct file *file, int mode, loff_t offset,
19901990
extern long do_sys_open(int dfd, const char __user *filename, int flags,
19911991
int mode);
19921992
extern struct file *filp_open(const char *, int, int);
1993+
extern struct file *file_open_root(struct dentry *, struct vfsmount *,
1994+
const char *, int);
19931995
extern struct file * dentry_open(struct dentry *, struct vfsmount *, int,
19941996
const struct cred *);
19951997
extern int filp_close(struct file *, fl_owner_t id);
@@ -2205,8 +2207,6 @@ extern struct file *create_read_pipe(struct file *f, int flags);
22052207
extern struct file *create_write_pipe(int flags);
22062208
extern void free_write_pipe(struct file *);
22072209

2208-
extern int may_open(struct path *, int, int);
2209-
22102210
extern int kernel_read(struct file *, loff_t, char *, unsigned long);
22112211
extern struct file * open_exec(const char *);
22122212

kernel/sysctl_binary.c

+1-18
Original file line numberDiff line numberDiff line change
@@ -1321,13 +1321,11 @@ static ssize_t binary_sysctl(const int *name, int nlen,
13211321
void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)
13221322
{
13231323
const struct bin_table *table = NULL;
1324-
struct nameidata nd;
13251324
struct vfsmount *mnt;
13261325
struct file *file;
13271326
ssize_t result;
13281327
char *pathname;
13291328
int flags;
1330-
int acc_mode;
13311329

13321330
pathname = sysctl_getname(name, nlen, &table);
13331331
result = PTR_ERR(pathname);
@@ -1337,28 +1335,17 @@ static ssize_t binary_sysctl(const int *name, int nlen,
13371335
/* How should the sysctl be accessed? */
13381336
if (oldval && oldlen && newval && newlen) {
13391337
flags = O_RDWR;
1340-
acc_mode = MAY_READ | MAY_WRITE;
13411338
} else if (newval && newlen) {
13421339
flags = O_WRONLY;
1343-
acc_mode = MAY_WRITE;
13441340
} else if (oldval && oldlen) {
13451341
flags = O_RDONLY;
1346-
acc_mode = MAY_READ;
13471342
} else {
13481343
result = 0;
13491344
goto out_putname;
13501345
}
13511346

13521347
mnt = current->nsproxy->pid_ns->proc_mnt;
1353-
result = vfs_path_lookup(mnt->mnt_root, mnt, pathname, 0, &nd);
1354-
if (result)
1355-
goto out_putname;
1356-
1357-
result = may_open(&nd.path, acc_mode, flags);
1358-
if (result)
1359-
goto out_putpath;
1360-
1361-
file = dentry_open(nd.path.dentry, nd.path.mnt, flags, current_cred());
1348+
file = file_open_root(mnt->mnt_root, mnt, pathname, flags);
13621349
result = PTR_ERR(file);
13631350
if (IS_ERR(file))
13641351
goto out_putname;
@@ -1370,10 +1357,6 @@ static ssize_t binary_sysctl(const int *name, int nlen,
13701357
putname(pathname);
13711358
out:
13721359
return result;
1373-
1374-
out_putpath:
1375-
path_put(&nd.path);
1376-
goto out_putname;
13771360
}
13781361

13791362

0 commit comments

Comments
 (0)