aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namei.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-04-28 17:38:32 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-04-28 17:38:32 -0400
commit3f9f0aa687d45cbc8e7bb3cfd3aab555dcc8872e (patch)
tree317c59226a5741c3de8739c09afedfb84b124dff /fs/namei.c
parent0749708352fddbe0fa81fc25f96e3b1f77c655f4 (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.c58
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 */
119static 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
141static char *getname_flags(const char __user *filename, int flags, int *empty) 119static 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
147error:
148 __putname(result);
149 return err;
160} 150}
161 151
162char *getname(const char __user * filename) 152char *getname(const char __user * filename)