aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c93
1 files changed, 86 insertions, 7 deletions
diff --git a/fs/namei.c b/fs/namei.c
index aa62dbda93ac..0d1dff7d3d95 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -28,6 +28,7 @@
28#include <linux/syscalls.h> 28#include <linux/syscalls.h>
29#include <linux/mount.h> 29#include <linux/mount.h>
30#include <linux/audit.h> 30#include <linux/audit.h>
31#include <linux/file.h>
31#include <asm/namei.h> 32#include <asm/namei.h>
32#include <asm/uaccess.h> 33#include <asm/uaccess.h>
33 34
@@ -317,6 +318,18 @@ void path_release_on_umount(struct nameidata *nd)
317 mntput_no_expire(nd->mnt); 318 mntput_no_expire(nd->mnt);
318} 319}
319 320
321/**
322 * release_open_intent - free up open intent resources
323 * @nd: pointer to nameidata
324 */
325void release_open_intent(struct nameidata *nd)
326{
327 if (nd->intent.open.file->f_dentry == NULL)
328 put_filp(nd->intent.open.file);
329 else
330 fput(nd->intent.open.file);
331}
332
320/* 333/*
321 * Internal lookup() using the new generic dcache. 334 * Internal lookup() using the new generic dcache.
322 * SMP-safe 335 * SMP-safe
@@ -1052,6 +1065,70 @@ out:
1052 return retval; 1065 return retval;
1053} 1066}
1054 1067
1068static int __path_lookup_intent_open(const char *name, unsigned int lookup_flags,
1069 struct nameidata *nd, int open_flags, int create_mode)
1070{
1071 struct file *filp = get_empty_filp();
1072 int err;
1073
1074 if (filp == NULL)
1075 return -ENFILE;
1076 nd->intent.open.file = filp;
1077 nd->intent.open.flags = open_flags;
1078 nd->intent.open.create_mode = create_mode;
1079 err = path_lookup(name, lookup_flags|LOOKUP_OPEN, nd);
1080 if (IS_ERR(nd->intent.open.file)) {
1081 if (err == 0) {
1082 err = PTR_ERR(nd->intent.open.file);
1083 path_release(nd);
1084 }
1085 } else if (err != 0)
1086 release_open_intent(nd);
1087 return err;
1088}
1089
1090/**
1091 * path_lookup_open - lookup a file path with open intent
1092 * @name: pointer to file name
1093 * @lookup_flags: lookup intent flags
1094 * @nd: pointer to nameidata
1095 * @open_flags: open intent flags
1096 */
1097int path_lookup_open(const char *name, unsigned int lookup_flags,
1098 struct nameidata *nd, int open_flags)
1099{
1100 return __path_lookup_intent_open(name, lookup_flags, nd,
1101 open_flags, 0);
1102}
1103
1104/**
1105 * path_lookup_create - lookup a file path with open + create intent
1106 * @name: pointer to file name
1107 * @lookup_flags: lookup intent flags
1108 * @nd: pointer to nameidata
1109 * @open_flags: open intent flags
1110 * @create_mode: create intent flags
1111 */
1112int path_lookup_create(const char *name, unsigned int lookup_flags,
1113 struct nameidata *nd, int open_flags, int create_mode)
1114{
1115 return __path_lookup_intent_open(name, lookup_flags|LOOKUP_CREATE, nd,
1116 open_flags, create_mode);
1117}
1118
1119int __user_path_lookup_open(const char __user *name, unsigned int lookup_flags,
1120 struct nameidata *nd, int open_flags)
1121{
1122 char *tmp = getname(name);
1123 int err = PTR_ERR(tmp);
1124
1125 if (!IS_ERR(tmp)) {
1126 err = __path_lookup_intent_open(tmp, lookup_flags, nd, open_flags, 0);
1127 putname(tmp);
1128 }
1129 return err;
1130}
1131
1055/* 1132/*
1056 * Restricted form of lookup. Doesn't follow links, single-component only, 1133 * Restricted form of lookup. Doesn't follow links, single-component only,
1057 * needs parent already locked. Doesn't follow mounts. 1134 * needs parent already locked. Doesn't follow mounts.
@@ -1416,27 +1493,27 @@ int may_open(struct nameidata *nd, int acc_mode, int flag)
1416 */ 1493 */
1417int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) 1494int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
1418{ 1495{
1419 int acc_mode, error = 0; 1496 int acc_mode, error;
1420 struct path path; 1497 struct path path;
1421 struct dentry *dir; 1498 struct dentry *dir;
1422 int count = 0; 1499 int count = 0;
1423 1500
1424 acc_mode = ACC_MODE(flag); 1501 acc_mode = ACC_MODE(flag);
1425 1502
1503 /* O_TRUNC implies we need access checks for write permissions */
1504 if (flag & O_TRUNC)
1505 acc_mode |= MAY_WRITE;
1506
1426 /* Allow the LSM permission hook to distinguish append 1507 /* Allow the LSM permission hook to distinguish append
1427 access from general write access. */ 1508 access from general write access. */
1428 if (flag & O_APPEND) 1509 if (flag & O_APPEND)
1429 acc_mode |= MAY_APPEND; 1510 acc_mode |= MAY_APPEND;
1430 1511
1431 /* Fill in the open() intent data */
1432 nd->intent.open.flags = flag;
1433 nd->intent.open.create_mode = mode;
1434
1435 /* 1512 /*
1436 * The simplest case - just a plain lookup. 1513 * The simplest case - just a plain lookup.
1437 */ 1514 */
1438 if (!(flag & O_CREAT)) { 1515 if (!(flag & O_CREAT)) {
1439 error = path_lookup(pathname, lookup_flags(flag)|LOOKUP_OPEN, nd); 1516 error = path_lookup_open(pathname, lookup_flags(flag), nd, flag);
1440 if (error) 1517 if (error)
1441 return error; 1518 return error;
1442 goto ok; 1519 goto ok;
@@ -1445,7 +1522,7 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd)
1445 /* 1522 /*
1446 * Create - we need to know the parent. 1523 * Create - we need to know the parent.
1447 */ 1524 */
1448 error = path_lookup(pathname, LOOKUP_PARENT|LOOKUP_OPEN|LOOKUP_CREATE, nd); 1525 error = path_lookup_create(pathname, LOOKUP_PARENT, nd, flag, mode);
1449 if (error) 1526 if (error)
1450 return error; 1527 return error;
1451 1528
@@ -1520,6 +1597,8 @@ ok:
1520exit_dput: 1597exit_dput:
1521 dput_path(&path, nd); 1598 dput_path(&path, nd);
1522exit: 1599exit:
1600 if (!IS_ERR(nd->intent.open.file))
1601 release_open_intent(nd);
1523 path_release(nd); 1602 path_release(nd);
1524 return error; 1603 return error;
1525 1604