aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorAndy Whitcroft <apw@canonical.com>2011-11-02 04:44:39 -0400
committerChristoph Hellwig <hch@serles.lst.de>2011-11-02 07:53:42 -0400
commit1fa1e7f615f4d3ae436fa319af6e4eebdd4026a8 (patch)
treeaa3521aaa762424cc7fb38dbf924a34dac1b03c2 /fs/namei.c
parent32096ea1aac14e6f29d4744924092eca52b937b0 (diff)
readlinkat: ensure we return ENOENT for the empty pathname for normal lookups
Since the commit below which added O_PATH support to the *at() calls, the error return for readlink/readlinkat for the empty pathname has switched from ENOENT to EINVAL: commit 65cfc6722361570bfe255698d9cd4dccaf47570d Author: Al Viro <viro@zeniv.linux.org.uk> Date: Sun Mar 13 15:56:26 2011 -0400 readlinkat(), fchownat() and fstatat() with empty relative pathnames This is both unexpected for userspace and makes readlink/readlinkat inconsistant with all other interfaces; and inconsistant with our stated return for these pathnames. As the readlinkat call does not have a flags parameter we cannot use the AT_EMPTY_PATH approach used in the other calls. Therefore expose whether the original path is infact entry via a new user_path_at_empty() path lookup function. Use this to determine whether to default to EINVAL or ENOENT for failures. Addresses http://bugs.launchpad.net/bugs/817187 [akpm@linux-foundation.org: remove unused getname_flags()] Signed-off-by: Andy Whitcroft <apw@canonical.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: <stable@kernel.org> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/namei.c')
-rw-r--r--fs/namei.c18
1 files changed, 13 insertions, 5 deletions
diff --git a/fs/namei.c b/fs/namei.c
index 7657be4352bf..ac6d214da827 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -137,7 +137,7 @@ static int do_getname(const char __user *filename, char *page)
137 return retval; 137 return retval;
138} 138}
139 139
140static char *getname_flags(const char __user * filename, int flags) 140static char *getname_flags(const char __user *filename, int flags, int *empty)
141{ 141{
142 char *tmp, *result; 142 char *tmp, *result;
143 143
@@ -148,6 +148,8 @@ static char *getname_flags(const char __user * filename, int flags)
148 148
149 result = tmp; 149 result = tmp;
150 if (retval < 0) { 150 if (retval < 0) {
151 if (retval == -ENOENT && empty)
152 *empty = 1;
151 if (retval != -ENOENT || !(flags & LOOKUP_EMPTY)) { 153 if (retval != -ENOENT || !(flags & LOOKUP_EMPTY)) {
152 __putname(tmp); 154 __putname(tmp);
153 result = ERR_PTR(retval); 155 result = ERR_PTR(retval);
@@ -160,7 +162,7 @@ static char *getname_flags(const char __user * filename, int flags)
160 162
161char *getname(const char __user * filename) 163char *getname(const char __user * filename)
162{ 164{
163 return getname_flags(filename, 0); 165 return getname_flags(filename, 0, 0);
164} 166}
165 167
166#ifdef CONFIG_AUDITSYSCALL 168#ifdef CONFIG_AUDITSYSCALL
@@ -1798,11 +1800,11 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
1798 return __lookup_hash(&this, base, NULL); 1800 return __lookup_hash(&this, base, NULL);
1799} 1801}
1800 1802
1801int user_path_at(int dfd, const char __user *name, unsigned flags, 1803int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
1802 struct path *path) 1804 struct path *path, int *empty)
1803{ 1805{
1804 struct nameidata nd; 1806 struct nameidata nd;
1805 char *tmp = getname_flags(name, flags); 1807 char *tmp = getname_flags(name, flags, empty);
1806 int err = PTR_ERR(tmp); 1808 int err = PTR_ERR(tmp);
1807 if (!IS_ERR(tmp)) { 1809 if (!IS_ERR(tmp)) {
1808 1810
@@ -1816,6 +1818,12 @@ int user_path_at(int dfd, const char __user *name, unsigned flags,
1816 return err; 1818 return err;
1817} 1819}
1818 1820
1821int user_path_at(int dfd, const char __user *name, unsigned flags,
1822 struct path *path)
1823{
1824 return user_path_at_empty(dfd, name, flags, path, 0);
1825}
1826
1819static int user_path_parent(int dfd, const char __user *path, 1827static int user_path_parent(int dfd, const char __user *path,
1820 struct nameidata *nd, char **name) 1828 struct nameidata *nd, char **name)
1821{ 1829{