From 0e5cfc4b93cbdf1d155a7f8e0453c3788a18a2a8 Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Wed, 2 Nov 2011 09:44:39 +0100 Subject: [PATCH] --- yaml --- r: 273190 b: refs/heads/master c: 1fa1e7f615f4d3ae436fa319af6e4eebdd4026a8 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/fs/namei.c | 18 +++++++++++++----- trunk/fs/stat.c | 5 +++-- trunk/include/linux/namei.h | 1 + 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/[refs] b/[refs] index b8f719789597..df49f22308ec 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 32096ea1aac14e6f29d4744924092eca52b937b0 +refs/heads/master: 1fa1e7f615f4d3ae436fa319af6e4eebdd4026a8 diff --git a/trunk/fs/namei.c b/trunk/fs/namei.c index 7657be4352bf..ac6d214da827 100644 --- a/trunk/fs/namei.c +++ b/trunk/fs/namei.c @@ -137,7 +137,7 @@ static int do_getname(const char __user *filename, char *page) return retval; } -static char *getname_flags(const char __user * filename, int flags) +static char *getname_flags(const char __user *filename, int flags, int *empty) { char *tmp, *result; @@ -148,6 +148,8 @@ static char *getname_flags(const char __user * filename, int flags) result = tmp; if (retval < 0) { + if (retval == -ENOENT && empty) + *empty = 1; if (retval != -ENOENT || !(flags & LOOKUP_EMPTY)) { __putname(tmp); result = ERR_PTR(retval); @@ -160,7 +162,7 @@ static char *getname_flags(const char __user * filename, int flags) char *getname(const char __user * filename) { - return getname_flags(filename, 0); + return getname_flags(filename, 0, 0); } #ifdef CONFIG_AUDITSYSCALL @@ -1798,11 +1800,11 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len) return __lookup_hash(&this, base, NULL); } -int user_path_at(int dfd, const char __user *name, unsigned flags, - struct path *path) +int user_path_at_empty(int dfd, const char __user *name, unsigned flags, + struct path *path, int *empty) { struct nameidata nd; - char *tmp = getname_flags(name, flags); + char *tmp = getname_flags(name, flags, empty); int err = PTR_ERR(tmp); if (!IS_ERR(tmp)) { @@ -1816,6 +1818,12 @@ int user_path_at(int dfd, const char __user *name, unsigned flags, return err; } +int user_path_at(int dfd, const char __user *name, unsigned flags, + struct path *path) +{ + return user_path_at_empty(dfd, name, flags, path, 0); +} + static int user_path_parent(int dfd, const char __user *path, struct nameidata *nd, char **name) { diff --git a/trunk/fs/stat.c b/trunk/fs/stat.c index 78a3aa83c7ea..8806b8997d2e 100644 --- a/trunk/fs/stat.c +++ b/trunk/fs/stat.c @@ -294,15 +294,16 @@ SYSCALL_DEFINE4(readlinkat, int, dfd, const char __user *, pathname, { struct path path; int error; + int empty = 0; if (bufsiz <= 0) return -EINVAL; - error = user_path_at(dfd, pathname, LOOKUP_EMPTY, &path); + error = user_path_at_empty(dfd, pathname, LOOKUP_EMPTY, &path, &empty); if (!error) { struct inode *inode = path.dentry->d_inode; - error = -EINVAL; + error = empty ? -ENOENT : -EINVAL; if (inode->i_op->readlink) { error = security_inode_readlink(path.dentry); if (!error) { diff --git a/trunk/include/linux/namei.h b/trunk/include/linux/namei.h index 409328d1cbbb..ffc02135c483 100644 --- a/trunk/include/linux/namei.h +++ b/trunk/include/linux/namei.h @@ -67,6 +67,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND}; #define LOOKUP_EMPTY 0x4000 extern int user_path_at(int, const char __user *, unsigned, struct path *); +extern int user_path_at_empty(int, const char __user *, unsigned, struct path *, int *empty); #define user_path(name, path) user_path_at(AT_FDCWD, name, LOOKUP_FOLLOW, path) #define user_lpath(name, path) user_path_at(AT_FDCWD, name, 0, path)