aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/um/drivers/mconsole_kern.c21
-rw-r--r--fs/internal.h2
-rw-r--r--fs/namei.c80
-rw-r--r--fs/nfsctl.c21
-rw-r--r--fs/open.c14
-rw-r--r--include/linux/fs.h4
-rw-r--r--kernel/sysctl_binary.c19
7 files changed, 77 insertions, 84 deletions
diff --git a/arch/um/drivers/mconsole_kern.c b/arch/um/drivers/mconsole_kern.c
index 975613b23dcf..c70e047eed72 100644
--- a/arch/um/drivers/mconsole_kern.c
+++ b/arch/um/drivers/mconsole_kern.c
@@ -124,35 +124,18 @@ void mconsole_log(struct mc_request *req)
124#if 0 124#if 0
125void mconsole_proc(struct mc_request *req) 125void mconsole_proc(struct mc_request *req)
126{ 126{
127 struct nameidata nd;
128 struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt; 127 struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt;
129 struct file *file; 128 struct file *file;
130 int n, err; 129 int n;
131 char *ptr = req->request.data, *buf; 130 char *ptr = req->request.data, *buf;
132 mm_segment_t old_fs = get_fs(); 131 mm_segment_t old_fs = get_fs();
133 132
134 ptr += strlen("proc"); 133 ptr += strlen("proc");
135 ptr = skip_spaces(ptr); 134 ptr = skip_spaces(ptr);
136 135
137 err = vfs_path_lookup(mnt->mnt_root, mnt, ptr, LOOKUP_FOLLOW, &nd); 136 file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY);
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);
153 if (IS_ERR(file)) { 137 if (IS_ERR(file)) {
154 mconsole_reply(req, "Failed to open file", 1, 0); 138 mconsole_reply(req, "Failed to open file", 1, 0);
155 path_put(&nd.path);
156 goto out; 139 goto out;
157 } 140 }
158 141
diff --git a/fs/internal.h b/fs/internal.h
index 6fdbdf2c6047..52abc5287f50 100644
--- a/fs/internal.h
+++ b/fs/internal.h
@@ -114,6 +114,8 @@ struct open_flags {
114}; 114};
115extern struct file *do_filp_open(int dfd, const char *pathname, 115extern struct file *do_filp_open(int dfd, const char *pathname,
116 const struct open_flags *op, int lookup_flags); 116 const struct open_flags *op, int lookup_flags);
117extern struct file *do_file_open_root(struct dentry *, struct vfsmount *,
118 const char *, const struct open_flags *, int lookup_flags);
117 119
118/* 120/*
119 * inode.c 121 * inode.c
diff --git a/fs/namei.c b/fs/namei.c
index 8ee7785d5642..abc8d2df121c 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -1487,11 +1487,13 @@ static int path_init(int dfd, const char *name, unsigned int flags,
1487 nd->depth = 0; 1487 nd->depth = 0;
1488 if (flags & LOOKUP_ROOT) { 1488 if (flags & LOOKUP_ROOT) {
1489 struct inode *inode = nd->root.dentry->d_inode; 1489 struct inode *inode = nd->root.dentry->d_inode;
1490 if (!inode->i_op->lookup) 1490 if (*name) {
1491 return -ENOTDIR; 1491 if (!inode->i_op->lookup)
1492 retval = inode_permission(inode, MAY_EXEC); 1492 return -ENOTDIR;
1493 if (retval) 1493 retval = inode_permission(inode, MAY_EXEC);
1494 return retval; 1494 if (retval)
1495 return retval;
1496 }
1495 nd->path = nd->root; 1497 nd->path = nd->root;
1496 nd->inode = inode; 1498 nd->inode = inode;
1497 if (flags & LOOKUP_RCU) { 1499 if (flags & LOOKUP_RCU) {
@@ -1937,7 +1939,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, int mode,
1937 return error; 1939 return error;
1938} 1940}
1939 1941
1940int may_open(struct path *path, int acc_mode, int flag) 1942static int may_open(struct path *path, int acc_mode, int flag)
1941{ 1943{
1942 struct dentry *dentry = path->dentry; 1944 struct dentry *dentry = path->dentry;
1943 struct inode *inode = dentry->d_inode; 1945 struct inode *inode = dentry->d_inode;
@@ -2250,11 +2252,10 @@ exit:
2250} 2252}
2251 2253
2252static struct file *path_openat(int dfd, const char *pathname, 2254static 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)
2254{ 2256{
2255 struct file *base = NULL; 2257 struct file *base = NULL;
2256 struct file *filp; 2258 struct file *filp;
2257 struct nameidata nd;
2258 struct path path; 2259 struct path path;
2259 int count = 0; 2260 int count = 0;
2260 int error; 2261 int error;
@@ -2264,27 +2265,27 @@ static struct file *path_openat(int dfd, const char *pathname,
2264 return ERR_PTR(-ENFILE); 2265 return ERR_PTR(-ENFILE);
2265 2266
2266 filp->f_flags = op->open_flag; 2267 filp->f_flags = op->open_flag;
2267 nd.intent.open.file = filp; 2268 nd->intent.open.file = filp;
2268 nd.intent.open.flags = open_to_namei_flags(op->open_flag); 2269 nd->intent.open.flags = open_to_namei_flags(op->open_flag);
2269 nd.intent.open.create_mode = op->mode; 2270 nd->intent.open.create_mode = op->mode;
2270 2271
2271 error = path_init(dfd, pathname, flags | LOOKUP_PARENT, &nd, &base); 2272 error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base);
2272 if (unlikely(error)) 2273 if (unlikely(error))
2273 goto out_filp; 2274 goto out_filp;
2274 2275
2275 current->total_link_count = 0; 2276 current->total_link_count = 0;
2276 error = link_path_walk(pathname, &nd); 2277 error = link_path_walk(pathname, nd);
2277 if (unlikely(error)) 2278 if (unlikely(error))
2278 goto out_filp; 2279 goto out_filp;
2279 2280
2280 filp = do_last(&nd, &path, op, pathname); 2281 filp = do_last(nd, &path, op, pathname);
2281 while (unlikely(!filp)) { /* trailing symlink */ 2282 while (unlikely(!filp)) { /* trailing symlink */
2282 struct path link = path; 2283 struct path link = path;
2283 struct inode *linki = link.dentry->d_inode; 2284 struct inode *linki = link.dentry->d_inode;
2284 void *cookie; 2285 void *cookie;
2285 if (!(nd.flags & LOOKUP_FOLLOW) || count++ == 32) { 2286 if (!(nd->flags & LOOKUP_FOLLOW) || count++ == 32) {
2286 path_put_conditional(&path, &nd); 2287 path_put_conditional(&path, nd);
2287 path_put(&nd.path); 2288 path_put(&nd->path);
2288 filp = ERR_PTR(-ELOOP); 2289 filp = ERR_PTR(-ELOOP);
2289 break; 2290 break;
2290 } 2291 }
@@ -2299,23 +2300,23 @@ static struct file *path_openat(int dfd, const char *pathname,
2299 * have to putname() it when we are done. Procfs-like symlinks 2300 * have to putname() it when we are done. Procfs-like symlinks
2300 * just set LAST_BIND. 2301 * just set LAST_BIND.
2301 */ 2302 */
2302 nd.flags |= LOOKUP_PARENT; 2303 nd->flags |= LOOKUP_PARENT;
2303 nd.flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL); 2304 nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
2304 error = __do_follow_link(&link, &nd, &cookie); 2305 error = __do_follow_link(&link, nd, &cookie);
2305 if (unlikely(error)) 2306 if (unlikely(error))
2306 filp = ERR_PTR(error); 2307 filp = ERR_PTR(error);
2307 else 2308 else
2308 filp = do_last(&nd, &path, op, pathname); 2309 filp = do_last(nd, &path, op, pathname);
2309 if (!IS_ERR(cookie) && linki->i_op->put_link) 2310 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);
2311 path_put(&link); 2312 path_put(&link);
2312 } 2313 }
2313out: 2314out:
2314 if (nd.root.mnt && !(nd.flags & LOOKUP_ROOT)) 2315 if (nd->root.mnt && !(nd->flags & LOOKUP_ROOT))
2315 path_put(&nd.root); 2316 path_put(&nd->root);
2316 if (base) 2317 if (base)
2317 fput(base); 2318 fput(base);
2318 release_open_intent(&nd); 2319 release_open_intent(nd);
2319 return filp; 2320 return filp;
2320 2321
2321out_filp: 2322out_filp:
@@ -2326,16 +2327,39 @@ out_filp:
2326struct file *do_filp_open(int dfd, const char *pathname, 2327struct file *do_filp_open(int dfd, const char *pathname,
2327 const struct open_flags *op, int flags) 2328 const struct open_flags *op, int flags)
2328{ 2329{
2330 struct nameidata nd;
2329 struct file *filp; 2331 struct file *filp;
2330 2332
2331 filp = path_openat(dfd, pathname, op, flags | LOOKUP_RCU); 2333 filp = path_openat(dfd, pathname, &nd, op, flags | LOOKUP_RCU);
2332 if (unlikely(filp == ERR_PTR(-ECHILD))) 2334 if (unlikely(filp == ERR_PTR(-ECHILD)))
2333 filp = path_openat(dfd, pathname, op, flags); 2335 filp = path_openat(dfd, pathname, &nd, op, flags);
2334 if (unlikely(filp == ERR_PTR(-ESTALE))) 2336 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);
2336 return filp; 2338 return filp;
2337} 2339}
2338 2340
2341struct 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
2339/** 2363/**
2340 * lookup_create - lookup a dentry, creating it if it doesn't exist 2364 * lookup_create - lookup a dentry, creating it if it doesn't exist
2341 * @nd: nameidata info 2365 * @nd: nameidata info
diff --git a/fs/nfsctl.c b/fs/nfsctl.c
index bf9cbd242ddd..124e8fcb0dd6 100644
--- a/fs/nfsctl.c
+++ b/fs/nfsctl.c
@@ -22,30 +22,17 @@
22 22
23static struct file *do_open(char *name, int flags) 23static struct file *do_open(char *name, int flags)
24{ 24{
25 struct nameidata nd;
26 struct vfsmount *mnt; 25 struct vfsmount *mnt;
27 int error; 26 struct file *file;
28 27
29 mnt = do_kern_mount("nfsd", 0, "nfsd", NULL); 28 mnt = do_kern_mount("nfsd", 0, "nfsd", NULL);
30 if (IS_ERR(mnt)) 29 if (IS_ERR(mnt))
31 return (struct file *)mnt; 30 return (struct file *)mnt;
32 31
33 error = vfs_path_lookup(mnt->mnt_root, mnt, name, 0, &nd); 32 file = file_open_root(mnt->mnt_root, mnt, name, flags);
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);
42 33
43 if (!error) 34 mntput(mnt); /* drop do_kern_mount reference */
44 return dentry_open(nd.path.dentry, nd.path.mnt, flags, 35 return file;
45 current_cred());
46
47 path_put(&nd.path);
48 return ERR_PTR(error);
49} 36}
50 37
51static struct { 38static struct {
diff --git a/fs/open.c b/fs/open.c
index d05e18c60bae..48afc5c139d2 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -959,6 +959,20 @@ struct file *filp_open(const char *filename, int flags, int mode)
959} 959}
960EXPORT_SYMBOL(filp_open); 960EXPORT_SYMBOL(filp_open);
961 961
962struct 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}
974EXPORT_SYMBOL(file_open_root);
975
962long do_sys_open(int dfd, const char __user *filename, int flags, int mode) 976long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
963{ 977{
964 struct open_flags op; 978 struct open_flags op;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 9c75714f92c1..bf5c3c896072 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1990,6 +1990,8 @@ extern int do_fallocate(struct file *file, int mode, loff_t offset,
1990extern long do_sys_open(int dfd, const char __user *filename, int flags, 1990extern long do_sys_open(int dfd, const char __user *filename, int flags,
1991 int mode); 1991 int mode);
1992extern struct file *filp_open(const char *, int, int); 1992extern struct file *filp_open(const char *, int, int);
1993extern struct file *file_open_root(struct dentry *, struct vfsmount *,
1994 const char *, int);
1993extern struct file * dentry_open(struct dentry *, struct vfsmount *, int, 1995extern struct file * dentry_open(struct dentry *, struct vfsmount *, int,
1994 const struct cred *); 1996 const struct cred *);
1995extern int filp_close(struct file *, fl_owner_t id); 1997extern int filp_close(struct file *, fl_owner_t id);
@@ -2205,8 +2207,6 @@ extern struct file *create_read_pipe(struct file *f, int flags);
2205extern struct file *create_write_pipe(int flags); 2207extern struct file *create_write_pipe(int flags);
2206extern void free_write_pipe(struct file *); 2208extern void free_write_pipe(struct file *);
2207 2209
2208extern int may_open(struct path *, int, int);
2209
2210extern int kernel_read(struct file *, loff_t, char *, unsigned long); 2210extern int kernel_read(struct file *, loff_t, char *, unsigned long);
2211extern struct file * open_exec(const char *); 2211extern struct file * open_exec(const char *);
2212 2212
diff --git a/kernel/sysctl_binary.c b/kernel/sysctl_binary.c
index b875bedf7c9a..3b8e028b9601 100644
--- a/kernel/sysctl_binary.c
+++ b/kernel/sysctl_binary.c
@@ -1321,13 +1321,11 @@ static ssize_t binary_sysctl(const int *name, int nlen,
1321 void __user *oldval, size_t oldlen, void __user *newval, size_t newlen) 1321 void __user *oldval, size_t oldlen, void __user *newval, size_t newlen)
1322{ 1322{
1323 const struct bin_table *table = NULL; 1323 const struct bin_table *table = NULL;
1324 struct nameidata nd;
1325 struct vfsmount *mnt; 1324 struct vfsmount *mnt;
1326 struct file *file; 1325 struct file *file;
1327 ssize_t result; 1326 ssize_t result;
1328 char *pathname; 1327 char *pathname;
1329 int flags; 1328 int flags;
1330 int acc_mode;
1331 1329
1332 pathname = sysctl_getname(name, nlen, &table); 1330 pathname = sysctl_getname(name, nlen, &table);
1333 result = PTR_ERR(pathname); 1331 result = PTR_ERR(pathname);
@@ -1337,28 +1335,17 @@ static ssize_t binary_sysctl(const int *name, int nlen,
1337 /* How should the sysctl be accessed? */ 1335 /* How should the sysctl be accessed? */
1338 if (oldval && oldlen && newval && newlen) { 1336 if (oldval && oldlen && newval && newlen) {
1339 flags = O_RDWR; 1337 flags = O_RDWR;
1340 acc_mode = MAY_READ | MAY_WRITE;
1341 } else if (newval && newlen) { 1338 } else if (newval && newlen) {
1342 flags = O_WRONLY; 1339 flags = O_WRONLY;
1343 acc_mode = MAY_WRITE;
1344 } else if (oldval && oldlen) { 1340 } else if (oldval && oldlen) {
1345 flags = O_RDONLY; 1341 flags = O_RDONLY;
1346 acc_mode = MAY_READ;
1347 } else { 1342 } else {
1348 result = 0; 1343 result = 0;
1349 goto out_putname; 1344 goto out_putname;
1350 } 1345 }
1351 1346
1352 mnt = current->nsproxy->pid_ns->proc_mnt; 1347 mnt = current->nsproxy->pid_ns->proc_mnt;
1353 result = vfs_path_lookup(mnt->mnt_root, mnt, pathname, 0, &nd); 1348 file = file_open_root(mnt->mnt_root, mnt, pathname, flags);
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());
1362 result = PTR_ERR(file); 1349 result = PTR_ERR(file);
1363 if (IS_ERR(file)) 1350 if (IS_ERR(file))
1364 goto out_putname; 1351 goto out_putname;
@@ -1370,10 +1357,6 @@ out_putname:
1370 putname(pathname); 1357 putname(pathname);
1371out: 1358out:
1372 return result; 1359 return result;
1373
1374out_putpath:
1375 path_put(&nd.path);
1376 goto out_putname;
1377} 1360}
1378 1361
1379 1362