aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/base.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc/base.c')
-rw-r--r--fs/proc/base.c71
1 files changed, 8 insertions, 63 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 255f6754c70d..8040f9d1cf07 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -212,7 +212,7 @@ static int proc_root_link(struct dentry *dentry, struct path *path)
212static ssize_t get_mm_cmdline(struct mm_struct *mm, char __user *buf, 212static ssize_t get_mm_cmdline(struct mm_struct *mm, char __user *buf,
213 size_t count, loff_t *ppos) 213 size_t count, loff_t *ppos)
214{ 214{
215 unsigned long arg_start, arg_end, env_start, env_end; 215 unsigned long arg_start, arg_end;
216 unsigned long pos, len; 216 unsigned long pos, len;
217 char *page; 217 char *page;
218 218
@@ -223,36 +223,18 @@ static ssize_t get_mm_cmdline(struct mm_struct *mm, char __user *buf,
223 spin_lock(&mm->arg_lock); 223 spin_lock(&mm->arg_lock);
224 arg_start = mm->arg_start; 224 arg_start = mm->arg_start;
225 arg_end = mm->arg_end; 225 arg_end = mm->arg_end;
226 env_start = mm->env_start;
227 env_end = mm->env_end;
228 spin_unlock(&mm->arg_lock); 226 spin_unlock(&mm->arg_lock);
229 227
230 if (arg_start >= arg_end) 228 if (arg_start >= arg_end)
231 return 0; 229 return 0;
232 230
233 /*
234 * We have traditionally allowed the user to re-write
235 * the argument strings and overflow the end result
236 * into the environment section. But only do that if
237 * the environment area is contiguous to the arguments.
238 */
239 if (env_start != arg_end || env_start >= env_end)
240 env_start = env_end = arg_end;
241
242 /* .. and limit it to a maximum of one page of slop */
243 if (env_end >= arg_end + PAGE_SIZE)
244 env_end = arg_end + PAGE_SIZE - 1;
245
246 /* We're not going to care if "*ppos" has high bits set */ 231 /* We're not going to care if "*ppos" has high bits set */
247 pos = arg_start + *ppos;
248
249 /* .. but we do check the result is in the proper range */ 232 /* .. but we do check the result is in the proper range */
250 if (pos < arg_start || pos >= env_end) 233 pos = arg_start + *ppos;
234 if (pos < arg_start || pos >= arg_end)
251 return 0; 235 return 0;
252 236 if (count > arg_end - pos)
253 /* .. and we never go past env_end */ 237 count = arg_end - pos;
254 if (env_end - pos < count)
255 count = env_end - pos;
256 238
257 page = (char *)__get_free_page(GFP_KERNEL); 239 page = (char *)__get_free_page(GFP_KERNEL);
258 if (!page) 240 if (!page)
@@ -262,48 +244,11 @@ static ssize_t get_mm_cmdline(struct mm_struct *mm, char __user *buf,
262 while (count) { 244 while (count) {
263 int got; 245 int got;
264 size_t size = min_t(size_t, PAGE_SIZE, count); 246 size_t size = min_t(size_t, PAGE_SIZE, count);
265 long offset;
266 247
267 /* 248 got = access_remote_vm(mm, pos, page, size, FOLL_ANON);
268 * Are we already starting past the official end? 249 if (got <= 0)
269 * We always include the last byte that is *supposed*
270 * to be NUL
271 */
272 offset = (pos >= arg_end) ? pos - arg_end + 1 : 0;
273
274 got = access_remote_vm(mm, pos - offset, page, size + offset, FOLL_ANON);
275 if (got <= offset)
276 break; 250 break;
277 got -= offset; 251 got -= copy_to_user(buf, page, got);
278
279 /* Don't walk past a NUL character once you hit arg_end */
280 if (pos + got >= arg_end) {
281 int n = 0;
282
283 /*
284 * If we started before 'arg_end' but ended up
285 * at or after it, we start the NUL character
286 * check at arg_end-1 (where we expect the normal
287 * EOF to be).
288 *
289 * NOTE! This is smaller than 'got', because
290 * pos + got >= arg_end
291 */
292 if (pos < arg_end)
293 n = arg_end - pos - 1;
294
295 /* Cut off at first NUL after 'n' */
296 got = n + strnlen(page+n, offset+got-n);
297 if (got < offset)
298 break;
299 got -= offset;
300
301 /* Include the NUL if it existed */
302 if (got < size)
303 got++;
304 }
305
306 got -= copy_to_user(buf, page+offset, got);
307 if (unlikely(!got)) { 252 if (unlikely(!got)) {
308 if (!len) 253 if (!len)
309 len = -EFAULT; 254 len = -EFAULT;