From 0ecf5178fac963631c8e54f5bb61ffff36444791 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 14 Mar 2011 18:56:51 -0400 Subject: [PATCH] --- yaml --- r: 234273 b: refs/heads/master c: f52e0c11305aa09ed56cad97ffc8f0cdc3d78b5d h: refs/heads/master i: 234271: 6613994bd04522ef48414189a396483c32958bfb v: v3 --- [refs] | 2 +- trunk/fs/namei.c | 29 +++++++++++++++++++---------- trunk/include/linux/fcntl.h | 1 + trunk/include/linux/namei.h | 1 + 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/[refs] b/[refs] index e3562c4bea16..3cec66d9e102 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 5fe0c2378884e68beb532f5890cc0e3539ac747b +refs/heads/master: f52e0c11305aa09ed56cad97ffc8f0cdc3d78b5d diff --git a/trunk/fs/namei.c b/trunk/fs/namei.c index abc8d2df121c..83e92bab79a6 100644 --- a/trunk/fs/namei.c +++ b/trunk/fs/namei.c @@ -136,7 +136,7 @@ static int do_getname(const char __user *filename, char *page) return retval; } -char * getname(const char __user * filename) +static char *getname_flags(const char __user * filename, int flags) { char *tmp, *result; @@ -147,14 +147,21 @@ char * getname(const char __user * filename) result = tmp; if (retval < 0) { - __putname(tmp); - result = ERR_PTR(retval); + if (retval != -ENOENT || !(flags & LOOKUP_EMPTY)) { + __putname(tmp); + result = ERR_PTR(retval); + } } } audit_getname(result); return result; } +char *getname(const char __user * filename) +{ + return getname_flags(filename, 0); +} + #ifdef CONFIG_AUDITSYSCALL void putname(const char *name) { @@ -1544,13 +1551,15 @@ static int path_init(int dfd, const char *name, unsigned int flags, dentry = file->f_path.dentry; - retval = -ENOTDIR; - if (!S_ISDIR(dentry->d_inode->i_mode)) - goto fput_fail; + if (*name) { + retval = -ENOTDIR; + if (!S_ISDIR(dentry->d_inode->i_mode)) + goto fput_fail; - retval = file_permission(file, MAY_EXEC); - if (retval) - goto fput_fail; + retval = file_permission(file, MAY_EXEC); + if (retval) + goto fput_fail; + } nd->path = file->f_path; if (flags & LOOKUP_RCU) { @@ -1759,7 +1768,7 @@ int user_path_at(int dfd, const char __user *name, unsigned flags, struct path *path) { struct nameidata nd; - char *tmp = getname(name); + char *tmp = getname_flags(name, flags); int err = PTR_ERR(tmp); if (!IS_ERR(tmp)) { diff --git a/trunk/include/linux/fcntl.h b/trunk/include/linux/fcntl.h index a562fa5fb4e3..f550f894ba15 100644 --- a/trunk/include/linux/fcntl.h +++ b/trunk/include/linux/fcntl.h @@ -46,6 +46,7 @@ unlinking file. */ #define AT_SYMLINK_FOLLOW 0x400 /* Follow symbolic links. */ #define AT_NO_AUTOMOUNT 0x800 /* Suppress terminal automount traversal */ +#define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname */ #ifdef __KERNEL__ diff --git a/trunk/include/linux/namei.h b/trunk/include/linux/namei.h index 83cd6e5cd7dc..9c8603872c36 100644 --- a/trunk/include/linux/namei.h +++ b/trunk/include/linux/namei.h @@ -64,6 +64,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; #define LOOKUP_JUMPED 0x1000 #define LOOKUP_ROOT 0x2000 +#define LOOKUP_EMPTY 0x4000 extern int user_path_at(int, const char __user *, unsigned, struct path *);