diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-04-28 17:38:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-04-28 17:38:32 -0400 |
commit | 3f9f0aa687d45cbc8e7bb3cfd3aab555dcc8872e (patch) | |
tree | 317c59226a5741c3de8739c09afedfb84b124dff /fs/namei.c | |
parent | 0749708352fddbe0fa81fc25f96e3b1f77c655f4 (diff) |
VFS: clean up and simplify getname_flags()
This removes a number of silly games around strncpy_from_user() in
do_getname(), and removes that helper function entirely. We instead
make getname_flags() just use strncpy_from_user() properly directly.
Removing the wrapper function simplifies things noticeably, mostly
because we no longer play the unnecessary games with segments (x86
strncpy_from_user() no longer needs the hack), but also because the
empty path handling is just much more obvious. The return value of
"strncpy_to_user()" is much more obvious than checking an odd error
return case from do_getname().
[ non-x86 architectures were notified of this change several weeks ago,
since it is possible that they have copied the old broken x86
strncpy_from_user. But nobody reacted, so .. See
http://www.spinics.net/lists/linux-arch/msg17313.html
for details ]
Cc: linux-arch@vger.kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/namei.c')
-rw-r--r-- | fs/namei.c | 58 |
1 files changed, 24 insertions, 34 deletions
diff --git a/fs/namei.c b/fs/namei.c index 0062dd17eb55..494b1caa25f8 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -116,47 +116,37 @@ | |||
116 | * POSIX.1 2.4: an empty pathname is invalid (ENOENT). | 116 | * POSIX.1 2.4: an empty pathname is invalid (ENOENT). |
117 | * PATH_MAX includes the nul terminator --RR. | 117 | * PATH_MAX includes the nul terminator --RR. |
118 | */ | 118 | */ |
119 | static int do_getname(const char __user *filename, char *page) | ||
120 | { | ||
121 | int retval; | ||
122 | unsigned long len = PATH_MAX; | ||
123 | |||
124 | if (!segment_eq(get_fs(), KERNEL_DS)) { | ||
125 | if ((unsigned long) filename >= TASK_SIZE) | ||
126 | return -EFAULT; | ||
127 | if (TASK_SIZE - (unsigned long) filename < PATH_MAX) | ||
128 | len = TASK_SIZE - (unsigned long) filename; | ||
129 | } | ||
130 | |||
131 | retval = strncpy_from_user(page, filename, len); | ||
132 | if (retval > 0) { | ||
133 | if (retval < len) | ||
134 | return 0; | ||
135 | return -ENAMETOOLONG; | ||
136 | } else if (!retval) | ||
137 | retval = -ENOENT; | ||
138 | return retval; | ||
139 | } | ||
140 | |||
141 | static char *getname_flags(const char __user *filename, int flags, int *empty) | 119 | static char *getname_flags(const char __user *filename, int flags, int *empty) |
142 | { | 120 | { |
143 | char *result = __getname(); | 121 | char *result = __getname(), *err; |
144 | int retval; | 122 | int len; |
145 | 123 | ||
146 | if (!result) | 124 | if (unlikely(!result)) |
147 | return ERR_PTR(-ENOMEM); | 125 | return ERR_PTR(-ENOMEM); |
148 | 126 | ||
149 | retval = do_getname(filename, result); | 127 | len = strncpy_from_user(result, filename, PATH_MAX); |
150 | if (retval < 0) { | 128 | err = ERR_PTR(len); |
151 | if (retval == -ENOENT && empty) | 129 | if (unlikely(len < 0)) |
130 | goto error; | ||
131 | |||
132 | /* The empty path is special. */ | ||
133 | if (unlikely(!len)) { | ||
134 | if (empty) | ||
152 | *empty = 1; | 135 | *empty = 1; |
153 | if (retval != -ENOENT || !(flags & LOOKUP_EMPTY)) { | 136 | err = ERR_PTR(-ENOENT); |
154 | __putname(result); | 137 | if (!(flags & LOOKUP_EMPTY)) |
155 | return ERR_PTR(retval); | 138 | goto error; |
156 | } | ||
157 | } | 139 | } |
158 | audit_getname(result); | 140 | |
159 | return result; | 141 | err = ERR_PTR(-ENAMETOOLONG); |
142 | if (likely(len < PATH_MAX)) { | ||
143 | audit_getname(result); | ||
144 | return result; | ||
145 | } | ||
146 | |||
147 | error: | ||
148 | __putname(result); | ||
149 | return err; | ||
160 | } | 150 | } |
161 | 151 | ||
162 | char *getname(const char __user * filename) | 152 | char *getname(const char __user * filename) |