diff options
author | Jeff Layton <jlayton@redhat.com> | 2012-10-10 15:25:28 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-10-12 20:14:55 -0400 |
commit | 91a27b2a756784714e924e5e854b919273082d26 (patch) | |
tree | 3913246b7d6e62703ec915f481e3a7159393f0f0 | |
parent | 8e377d15078a501c4da98471f56396343c407d92 (diff) |
vfs: define struct filename and have getname() return it
getname() is intended to copy pathname strings from userspace into a
kernel buffer. The result is just a string in kernel space. It would
however be quite helpful to be able to attach some ancillary info to
the string.
For instance, we could attach some audit-related info to reduce the
amount of audit-related processing needed. When auditing is enabled,
we could also call getname() on the string more than once and not
need to recopy it from userspace.
This patchset converts the getname()/putname() interfaces to return
a struct instead of a string. For now, the struct just tracks the
string in kernel space and the original userland pointer for it.
Later, we'll add other information to the struct as it becomes
convenient.
Signed-off-by: Jeff Layton <jlayton@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
40 files changed, 218 insertions, 175 deletions
diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index 63e77e3944ce..9eb090582cf1 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c | |||
@@ -449,7 +449,7 @@ osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags) | |||
449 | { | 449 | { |
450 | int retval; | 450 | int retval; |
451 | struct cdfs_args tmp; | 451 | struct cdfs_args tmp; |
452 | char *devname; | 452 | struct filename *devname; |
453 | 453 | ||
454 | retval = -EFAULT; | 454 | retval = -EFAULT; |
455 | if (copy_from_user(&tmp, args, sizeof(tmp))) | 455 | if (copy_from_user(&tmp, args, sizeof(tmp))) |
@@ -458,7 +458,7 @@ osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags) | |||
458 | retval = PTR_ERR(devname); | 458 | retval = PTR_ERR(devname); |
459 | if (IS_ERR(devname)) | 459 | if (IS_ERR(devname)) |
460 | goto out; | 460 | goto out; |
461 | retval = do_mount(devname, dirname, "ext2", flags, NULL); | 461 | retval = do_mount(devname->name, dirname, "ext2", flags, NULL); |
462 | putname(devname); | 462 | putname(devname); |
463 | out: | 463 | out: |
464 | return retval; | 464 | return retval; |
@@ -469,7 +469,7 @@ osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags) | |||
469 | { | 469 | { |
470 | int retval; | 470 | int retval; |
471 | struct cdfs_args tmp; | 471 | struct cdfs_args tmp; |
472 | char *devname; | 472 | struct filename *devname; |
473 | 473 | ||
474 | retval = -EFAULT; | 474 | retval = -EFAULT; |
475 | if (copy_from_user(&tmp, args, sizeof(tmp))) | 475 | if (copy_from_user(&tmp, args, sizeof(tmp))) |
@@ -478,7 +478,7 @@ osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags) | |||
478 | retval = PTR_ERR(devname); | 478 | retval = PTR_ERR(devname); |
479 | if (IS_ERR(devname)) | 479 | if (IS_ERR(devname)) |
480 | goto out; | 480 | goto out; |
481 | retval = do_mount(devname, dirname, "iso9660", flags, NULL); | 481 | retval = do_mount(devname->name, dirname, "iso9660", flags, NULL); |
482 | putname(devname); | 482 | putname(devname); |
483 | out: | 483 | out: |
484 | return retval; | 484 | return retval; |
@@ -499,7 +499,7 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, const char __user *, path, | |||
499 | int, flag, void __user *, data) | 499 | int, flag, void __user *, data) |
500 | { | 500 | { |
501 | int retval; | 501 | int retval; |
502 | char *name; | 502 | struct filename *name; |
503 | 503 | ||
504 | name = getname(path); | 504 | name = getname(path); |
505 | retval = PTR_ERR(name); | 505 | retval = PTR_ERR(name); |
@@ -507,13 +507,13 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, const char __user *, path, | |||
507 | goto out; | 507 | goto out; |
508 | switch (typenr) { | 508 | switch (typenr) { |
509 | case 1: | 509 | case 1: |
510 | retval = osf_ufs_mount(name, data, flag); | 510 | retval = osf_ufs_mount(name->name, data, flag); |
511 | break; | 511 | break; |
512 | case 6: | 512 | case 6: |
513 | retval = osf_cdfs_mount(name, data, flag); | 513 | retval = osf_cdfs_mount(name->name, data, flag); |
514 | break; | 514 | break; |
515 | case 9: | 515 | case 9: |
516 | retval = osf_procfs_mount(name, data, flag); | 516 | retval = osf_procfs_mount(name->name, data, flag); |
517 | break; | 517 | break; |
518 | default: | 518 | default: |
519 | retval = -EINVAL; | 519 | retval = -EINVAL; |
diff --git a/arch/arm64/kernel/sys.c b/arch/arm64/kernel/sys.c index 905fcfb0ddd0..b120df37de35 100644 --- a/arch/arm64/kernel/sys.c +++ b/arch/arm64/kernel/sys.c | |||
@@ -50,13 +50,13 @@ asmlinkage long sys_execve(const char __user *filenamei, | |||
50 | struct pt_regs *regs) | 50 | struct pt_regs *regs) |
51 | { | 51 | { |
52 | long error; | 52 | long error; |
53 | char * filename; | 53 | struct filename *filename; |
54 | 54 | ||
55 | filename = getname(filenamei); | 55 | filename = getname(filenamei); |
56 | error = PTR_ERR(filename); | 56 | error = PTR_ERR(filename); |
57 | if (IS_ERR(filename)) | 57 | if (IS_ERR(filename)) |
58 | goto out; | 58 | goto out; |
59 | error = do_execve(filename, argv, envp, regs); | 59 | error = do_execve(filename->name, argv, envp, regs); |
60 | putname(filename); | 60 | putname(filename); |
61 | out: | 61 | out: |
62 | return error; | 62 | return error; |
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c index 93f10e27dc79..e521087cb0c4 100644 --- a/arch/arm64/kernel/sys_compat.c +++ b/arch/arm64/kernel/sys_compat.c | |||
@@ -56,14 +56,14 @@ asmlinkage int compat_sys_execve(const char __user *filenamei, | |||
56 | struct pt_regs *regs) | 56 | struct pt_regs *regs) |
57 | { | 57 | { |
58 | int error; | 58 | int error; |
59 | char * filename; | 59 | struct filename *filename; |
60 | 60 | ||
61 | filename = getname(filenamei); | 61 | filename = getname(filenamei); |
62 | error = PTR_ERR(filename); | 62 | error = PTR_ERR(filename); |
63 | if (IS_ERR(filename)) | 63 | if (IS_ERR(filename)) |
64 | goto out; | 64 | goto out; |
65 | error = compat_do_execve(filename, compat_ptr(argv), compat_ptr(envp), | 65 | error = compat_do_execve(filename->name, compat_ptr(argv), |
66 | regs); | 66 | compat_ptr(envp), regs); |
67 | putname(filename); | 67 | putname(filename); |
68 | out: | 68 | out: |
69 | return error; | 69 | return error; |
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c index 92c5af98a6f7..1bb0a8abd79b 100644 --- a/arch/avr32/kernel/process.c +++ b/arch/avr32/kernel/process.c | |||
@@ -388,14 +388,14 @@ asmlinkage int sys_execve(const char __user *ufilename, | |||
388 | struct pt_regs *regs) | 388 | struct pt_regs *regs) |
389 | { | 389 | { |
390 | int error; | 390 | int error; |
391 | char *filename; | 391 | struct filename *filename; |
392 | 392 | ||
393 | filename = getname(ufilename); | 393 | filename = getname(ufilename); |
394 | error = PTR_ERR(filename); | 394 | error = PTR_ERR(filename); |
395 | if (IS_ERR(filename)) | 395 | if (IS_ERR(filename)) |
396 | goto out; | 396 | goto out; |
397 | 397 | ||
398 | error = do_execve(filename, uargv, uenvp, regs); | 398 | error = do_execve(filename->name, uargv, uenvp, regs); |
399 | putname(filename); | 399 | putname(filename); |
400 | 400 | ||
401 | out: | 401 | out: |
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c index 62bcea7dcc6d..bb1cc721fcf7 100644 --- a/arch/blackfin/kernel/process.c +++ b/arch/blackfin/kernel/process.c | |||
@@ -213,14 +213,14 @@ asmlinkage int sys_execve(const char __user *name, | |||
213 | const char __user *const __user *envp) | 213 | const char __user *const __user *envp) |
214 | { | 214 | { |
215 | int error; | 215 | int error; |
216 | char *filename; | 216 | struct filename *filename; |
217 | struct pt_regs *regs = (struct pt_regs *)((&name) + 6); | 217 | struct pt_regs *regs = (struct pt_regs *)((&name) + 6); |
218 | 218 | ||
219 | filename = getname(name); | 219 | filename = getname(name); |
220 | error = PTR_ERR(filename); | 220 | error = PTR_ERR(filename); |
221 | if (IS_ERR(filename)) | 221 | if (IS_ERR(filename)) |
222 | return error; | 222 | return error; |
223 | error = do_execve(filename, argv, envp, regs); | 223 | error = do_execve(filename->name, argv, envp, regs); |
224 | putname(filename); | 224 | putname(filename); |
225 | return error; | 225 | return error; |
226 | } | 226 | } |
diff --git a/arch/cris/arch-v10/kernel/process.c b/arch/cris/arch-v10/kernel/process.c index bee8df43c201..15ac7150371f 100644 --- a/arch/cris/arch-v10/kernel/process.c +++ b/arch/cris/arch-v10/kernel/process.c | |||
@@ -212,14 +212,14 @@ asmlinkage int sys_execve(const char *fname, | |||
212 | struct pt_regs *regs) | 212 | struct pt_regs *regs) |
213 | { | 213 | { |
214 | int error; | 214 | int error; |
215 | char *filename; | 215 | struct filename *filename; |
216 | 216 | ||
217 | filename = getname(fname); | 217 | filename = getname(fname); |
218 | error = PTR_ERR(filename); | 218 | error = PTR_ERR(filename); |
219 | 219 | ||
220 | if (IS_ERR(filename)) | 220 | if (IS_ERR(filename)) |
221 | goto out; | 221 | goto out; |
222 | error = do_execve(filename, argv, envp, regs); | 222 | error = do_execve(filename->name, argv, envp, regs); |
223 | putname(filename); | 223 | putname(filename); |
224 | out: | 224 | out: |
225 | return error; | 225 | return error; |
diff --git a/arch/cris/arch-v32/kernel/process.c b/arch/cris/arch-v32/kernel/process.c index 0570e8ce603d..4e9992246359 100644 --- a/arch/cris/arch-v32/kernel/process.c +++ b/arch/cris/arch-v32/kernel/process.c | |||
@@ -224,7 +224,7 @@ sys_execve(const char *fname, | |||
224 | struct pt_regs *regs) | 224 | struct pt_regs *regs) |
225 | { | 225 | { |
226 | int error; | 226 | int error; |
227 | char *filename; | 227 | struct filename *filename; |
228 | 228 | ||
229 | filename = getname(fname); | 229 | filename = getname(fname); |
230 | error = PTR_ERR(filename); | 230 | error = PTR_ERR(filename); |
@@ -232,7 +232,7 @@ sys_execve(const char *fname, | |||
232 | if (IS_ERR(filename)) | 232 | if (IS_ERR(filename)) |
233 | goto out; | 233 | goto out; |
234 | 234 | ||
235 | error = do_execve(filename, argv, envp, regs); | 235 | error = do_execve(filename->name, argv, envp, regs); |
236 | putname(filename); | 236 | putname(filename); |
237 | out: | 237 | out: |
238 | return error; | 238 | return error; |
diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c index f153ed1a4c08..e8dc1393a13a 100644 --- a/arch/h8300/kernel/process.c +++ b/arch/h8300/kernel/process.c | |||
@@ -217,14 +217,14 @@ asmlinkage int sys_execve(const char *name, | |||
217 | int dummy, ...) | 217 | int dummy, ...) |
218 | { | 218 | { |
219 | int error; | 219 | int error; |
220 | char * filename; | 220 | struct filename *filename; |
221 | struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4); | 221 | struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4); |
222 | 222 | ||
223 | filename = getname(name); | 223 | filename = getname(name); |
224 | error = PTR_ERR(filename); | 224 | error = PTR_ERR(filename); |
225 | if (IS_ERR(filename)) | 225 | if (IS_ERR(filename)) |
226 | return error; | 226 | return error; |
227 | error = do_execve(filename, argv, envp, regs); | 227 | error = do_execve(filename->name, argv, envp, regs); |
228 | putname(filename); | 228 | putname(filename); |
229 | return error; | 229 | return error; |
230 | } | 230 | } |
diff --git a/arch/hexagon/kernel/syscall.c b/arch/hexagon/kernel/syscall.c index 553cd60ee659..25a9bfe3445d 100644 --- a/arch/hexagon/kernel/syscall.c +++ b/arch/hexagon/kernel/syscall.c | |||
@@ -40,7 +40,7 @@ asmlinkage int sys_execve(char __user *ufilename, | |||
40 | const char __user *const __user *envp) | 40 | const char __user *const __user *envp) |
41 | { | 41 | { |
42 | struct pt_regs *pregs = current_thread_info()->regs; | 42 | struct pt_regs *pregs = current_thread_info()->regs; |
43 | char *filename; | 43 | struct filename *filename; |
44 | int retval; | 44 | int retval; |
45 | 45 | ||
46 | filename = getname(ufilename); | 46 | filename = getname(ufilename); |
@@ -48,7 +48,7 @@ asmlinkage int sys_execve(char __user *ufilename, | |||
48 | if (IS_ERR(filename)) | 48 | if (IS_ERR(filename)) |
49 | return retval; | 49 | return retval; |
50 | 50 | ||
51 | retval = do_execve(filename, argv, envp, pregs); | 51 | retval = do_execve(filename->name, argv, envp, pregs); |
52 | putname(filename); | 52 | putname(filename); |
53 | 53 | ||
54 | return retval; | 54 | return retval; |
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index ee31fe9b310e..35e106f2ed13 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c | |||
@@ -614,14 +614,14 @@ sys_execve (const char __user *filename, | |||
614 | const char __user *const __user *envp, | 614 | const char __user *const __user *envp, |
615 | struct pt_regs *regs) | 615 | struct pt_regs *regs) |
616 | { | 616 | { |
617 | char *fname; | 617 | struct filename *fname; |
618 | int error; | 618 | int error; |
619 | 619 | ||
620 | fname = getname(filename); | 620 | fname = getname(filename); |
621 | error = PTR_ERR(fname); | 621 | error = PTR_ERR(fname); |
622 | if (IS_ERR(fname)) | 622 | if (IS_ERR(fname)) |
623 | goto out; | 623 | goto out; |
624 | error = do_execve(fname, argv, envp, regs); | 624 | error = do_execve(fname->name, argv, envp, regs); |
625 | putname(fname); | 625 | putname(fname); |
626 | out: | 626 | out: |
627 | return error; | 627 | return error; |
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c index 384e63f3a4c4..e7366276ef30 100644 --- a/arch/m32r/kernel/process.c +++ b/arch/m32r/kernel/process.c | |||
@@ -296,14 +296,14 @@ asmlinkage int sys_execve(const char __user *ufilename, | |||
296 | unsigned long r6, struct pt_regs regs) | 296 | unsigned long r6, struct pt_regs regs) |
297 | { | 297 | { |
298 | int error; | 298 | int error; |
299 | char *filename; | 299 | struct filename *filename; |
300 | 300 | ||
301 | filename = getname(ufilename); | 301 | filename = getname(ufilename); |
302 | error = PTR_ERR(filename); | 302 | error = PTR_ERR(filename); |
303 | if (IS_ERR(filename)) | 303 | if (IS_ERR(filename)) |
304 | goto out; | 304 | goto out; |
305 | 305 | ||
306 | error = do_execve(filename, uargv, uenvp, ®s); | 306 | error = do_execve(filename->name, uargv, uenvp, ®s); |
307 | putname(filename); | 307 | putname(filename); |
308 | out: | 308 | out: |
309 | return error; | 309 | return error; |
diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c index e5b154f24f85..404c0f24bd41 100644 --- a/arch/microblaze/kernel/sys_microblaze.c +++ b/arch/microblaze/kernel/sys_microblaze.c | |||
@@ -54,13 +54,13 @@ asmlinkage long microblaze_execve(const char __user *filenamei, | |||
54 | struct pt_regs *regs) | 54 | struct pt_regs *regs) |
55 | { | 55 | { |
56 | int error; | 56 | int error; |
57 | char *filename; | 57 | struct filename *filename; |
58 | 58 | ||
59 | filename = getname(filenamei); | 59 | filename = getname(filenamei); |
60 | error = PTR_ERR(filename); | 60 | error = PTR_ERR(filename); |
61 | if (IS_ERR(filename)) | 61 | if (IS_ERR(filename)) |
62 | goto out; | 62 | goto out; |
63 | error = do_execve(filename, argv, envp, regs); | 63 | error = do_execve(filename->name, argv, envp, regs); |
64 | putname(filename); | 64 | putname(filename); |
65 | out: | 65 | out: |
66 | return error; | 66 | return error; |
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 922a554cd108..3a21acedf882 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c | |||
@@ -83,13 +83,13 @@ out: | |||
83 | asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs) | 83 | asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs) |
84 | { | 84 | { |
85 | int error; | 85 | int error; |
86 | char * filename; | 86 | struct filename *filename; |
87 | 87 | ||
88 | filename = getname(compat_ptr(regs.regs[4])); | 88 | filename = getname(compat_ptr(regs.regs[4])); |
89 | error = PTR_ERR(filename); | 89 | error = PTR_ERR(filename); |
90 | if (IS_ERR(filename)) | 90 | if (IS_ERR(filename)) |
91 | goto out; | 91 | goto out; |
92 | error = compat_do_execve(filename, compat_ptr(regs.regs[5]), | 92 | error = compat_do_execve(filename->name, compat_ptr(regs.regs[5]), |
93 | compat_ptr(regs.regs[6]), ®s); | 93 | compat_ptr(regs.regs[6]), ®s); |
94 | putname(filename); | 94 | putname(filename); |
95 | 95 | ||
diff --git a/arch/mips/kernel/syscall.c b/arch/mips/kernel/syscall.c index b08220c82113..2bd561bc05ae 100644 --- a/arch/mips/kernel/syscall.c +++ b/arch/mips/kernel/syscall.c | |||
@@ -133,13 +133,13 @@ _sys_clone(nabi_no_regargs struct pt_regs regs) | |||
133 | asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs) | 133 | asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs) |
134 | { | 134 | { |
135 | int error; | 135 | int error; |
136 | char * filename; | 136 | struct filename *filename; |
137 | 137 | ||
138 | filename = getname((const char __user *) (long)regs.regs[4]); | 138 | filename = getname((const char __user *) (long)regs.regs[4]); |
139 | error = PTR_ERR(filename); | 139 | error = PTR_ERR(filename); |
140 | if (IS_ERR(filename)) | 140 | if (IS_ERR(filename)) |
141 | goto out; | 141 | goto out; |
142 | error = do_execve(filename, | 142 | error = do_execve(filename->name, |
143 | (const char __user *const __user *) (long)regs.regs[5], | 143 | (const char __user *const __user *) (long)regs.regs[5], |
144 | (const char __user *const __user *) (long)regs.regs[6], | 144 | (const char __user *const __user *) (long)regs.regs[6], |
145 | ®s); | 145 | ®s); |
diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c index 55210f37d1a3..c35f3ab1a8d3 100644 --- a/arch/openrisc/kernel/process.c +++ b/arch/openrisc/kernel/process.c | |||
@@ -271,7 +271,7 @@ asmlinkage long _sys_execve(const char __user *name, | |||
271 | struct pt_regs *regs) | 271 | struct pt_regs *regs) |
272 | { | 272 | { |
273 | int error; | 273 | int error; |
274 | char *filename; | 274 | struct filename *filename; |
275 | 275 | ||
276 | filename = getname(name); | 276 | filename = getname(name); |
277 | error = PTR_ERR(filename); | 277 | error = PTR_ERR(filename); |
@@ -279,7 +279,7 @@ asmlinkage long _sys_execve(const char __user *name, | |||
279 | if (IS_ERR(filename)) | 279 | if (IS_ERR(filename)) |
280 | goto out; | 280 | goto out; |
281 | 281 | ||
282 | error = do_execve(filename, argv, envp, regs); | 282 | error = do_execve(filename->name, argv, envp, regs); |
283 | putname(filename); | 283 | putname(filename); |
284 | 284 | ||
285 | out: | 285 | out: |
diff --git a/arch/parisc/hpux/fs.c b/arch/parisc/hpux/fs.c index 6785de7bd2a0..a0760b87fd4e 100644 --- a/arch/parisc/hpux/fs.c +++ b/arch/parisc/hpux/fs.c | |||
@@ -34,14 +34,14 @@ | |||
34 | int hpux_execve(struct pt_regs *regs) | 34 | int hpux_execve(struct pt_regs *regs) |
35 | { | 35 | { |
36 | int error; | 36 | int error; |
37 | char *filename; | 37 | struct filename *filename; |
38 | 38 | ||
39 | filename = getname((const char __user *) regs->gr[26]); | 39 | filename = getname((const char __user *) regs->gr[26]); |
40 | error = PTR_ERR(filename); | 40 | error = PTR_ERR(filename); |
41 | if (IS_ERR(filename)) | 41 | if (IS_ERR(filename)) |
42 | goto out; | 42 | goto out; |
43 | 43 | ||
44 | error = do_execve(filename, | 44 | error = do_execve(filename->name, |
45 | (const char __user *const __user *) regs->gr[25], | 45 | (const char __user *const __user *) regs->gr[25], |
46 | (const char __user *const __user *) regs->gr[24], | 46 | (const char __user *const __user *) regs->gr[24], |
47 | regs); | 47 | regs); |
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c index 8c6b6b6561f0..cbc37216bf90 100644 --- a/arch/parisc/kernel/process.c +++ b/arch/parisc/kernel/process.c | |||
@@ -342,13 +342,13 @@ unsigned long thread_saved_pc(struct task_struct *t) | |||
342 | asmlinkage int sys_execve(struct pt_regs *regs) | 342 | asmlinkage int sys_execve(struct pt_regs *regs) |
343 | { | 343 | { |
344 | int error; | 344 | int error; |
345 | char *filename; | 345 | struct filename *filename; |
346 | 346 | ||
347 | filename = getname((const char __user *) regs->gr[26]); | 347 | filename = getname((const char __user *) regs->gr[26]); |
348 | error = PTR_ERR(filename); | 348 | error = PTR_ERR(filename); |
349 | if (IS_ERR(filename)) | 349 | if (IS_ERR(filename)) |
350 | goto out; | 350 | goto out; |
351 | error = do_execve(filename, | 351 | error = do_execve(filename->name, |
352 | (const char __user *const __user *) regs->gr[25], | 352 | (const char __user *const __user *) regs->gr[25], |
353 | (const char __user *const __user *) regs->gr[24], | 353 | (const char __user *const __user *) regs->gr[24], |
354 | regs); | 354 | regs); |
diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c index dc9a62462323..bf5b93a885d3 100644 --- a/arch/parisc/kernel/sys_parisc32.c +++ b/arch/parisc/kernel/sys_parisc32.c | |||
@@ -60,14 +60,14 @@ | |||
60 | asmlinkage int sys32_execve(struct pt_regs *regs) | 60 | asmlinkage int sys32_execve(struct pt_regs *regs) |
61 | { | 61 | { |
62 | int error; | 62 | int error; |
63 | char *filename; | 63 | struct filename *filename; |
64 | 64 | ||
65 | DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26])); | 65 | DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26])); |
66 | filename = getname((const char __user *) regs->gr[26]); | 66 | filename = getname((const char __user *) regs->gr[26]); |
67 | error = PTR_ERR(filename); | 67 | error = PTR_ERR(filename); |
68 | if (IS_ERR(filename)) | 68 | if (IS_ERR(filename)) |
69 | goto out; | 69 | goto out; |
70 | error = compat_do_execve(filename, compat_ptr(regs->gr[25]), | 70 | error = compat_do_execve(filename->name, compat_ptr(regs->gr[25]), |
71 | compat_ptr(regs->gr[24]), regs); | 71 | compat_ptr(regs->gr[24]), regs); |
72 | putname(filename); | 72 | putname(filename); |
73 | out: | 73 | out: |
diff --git a/arch/score/kernel/sys_score.c b/arch/score/kernel/sys_score.c index 21e867974066..d45cf00a3351 100644 --- a/arch/score/kernel/sys_score.c +++ b/arch/score/kernel/sys_score.c | |||
@@ -92,14 +92,14 @@ asmlinkage long | |||
92 | score_execve(struct pt_regs *regs) | 92 | score_execve(struct pt_regs *regs) |
93 | { | 93 | { |
94 | int error; | 94 | int error; |
95 | char *filename; | 95 | struct filename *filename; |
96 | 96 | ||
97 | filename = getname((char __user*)regs->regs[4]); | 97 | filename = getname((char __user*)regs->regs[4]); |
98 | error = PTR_ERR(filename); | 98 | error = PTR_ERR(filename); |
99 | if (IS_ERR(filename)) | 99 | if (IS_ERR(filename)) |
100 | return error; | 100 | return error; |
101 | 101 | ||
102 | error = do_execve(filename, | 102 | error = do_execve(filename->name, |
103 | (const char __user *const __user *)regs->regs[5], | 103 | (const char __user *const __user *)regs->regs[5], |
104 | (const char __user *const __user *)regs->regs[6], | 104 | (const char __user *const __user *)regs->regs[6], |
105 | regs); | 105 | regs); |
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index 59521e8a164d..ba7345f37bc9 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c | |||
@@ -298,14 +298,14 @@ asmlinkage int sys_execve(const char __user *ufilename, | |||
298 | { | 298 | { |
299 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); | 299 | struct pt_regs *regs = RELOC_HIDE(&__regs, 0); |
300 | int error; | 300 | int error; |
301 | char *filename; | 301 | struct filename *filename; |
302 | 302 | ||
303 | filename = getname(ufilename); | 303 | filename = getname(ufilename); |
304 | error = PTR_ERR(filename); | 304 | error = PTR_ERR(filename); |
305 | if (IS_ERR(filename)) | 305 | if (IS_ERR(filename)) |
306 | goto out; | 306 | goto out; |
307 | 307 | ||
308 | error = do_execve(filename, uargv, uenvp, regs); | 308 | error = do_execve(filename->name, uargv, uenvp, regs); |
309 | putname(filename); | 309 | putname(filename); |
310 | out: | 310 | out: |
311 | return error; | 311 | return error; |
diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c index 602545b12a86..98a709f0c3c4 100644 --- a/arch/sh/kernel/process_64.c +++ b/arch/sh/kernel/process_64.c | |||
@@ -491,14 +491,14 @@ asmlinkage int sys_execve(const char *ufilename, char **uargv, | |||
491 | struct pt_regs *pregs) | 491 | struct pt_regs *pregs) |
492 | { | 492 | { |
493 | int error; | 493 | int error; |
494 | char *filename; | 494 | struct filename *filename; |
495 | 495 | ||
496 | filename = getname((char __user *)ufilename); | 496 | filename = getname((char __user *)ufilename); |
497 | error = PTR_ERR(filename); | 497 | error = PTR_ERR(filename); |
498 | if (IS_ERR(filename)) | 498 | if (IS_ERR(filename)) |
499 | goto out; | 499 | goto out; |
500 | 500 | ||
501 | error = do_execve(filename, | 501 | error = do_execve(filename->name, |
502 | (const char __user *const __user *)uargv, | 502 | (const char __user *const __user *)uargv, |
503 | (const char __user *const __user *)uenvp, | 503 | (const char __user *const __user *)uenvp, |
504 | pregs); | 504 | pregs); |
diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c index 14006d8aca28..487bffb36f5e 100644 --- a/arch/sparc/kernel/process_32.c +++ b/arch/sparc/kernel/process_32.c | |||
@@ -482,7 +482,7 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs) | |||
482 | asmlinkage int sparc_execve(struct pt_regs *regs) | 482 | asmlinkage int sparc_execve(struct pt_regs *regs) |
483 | { | 483 | { |
484 | int error, base = 0; | 484 | int error, base = 0; |
485 | char *filename; | 485 | struct filename *filename; |
486 | 486 | ||
487 | /* Check for indirect call. */ | 487 | /* Check for indirect call. */ |
488 | if(regs->u_regs[UREG_G1] == 0) | 488 | if(regs->u_regs[UREG_G1] == 0) |
@@ -492,7 +492,7 @@ asmlinkage int sparc_execve(struct pt_regs *regs) | |||
492 | error = PTR_ERR(filename); | 492 | error = PTR_ERR(filename); |
493 | if(IS_ERR(filename)) | 493 | if(IS_ERR(filename)) |
494 | goto out; | 494 | goto out; |
495 | error = do_execve(filename, | 495 | error = do_execve(filename->name, |
496 | (const char __user *const __user *) | 496 | (const char __user *const __user *) |
497 | regs->u_regs[base + UREG_I1], | 497 | regs->u_regs[base + UREG_I1], |
498 | (const char __user *const __user *) | 498 | (const char __user *const __user *) |
diff --git a/arch/sparc/kernel/process_64.c b/arch/sparc/kernel/process_64.c index aff0c72fac09..fcaa59421126 100644 --- a/arch/sparc/kernel/process_64.c +++ b/arch/sparc/kernel/process_64.c | |||
@@ -722,7 +722,7 @@ EXPORT_SYMBOL(dump_fpu); | |||
722 | asmlinkage int sparc_execve(struct pt_regs *regs) | 722 | asmlinkage int sparc_execve(struct pt_regs *regs) |
723 | { | 723 | { |
724 | int error, base = 0; | 724 | int error, base = 0; |
725 | char *filename; | 725 | struct filename *filename; |
726 | 726 | ||
727 | /* User register window flush is done by entry.S */ | 727 | /* User register window flush is done by entry.S */ |
728 | 728 | ||
@@ -734,7 +734,7 @@ asmlinkage int sparc_execve(struct pt_regs *regs) | |||
734 | error = PTR_ERR(filename); | 734 | error = PTR_ERR(filename); |
735 | if (IS_ERR(filename)) | 735 | if (IS_ERR(filename)) |
736 | goto out; | 736 | goto out; |
737 | error = do_execve(filename, | 737 | error = do_execve(filename->name, |
738 | (const char __user *const __user *) | 738 | (const char __user *const __user *) |
739 | regs->u_regs[base + UREG_I1], | 739 | regs->u_regs[base + UREG_I1], |
740 | (const char __user *const __user *) | 740 | (const char __user *const __user *) |
diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c index d862499eb01c..c3239811a1b5 100644 --- a/arch/sparc/kernel/sys_sparc32.c +++ b/arch/sparc/kernel/sys_sparc32.c | |||
@@ -403,7 +403,7 @@ asmlinkage long compat_sys_rt_sigaction(int sig, | |||
403 | asmlinkage long sparc32_execve(struct pt_regs *regs) | 403 | asmlinkage long sparc32_execve(struct pt_regs *regs) |
404 | { | 404 | { |
405 | int error, base = 0; | 405 | int error, base = 0; |
406 | char *filename; | 406 | struct filename *filename; |
407 | 407 | ||
408 | /* User register window flush is done by entry.S */ | 408 | /* User register window flush is done by entry.S */ |
409 | 409 | ||
@@ -416,7 +416,7 @@ asmlinkage long sparc32_execve(struct pt_regs *regs) | |||
416 | if (IS_ERR(filename)) | 416 | if (IS_ERR(filename)) |
417 | goto out; | 417 | goto out; |
418 | 418 | ||
419 | error = compat_do_execve(filename, | 419 | error = compat_do_execve(filename->name, |
420 | compat_ptr(regs->u_regs[base + UREG_I1]), | 420 | compat_ptr(regs->u_regs[base + UREG_I1]), |
421 | compat_ptr(regs->u_regs[base + UREG_I2]), regs); | 421 | compat_ptr(regs->u_regs[base + UREG_I2]), regs); |
422 | 422 | ||
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c index 6be799150501..622560030a58 100644 --- a/arch/tile/kernel/process.c +++ b/arch/tile/kernel/process.c | |||
@@ -594,13 +594,13 @@ SYSCALL_DEFINE4(execve, const char __user *, path, | |||
594 | struct pt_regs *, regs) | 594 | struct pt_regs *, regs) |
595 | { | 595 | { |
596 | long error; | 596 | long error; |
597 | char *filename; | 597 | struct filename *filename; |
598 | 598 | ||
599 | filename = getname(path); | 599 | filename = getname(path); |
600 | error = PTR_ERR(filename); | 600 | error = PTR_ERR(filename); |
601 | if (IS_ERR(filename)) | 601 | if (IS_ERR(filename)) |
602 | goto out; | 602 | goto out; |
603 | error = do_execve(filename, argv, envp, regs); | 603 | error = do_execve(filename->name, argv, envp, regs); |
604 | putname(filename); | 604 | putname(filename); |
605 | if (error == 0) | 605 | if (error == 0) |
606 | single_step_execve(); | 606 | single_step_execve(); |
@@ -615,13 +615,13 @@ long compat_sys_execve(const char __user *path, | |||
615 | struct pt_regs *regs) | 615 | struct pt_regs *regs) |
616 | { | 616 | { |
617 | long error; | 617 | long error; |
618 | char *filename; | 618 | struct filename *filename; |
619 | 619 | ||
620 | filename = getname(path); | 620 | filename = getname(path); |
621 | error = PTR_ERR(filename); | 621 | error = PTR_ERR(filename); |
622 | if (IS_ERR(filename)) | 622 | if (IS_ERR(filename)) |
623 | goto out; | 623 | goto out; |
624 | error = compat_do_execve(filename, argv, envp, regs); | 624 | error = compat_do_execve(filename->name, argv, envp, regs); |
625 | putname(filename); | 625 | putname(filename); |
626 | if (error == 0) | 626 | if (error == 0) |
627 | single_step_execve(); | 627 | single_step_execve(); |
diff --git a/arch/unicore32/kernel/sys.c b/arch/unicore32/kernel/sys.c index 5fd9af773e15..fabdee96110b 100644 --- a/arch/unicore32/kernel/sys.c +++ b/arch/unicore32/kernel/sys.c | |||
@@ -51,13 +51,13 @@ asmlinkage long __sys_execve(const char __user *filename, | |||
51 | struct pt_regs *regs) | 51 | struct pt_regs *regs) |
52 | { | 52 | { |
53 | int error; | 53 | int error; |
54 | char *fn; | 54 | struct filename *fn; |
55 | 55 | ||
56 | fn = getname(filename); | 56 | fn = getname(filename); |
57 | error = PTR_ERR(fn); | 57 | error = PTR_ERR(fn); |
58 | if (IS_ERR(fn)) | 58 | if (IS_ERR(fn)) |
59 | goto out; | 59 | goto out; |
60 | error = do_execve(fn, argv, envp, regs); | 60 | error = do_execve(fn->name, argv, envp, regs); |
61 | putname(fn); | 61 | putname(fn); |
62 | out: | 62 | out: |
63 | return error; | 63 | return error; |
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index bc44311aa18c..bc020825cce5 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c | |||
@@ -328,13 +328,13 @@ long xtensa_execve(const char __user *name, | |||
328 | struct pt_regs *regs) | 328 | struct pt_regs *regs) |
329 | { | 329 | { |
330 | long error; | 330 | long error; |
331 | char * filename; | 331 | struct filename *filename; |
332 | 332 | ||
333 | filename = getname(name); | 333 | filename = getname(name); |
334 | error = PTR_ERR(filename); | 334 | error = PTR_ERR(filename); |
335 | if (IS_ERR(filename)) | 335 | if (IS_ERR(filename)) |
336 | goto out; | 336 | goto out; |
337 | error = do_execve(filename, argv, envp, regs); | 337 | error = do_execve(filename->name, argv, envp, regs); |
338 | putname(filename); | 338 | putname(filename); |
339 | out: | 339 | out: |
340 | return error; | 340 | return error; |
diff --git a/fs/compat.c b/fs/compat.c index b7a24d0ca30d..015e1e1f87c6 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -776,16 +776,16 @@ asmlinkage long compat_sys_mount(const char __user * dev_name, | |||
776 | char *kernel_type; | 776 | char *kernel_type; |
777 | unsigned long data_page; | 777 | unsigned long data_page; |
778 | char *kernel_dev; | 778 | char *kernel_dev; |
779 | char *dir_page; | 779 | struct filename *dir; |
780 | int retval; | 780 | int retval; |
781 | 781 | ||
782 | retval = copy_mount_string(type, &kernel_type); | 782 | retval = copy_mount_string(type, &kernel_type); |
783 | if (retval < 0) | 783 | if (retval < 0) |
784 | goto out; | 784 | goto out; |
785 | 785 | ||
786 | dir_page = getname(dir_name); | 786 | dir = getname(dir_name); |
787 | retval = PTR_ERR(dir_page); | 787 | retval = PTR_ERR(dir); |
788 | if (IS_ERR(dir_page)) | 788 | if (IS_ERR(dir)) |
789 | goto out1; | 789 | goto out1; |
790 | 790 | ||
791 | retval = copy_mount_string(dev_name, &kernel_dev); | 791 | retval = copy_mount_string(dev_name, &kernel_dev); |
@@ -807,7 +807,7 @@ asmlinkage long compat_sys_mount(const char __user * dev_name, | |||
807 | } | 807 | } |
808 | } | 808 | } |
809 | 809 | ||
810 | retval = do_mount(kernel_dev, dir_page, kernel_type, | 810 | retval = do_mount(kernel_dev, dir->name, kernel_type, |
811 | flags, (void*)data_page); | 811 | flags, (void*)data_page); |
812 | 812 | ||
813 | out4: | 813 | out4: |
@@ -815,7 +815,7 @@ asmlinkage long compat_sys_mount(const char __user * dev_name, | |||
815 | out3: | 815 | out3: |
816 | kfree(kernel_dev); | 816 | kfree(kernel_dev); |
817 | out2: | 817 | out2: |
818 | putname(dir_page); | 818 | putname(dir); |
819 | out1: | 819 | out1: |
820 | kfree(kernel_type); | 820 | kfree(kernel_type); |
821 | out: | 821 | out: |
@@ -105,7 +105,7 @@ static inline void put_binfmt(struct linux_binfmt * fmt) | |||
105 | SYSCALL_DEFINE1(uselib, const char __user *, library) | 105 | SYSCALL_DEFINE1(uselib, const char __user *, library) |
106 | { | 106 | { |
107 | struct file *file; | 107 | struct file *file; |
108 | char *tmp = getname(library); | 108 | struct filename *tmp = getname(library); |
109 | int error = PTR_ERR(tmp); | 109 | int error = PTR_ERR(tmp); |
110 | static const struct open_flags uselib_flags = { | 110 | static const struct open_flags uselib_flags = { |
111 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, | 111 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, |
@@ -116,7 +116,7 @@ SYSCALL_DEFINE1(uselib, const char __user *, library) | |||
116 | if (IS_ERR(tmp)) | 116 | if (IS_ERR(tmp)) |
117 | goto out; | 117 | goto out; |
118 | 118 | ||
119 | file = do_filp_open(AT_FDCWD, tmp, &uselib_flags, LOOKUP_FOLLOW); | 119 | file = do_filp_open(AT_FDCWD, tmp->name, &uselib_flags, LOOKUP_FOLLOW); |
120 | putname(tmp); | 120 | putname(tmp); |
121 | error = PTR_ERR(file); | 121 | error = PTR_ERR(file); |
122 | if (IS_ERR(file)) | 122 | if (IS_ERR(file)) |
@@ -1664,10 +1664,10 @@ SYSCALL_DEFINE3(execve, | |||
1664 | const char __user *const __user *, argv, | 1664 | const char __user *const __user *, argv, |
1665 | const char __user *const __user *, envp) | 1665 | const char __user *const __user *, envp) |
1666 | { | 1666 | { |
1667 | const char *path = getname(filename); | 1667 | struct filename *path = getname(filename); |
1668 | int error = PTR_ERR(path); | 1668 | int error = PTR_ERR(path); |
1669 | if (!IS_ERR(path)) { | 1669 | if (!IS_ERR(path)) { |
1670 | error = do_execve(path, argv, envp, current_pt_regs()); | 1670 | error = do_execve(path->name, argv, envp, current_pt_regs()); |
1671 | putname(path); | 1671 | putname(path); |
1672 | } | 1672 | } |
1673 | return error; | 1673 | return error; |
@@ -1677,10 +1677,11 @@ asmlinkage long compat_sys_execve(const char __user * filename, | |||
1677 | const compat_uptr_t __user * argv, | 1677 | const compat_uptr_t __user * argv, |
1678 | const compat_uptr_t __user * envp) | 1678 | const compat_uptr_t __user * envp) |
1679 | { | 1679 | { |
1680 | const char *path = getname(filename); | 1680 | struct filename *path = getname(filename); |
1681 | int error = PTR_ERR(path); | 1681 | int error = PTR_ERR(path); |
1682 | if (!IS_ERR(path)) { | 1682 | if (!IS_ERR(path)) { |
1683 | error = compat_do_execve(path, argv, envp, current_pt_regs()); | 1683 | error = compat_do_execve(path->name, argv, envp, |
1684 | current_pt_regs()); | ||
1684 | putname(path); | 1685 | putname(path); |
1685 | } | 1686 | } |
1686 | return error; | 1687 | return error; |
diff --git a/fs/filesystems.c b/fs/filesystems.c index 96f24286667a..da165f6adcbf 100644 --- a/fs/filesystems.c +++ b/fs/filesystems.c | |||
@@ -124,7 +124,7 @@ EXPORT_SYMBOL(unregister_filesystem); | |||
124 | static int fs_index(const char __user * __name) | 124 | static int fs_index(const char __user * __name) |
125 | { | 125 | { |
126 | struct file_system_type * tmp; | 126 | struct file_system_type * tmp; |
127 | char * name; | 127 | struct filename *name; |
128 | int err, index; | 128 | int err, index; |
129 | 129 | ||
130 | name = getname(__name); | 130 | name = getname(__name); |
@@ -135,7 +135,7 @@ static int fs_index(const char __user * __name) | |||
135 | err = -EINVAL; | 135 | err = -EINVAL; |
136 | read_lock(&file_systems_lock); | 136 | read_lock(&file_systems_lock); |
137 | for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) { | 137 | for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) { |
138 | if (strcmp(tmp->name,name) == 0) { | 138 | if (strcmp(tmp->name, name->name) == 0) { |
139 | err = index; | 139 | err = index; |
140 | break; | 140 | break; |
141 | } | 141 | } |
diff --git a/fs/namei.c b/fs/namei.c index 9cc0fce7fc91..ec638d27642f 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -117,18 +117,37 @@ | |||
117 | * POSIX.1 2.4: an empty pathname is invalid (ENOENT). | 117 | * POSIX.1 2.4: an empty pathname is invalid (ENOENT). |
118 | * PATH_MAX includes the nul terminator --RR. | 118 | * PATH_MAX includes the nul terminator --RR. |
119 | */ | 119 | */ |
120 | static char *getname_flags(const char __user *filename, int flags, int *empty) | 120 | void final_putname(struct filename *name) |
121 | { | 121 | { |
122 | char *result = __getname(), *err; | 122 | __putname(name->name); |
123 | kfree(name); | ||
124 | } | ||
125 | |||
126 | static struct filename * | ||
127 | getname_flags(const char __user *filename, int flags, int *empty) | ||
128 | { | ||
129 | struct filename *result, *err; | ||
130 | char *kname; | ||
123 | int len; | 131 | int len; |
124 | 132 | ||
133 | /* FIXME: create dedicated slabcache? */ | ||
134 | result = kzalloc(sizeof(*result), GFP_KERNEL); | ||
125 | if (unlikely(!result)) | 135 | if (unlikely(!result)) |
126 | return ERR_PTR(-ENOMEM); | 136 | return ERR_PTR(-ENOMEM); |
127 | 137 | ||
128 | len = strncpy_from_user(result, filename, PATH_MAX); | 138 | kname = __getname(); |
129 | err = ERR_PTR(len); | 139 | if (unlikely(!kname)) { |
130 | if (unlikely(len < 0)) | 140 | err = ERR_PTR(-ENOMEM); |
141 | goto error_free_name; | ||
142 | } | ||
143 | |||
144 | result->name = kname; | ||
145 | result->uptr = filename; | ||
146 | len = strncpy_from_user(kname, filename, PATH_MAX); | ||
147 | if (unlikely(len < 0)) { | ||
148 | err = ERR_PTR(len); | ||
131 | goto error; | 149 | goto error; |
150 | } | ||
132 | 151 | ||
133 | /* The empty path is special. */ | 152 | /* The empty path is special. */ |
134 | if (unlikely(!len)) { | 153 | if (unlikely(!len)) { |
@@ -146,22 +165,25 @@ static char *getname_flags(const char __user *filename, int flags, int *empty) | |||
146 | } | 165 | } |
147 | 166 | ||
148 | error: | 167 | error: |
149 | __putname(result); | 168 | __putname(kname); |
169 | error_free_name: | ||
170 | kfree(result); | ||
150 | return err; | 171 | return err; |
151 | } | 172 | } |
152 | 173 | ||
153 | char *getname(const char __user * filename) | 174 | struct filename * |
175 | getname(const char __user * filename) | ||
154 | { | 176 | { |
155 | return getname_flags(filename, 0, NULL); | 177 | return getname_flags(filename, 0, NULL); |
156 | } | 178 | } |
179 | EXPORT_SYMBOL(getname); | ||
157 | 180 | ||
158 | #ifdef CONFIG_AUDITSYSCALL | 181 | #ifdef CONFIG_AUDITSYSCALL |
159 | void putname(const char *name) | 182 | void putname(struct filename *name) |
160 | { | 183 | { |
161 | if (unlikely(!audit_dummy_context())) | 184 | if (unlikely(!audit_dummy_context())) |
162 | audit_putname(name); | 185 | return audit_putname(name); |
163 | else | 186 | final_putname(name); |
164 | __putname(name); | ||
165 | } | 187 | } |
166 | #endif | 188 | #endif |
167 | 189 | ||
@@ -2093,13 +2115,13 @@ int user_path_at_empty(int dfd, const char __user *name, unsigned flags, | |||
2093 | struct path *path, int *empty) | 2115 | struct path *path, int *empty) |
2094 | { | 2116 | { |
2095 | struct nameidata nd; | 2117 | struct nameidata nd; |
2096 | char *tmp = getname_flags(name, flags, empty); | 2118 | struct filename *tmp = getname_flags(name, flags, empty); |
2097 | int err = PTR_ERR(tmp); | 2119 | int err = PTR_ERR(tmp); |
2098 | if (!IS_ERR(tmp)) { | 2120 | if (!IS_ERR(tmp)) { |
2099 | 2121 | ||
2100 | BUG_ON(flags & LOOKUP_PARENT); | 2122 | BUG_ON(flags & LOOKUP_PARENT); |
2101 | 2123 | ||
2102 | err = do_path_lookup(dfd, tmp, flags, &nd); | 2124 | err = do_path_lookup(dfd, tmp->name, flags, &nd); |
2103 | putname(tmp); | 2125 | putname(tmp); |
2104 | if (!err) | 2126 | if (!err) |
2105 | *path = nd.path; | 2127 | *path = nd.path; |
@@ -2113,22 +2135,22 @@ int user_path_at(int dfd, const char __user *name, unsigned flags, | |||
2113 | return user_path_at_empty(dfd, name, flags, path, NULL); | 2135 | return user_path_at_empty(dfd, name, flags, path, NULL); |
2114 | } | 2136 | } |
2115 | 2137 | ||
2116 | static int user_path_parent(int dfd, const char __user *path, | 2138 | static struct filename * |
2117 | struct nameidata *nd, char **name) | 2139 | user_path_parent(int dfd, const char __user *path, struct nameidata *nd) |
2118 | { | 2140 | { |
2119 | char *s = getname(path); | 2141 | struct filename *s = getname(path); |
2120 | int error; | 2142 | int error; |
2121 | 2143 | ||
2122 | if (IS_ERR(s)) | 2144 | if (IS_ERR(s)) |
2123 | return PTR_ERR(s); | 2145 | return s; |
2124 | 2146 | ||
2125 | error = do_path_lookup(dfd, s, LOOKUP_PARENT, nd); | 2147 | error = do_path_lookup(dfd, s->name, LOOKUP_PARENT, nd); |
2126 | if (error) | 2148 | if (error) { |
2127 | putname(s); | 2149 | putname(s); |
2128 | else | 2150 | return ERR_PTR(error); |
2129 | *name = s; | 2151 | } |
2130 | 2152 | ||
2131 | return error; | 2153 | return s; |
2132 | } | 2154 | } |
2133 | 2155 | ||
2134 | /* | 2156 | /* |
@@ -3039,11 +3061,11 @@ EXPORT_SYMBOL(done_path_create); | |||
3039 | 3061 | ||
3040 | struct dentry *user_path_create(int dfd, const char __user *pathname, struct path *path, int is_dir) | 3062 | struct dentry *user_path_create(int dfd, const char __user *pathname, struct path *path, int is_dir) |
3041 | { | 3063 | { |
3042 | char *tmp = getname(pathname); | 3064 | struct filename *tmp = getname(pathname); |
3043 | struct dentry *res; | 3065 | struct dentry *res; |
3044 | if (IS_ERR(tmp)) | 3066 | if (IS_ERR(tmp)) |
3045 | return ERR_CAST(tmp); | 3067 | return ERR_CAST(tmp); |
3046 | res = kern_path_create(dfd, tmp, path, is_dir); | 3068 | res = kern_path_create(dfd, tmp->name, path, is_dir); |
3047 | putname(tmp); | 3069 | putname(tmp); |
3048 | return res; | 3070 | return res; |
3049 | } | 3071 | } |
@@ -3248,13 +3270,13 @@ out: | |||
3248 | static long do_rmdir(int dfd, const char __user *pathname) | 3270 | static long do_rmdir(int dfd, const char __user *pathname) |
3249 | { | 3271 | { |
3250 | int error = 0; | 3272 | int error = 0; |
3251 | char * name; | 3273 | struct filename *name; |
3252 | struct dentry *dentry; | 3274 | struct dentry *dentry; |
3253 | struct nameidata nd; | 3275 | struct nameidata nd; |
3254 | 3276 | ||
3255 | error = user_path_parent(dfd, pathname, &nd, &name); | 3277 | name = user_path_parent(dfd, pathname, &nd); |
3256 | if (error) | 3278 | if (IS_ERR(name)) |
3257 | return error; | 3279 | return PTR_ERR(name); |
3258 | 3280 | ||
3259 | switch(nd.last_type) { | 3281 | switch(nd.last_type) { |
3260 | case LAST_DOTDOT: | 3282 | case LAST_DOTDOT: |
@@ -3343,14 +3365,14 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) | |||
3343 | static long do_unlinkat(int dfd, const char __user *pathname) | 3365 | static long do_unlinkat(int dfd, const char __user *pathname) |
3344 | { | 3366 | { |
3345 | int error; | 3367 | int error; |
3346 | char *name; | 3368 | struct filename *name; |
3347 | struct dentry *dentry; | 3369 | struct dentry *dentry; |
3348 | struct nameidata nd; | 3370 | struct nameidata nd; |
3349 | struct inode *inode = NULL; | 3371 | struct inode *inode = NULL; |
3350 | 3372 | ||
3351 | error = user_path_parent(dfd, pathname, &nd, &name); | 3373 | name = user_path_parent(dfd, pathname, &nd); |
3352 | if (error) | 3374 | if (IS_ERR(name)) |
3353 | return error; | 3375 | return PTR_ERR(name); |
3354 | 3376 | ||
3355 | error = -EISDIR; | 3377 | error = -EISDIR; |
3356 | if (nd.last_type != LAST_NORM) | 3378 | if (nd.last_type != LAST_NORM) |
@@ -3434,7 +3456,7 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname, | |||
3434 | int, newdfd, const char __user *, newname) | 3456 | int, newdfd, const char __user *, newname) |
3435 | { | 3457 | { |
3436 | int error; | 3458 | int error; |
3437 | char *from; | 3459 | struct filename *from; |
3438 | struct dentry *dentry; | 3460 | struct dentry *dentry; |
3439 | struct path path; | 3461 | struct path path; |
3440 | 3462 | ||
@@ -3447,9 +3469,9 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname, | |||
3447 | if (IS_ERR(dentry)) | 3469 | if (IS_ERR(dentry)) |
3448 | goto out_putname; | 3470 | goto out_putname; |
3449 | 3471 | ||
3450 | error = security_path_symlink(&path, dentry, from); | 3472 | error = security_path_symlink(&path, dentry, from->name); |
3451 | if (!error) | 3473 | if (!error) |
3452 | error = vfs_symlink(path.dentry->d_inode, dentry, from); | 3474 | error = vfs_symlink(path.dentry->d_inode, dentry, from->name); |
3453 | done_path_create(&path, dentry); | 3475 | done_path_create(&path, dentry); |
3454 | out_putname: | 3476 | out_putname: |
3455 | putname(from); | 3477 | putname(from); |
@@ -3729,17 +3751,21 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, | |||
3729 | struct dentry *old_dentry, *new_dentry; | 3751 | struct dentry *old_dentry, *new_dentry; |
3730 | struct dentry *trap; | 3752 | struct dentry *trap; |
3731 | struct nameidata oldnd, newnd; | 3753 | struct nameidata oldnd, newnd; |
3732 | char *from; | 3754 | struct filename *from; |
3733 | char *to; | 3755 | struct filename *to; |
3734 | int error; | 3756 | int error; |
3735 | 3757 | ||
3736 | error = user_path_parent(olddfd, oldname, &oldnd, &from); | 3758 | from = user_path_parent(olddfd, oldname, &oldnd); |
3737 | if (error) | 3759 | if (IS_ERR(from)) { |
3760 | error = PTR_ERR(from); | ||
3738 | goto exit; | 3761 | goto exit; |
3762 | } | ||
3739 | 3763 | ||
3740 | error = user_path_parent(newdfd, newname, &newnd, &to); | 3764 | to = user_path_parent(newdfd, newname, &newnd); |
3741 | if (error) | 3765 | if (IS_ERR(to)) { |
3766 | error = PTR_ERR(to); | ||
3742 | goto exit1; | 3767 | goto exit1; |
3768 | } | ||
3743 | 3769 | ||
3744 | error = -EXDEV; | 3770 | error = -EXDEV; |
3745 | if (oldnd.path.mnt != newnd.path.mnt) | 3771 | if (oldnd.path.mnt != newnd.path.mnt) |
diff --git a/fs/namespace.c b/fs/namespace.c index fc33207e28ad..24960626bb6b 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -2408,7 +2408,7 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, | |||
2408 | { | 2408 | { |
2409 | int ret; | 2409 | int ret; |
2410 | char *kernel_type; | 2410 | char *kernel_type; |
2411 | char *kernel_dir; | 2411 | struct filename *kernel_dir; |
2412 | char *kernel_dev; | 2412 | char *kernel_dev; |
2413 | unsigned long data_page; | 2413 | unsigned long data_page; |
2414 | 2414 | ||
@@ -2430,7 +2430,7 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, | |||
2430 | if (ret < 0) | 2430 | if (ret < 0) |
2431 | goto out_data; | 2431 | goto out_data; |
2432 | 2432 | ||
2433 | ret = do_mount(kernel_dev, kernel_dir, kernel_type, flags, | 2433 | ret = do_mount(kernel_dev, kernel_dir->name, kernel_type, flags, |
2434 | (void *) data_page); | 2434 | (void *) data_page); |
2435 | 2435 | ||
2436 | free_page(data_page); | 2436 | free_page(data_page); |
@@ -895,13 +895,13 @@ long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) | |||
895 | { | 895 | { |
896 | struct open_flags op; | 896 | struct open_flags op; |
897 | int lookup = build_open_flags(flags, mode, &op); | 897 | int lookup = build_open_flags(flags, mode, &op); |
898 | char *tmp = getname(filename); | 898 | struct filename *tmp = getname(filename); |
899 | int fd = PTR_ERR(tmp); | 899 | int fd = PTR_ERR(tmp); |
900 | 900 | ||
901 | if (!IS_ERR(tmp)) { | 901 | if (!IS_ERR(tmp)) { |
902 | fd = get_unused_fd_flags(flags); | 902 | fd = get_unused_fd_flags(flags); |
903 | if (fd >= 0) { | 903 | if (fd >= 0) { |
904 | struct file *f = do_filp_open(dfd, tmp, &op, lookup); | 904 | struct file *f = do_filp_open(dfd, tmp->name, &op, lookup); |
905 | if (IS_ERR(f)) { | 905 | if (IS_ERR(f)) { |
906 | put_unused_fd(fd); | 906 | put_unused_fd(fd); |
907 | fd = PTR_ERR(f); | 907 | fd = PTR_ERR(f); |
diff --git a/fs/quota/quota.c b/fs/quota/quota.c index ff0135d6bc51..af1661f7a54f 100644 --- a/fs/quota/quota.c +++ b/fs/quota/quota.c | |||
@@ -331,11 +331,11 @@ static struct super_block *quotactl_block(const char __user *special, int cmd) | |||
331 | #ifdef CONFIG_BLOCK | 331 | #ifdef CONFIG_BLOCK |
332 | struct block_device *bdev; | 332 | struct block_device *bdev; |
333 | struct super_block *sb; | 333 | struct super_block *sb; |
334 | char *tmp = getname(special); | 334 | struct filename *tmp = getname(special); |
335 | 335 | ||
336 | if (IS_ERR(tmp)) | 336 | if (IS_ERR(tmp)) |
337 | return ERR_CAST(tmp); | 337 | return ERR_CAST(tmp); |
338 | bdev = lookup_bdev(tmp); | 338 | bdev = lookup_bdev(tmp->name); |
339 | putname(tmp); | 339 | putname(tmp); |
340 | if (IS_ERR(bdev)) | 340 | if (IS_ERR(bdev)) |
341 | return ERR_CAST(bdev); | 341 | return ERR_CAST(bdev); |
diff --git a/include/linux/audit.h b/include/linux/audit.h index 3df643d1ac5b..94d29164803f 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
@@ -460,6 +460,8 @@ extern int audit_classify_arch(int arch); | |||
460 | #define AUDIT_TYPE_CHILD_DELETE 3 /* a child being deleted */ | 460 | #define AUDIT_TYPE_CHILD_DELETE 3 /* a child being deleted */ |
461 | #define AUDIT_TYPE_CHILD_CREATE 4 /* a child being created */ | 461 | #define AUDIT_TYPE_CHILD_CREATE 4 /* a child being created */ |
462 | 462 | ||
463 | struct filename; | ||
464 | |||
463 | #ifdef CONFIG_AUDITSYSCALL | 465 | #ifdef CONFIG_AUDITSYSCALL |
464 | /* These are defined in auditsc.c */ | 466 | /* These are defined in auditsc.c */ |
465 | /* Public API */ | 467 | /* Public API */ |
@@ -469,8 +471,8 @@ extern void __audit_syscall_entry(int arch, | |||
469 | int major, unsigned long a0, unsigned long a1, | 471 | int major, unsigned long a0, unsigned long a1, |
470 | unsigned long a2, unsigned long a3); | 472 | unsigned long a2, unsigned long a3); |
471 | extern void __audit_syscall_exit(int ret_success, long ret_value); | 473 | extern void __audit_syscall_exit(int ret_success, long ret_value); |
472 | extern void __audit_getname(const char *name); | 474 | extern void __audit_getname(struct filename *name); |
473 | extern void audit_putname(const char *name); | 475 | extern void audit_putname(struct filename *name); |
474 | extern void __audit_inode(const char *name, const struct dentry *dentry, | 476 | extern void __audit_inode(const char *name, const struct dentry *dentry, |
475 | unsigned int parent); | 477 | unsigned int parent); |
476 | extern void __audit_inode_child(const struct inode *parent, | 478 | extern void __audit_inode_child(const struct inode *parent, |
@@ -505,7 +507,7 @@ static inline void audit_syscall_exit(void *pt_regs) | |||
505 | __audit_syscall_exit(success, return_code); | 507 | __audit_syscall_exit(success, return_code); |
506 | } | 508 | } |
507 | } | 509 | } |
508 | static inline void audit_getname(const char *name) | 510 | static inline void audit_getname(struct filename *name) |
509 | { | 511 | { |
510 | if (unlikely(!audit_dummy_context())) | 512 | if (unlikely(!audit_dummy_context())) |
511 | __audit_getname(name); | 513 | __audit_getname(name); |
@@ -663,9 +665,9 @@ static inline int audit_dummy_context(void) | |||
663 | { | 665 | { |
664 | return 1; | 666 | return 1; |
665 | } | 667 | } |
666 | static inline void audit_getname(const char *name) | 668 | static inline void audit_getname(struct filename *name) |
667 | { } | 669 | { } |
668 | static inline void audit_putname(const char *name) | 670 | static inline void audit_putname(struct filename *name) |
669 | { } | 671 | { } |
670 | static inline void __audit_inode(const char *name, const struct dentry *dentry, | 672 | static inline void __audit_inode(const char *name, const struct dentry *dentry, |
671 | unsigned int parent) | 673 | unsigned int parent) |
diff --git a/include/linux/fs.h b/include/linux/fs.h index b44b4ca82164..6c93b46f46dc 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2196,6 +2196,10 @@ static inline int break_lease(struct inode *inode, unsigned int mode) | |||
2196 | #endif /* CONFIG_FILE_LOCKING */ | 2196 | #endif /* CONFIG_FILE_LOCKING */ |
2197 | 2197 | ||
2198 | /* fs/open.c */ | 2198 | /* fs/open.c */ |
2199 | struct filename { | ||
2200 | const char *name; /* pointer to actual string */ | ||
2201 | const __user char *uptr; /* original userland pointer */ | ||
2202 | }; | ||
2199 | 2203 | ||
2200 | extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs, | 2204 | extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs, |
2201 | struct file *filp); | 2205 | struct file *filp); |
@@ -2208,7 +2212,9 @@ extern struct file *file_open_root(struct dentry *, struct vfsmount *, | |||
2208 | const char *, int); | 2212 | const char *, int); |
2209 | extern struct file * dentry_open(const struct path *, int, const struct cred *); | 2213 | extern struct file * dentry_open(const struct path *, int, const struct cred *); |
2210 | extern int filp_close(struct file *, fl_owner_t id); | 2214 | extern int filp_close(struct file *, fl_owner_t id); |
2211 | extern char * getname(const char __user *); | 2215 | |
2216 | extern struct filename *getname(const char __user *); | ||
2217 | |||
2212 | enum { | 2218 | enum { |
2213 | FILE_CREATED = 1, | 2219 | FILE_CREATED = 1, |
2214 | FILE_OPENED = 2 | 2220 | FILE_OPENED = 2 |
@@ -2228,12 +2234,14 @@ extern void __init vfs_caches_init(unsigned long); | |||
2228 | 2234 | ||
2229 | extern struct kmem_cache *names_cachep; | 2235 | extern struct kmem_cache *names_cachep; |
2230 | 2236 | ||
2237 | extern void final_putname(struct filename *name); | ||
2238 | |||
2231 | #define __getname() kmem_cache_alloc(names_cachep, GFP_KERNEL) | 2239 | #define __getname() kmem_cache_alloc(names_cachep, GFP_KERNEL) |
2232 | #define __putname(name) kmem_cache_free(names_cachep, (void *)(name)) | 2240 | #define __putname(name) kmem_cache_free(names_cachep, (void *)(name)) |
2233 | #ifndef CONFIG_AUDITSYSCALL | 2241 | #ifndef CONFIG_AUDITSYSCALL |
2234 | #define putname(name) __putname(name) | 2242 | #define putname(name) final_putname(name) |
2235 | #else | 2243 | #else |
2236 | extern void putname(const char *name); | 2244 | extern void putname(struct filename *name); |
2237 | #endif | 2245 | #endif |
2238 | 2246 | ||
2239 | #ifdef CONFIG_BLOCK | 2247 | #ifdef CONFIG_BLOCK |
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 9553ed006042..6c5d9dcc9030 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
@@ -772,7 +772,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, | |||
772 | { | 772 | { |
773 | struct path path; | 773 | struct path path; |
774 | struct file *filp; | 774 | struct file *filp; |
775 | char *name; | 775 | struct filename *name; |
776 | struct mq_attr attr; | 776 | struct mq_attr attr; |
777 | int fd, error; | 777 | int fd, error; |
778 | struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; | 778 | struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; |
@@ -795,7 +795,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, | |||
795 | ro = mnt_want_write(mnt); /* we'll drop it in any case */ | 795 | ro = mnt_want_write(mnt); /* we'll drop it in any case */ |
796 | error = 0; | 796 | error = 0; |
797 | mutex_lock(&root->d_inode->i_mutex); | 797 | mutex_lock(&root->d_inode->i_mutex); |
798 | path.dentry = lookup_one_len(name, root, strlen(name)); | 798 | path.dentry = lookup_one_len(name->name, root, strlen(name->name)); |
799 | if (IS_ERR(path.dentry)) { | 799 | if (IS_ERR(path.dentry)) { |
800 | error = PTR_ERR(path.dentry); | 800 | error = PTR_ERR(path.dentry); |
801 | goto out_putfd; | 801 | goto out_putfd; |
@@ -804,7 +804,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, | |||
804 | 804 | ||
805 | if (oflag & O_CREAT) { | 805 | if (oflag & O_CREAT) { |
806 | if (path.dentry->d_inode) { /* entry already exists */ | 806 | if (path.dentry->d_inode) { /* entry already exists */ |
807 | audit_inode(name, path.dentry, 0); | 807 | audit_inode(name->name, path.dentry, 0); |
808 | if (oflag & O_EXCL) { | 808 | if (oflag & O_EXCL) { |
809 | error = -EEXIST; | 809 | error = -EEXIST; |
810 | goto out; | 810 | goto out; |
@@ -824,7 +824,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode, | |||
824 | error = -ENOENT; | 824 | error = -ENOENT; |
825 | goto out; | 825 | goto out; |
826 | } | 826 | } |
827 | audit_inode(name, path.dentry, 0); | 827 | audit_inode(name->name, path.dentry, 0); |
828 | filp = do_open(&path, oflag); | 828 | filp = do_open(&path, oflag); |
829 | } | 829 | } |
830 | 830 | ||
@@ -849,7 +849,7 @@ out_putname: | |||
849 | SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name) | 849 | SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name) |
850 | { | 850 | { |
851 | int err; | 851 | int err; |
852 | char *name; | 852 | struct filename *name; |
853 | struct dentry *dentry; | 853 | struct dentry *dentry; |
854 | struct inode *inode = NULL; | 854 | struct inode *inode = NULL; |
855 | struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; | 855 | struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; |
@@ -863,7 +863,8 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name) | |||
863 | if (err) | 863 | if (err) |
864 | goto out_name; | 864 | goto out_name; |
865 | mutex_lock_nested(&mnt->mnt_root->d_inode->i_mutex, I_MUTEX_PARENT); | 865 | mutex_lock_nested(&mnt->mnt_root->d_inode->i_mutex, I_MUTEX_PARENT); |
866 | dentry = lookup_one_len(name, mnt->mnt_root, strlen(name)); | 866 | dentry = lookup_one_len(name->name, mnt->mnt_root, |
867 | strlen(name->name)); | ||
867 | if (IS_ERR(dentry)) { | 868 | if (IS_ERR(dentry)) { |
868 | err = PTR_ERR(dentry); | 869 | err = PTR_ERR(dentry); |
869 | goto out_unlock; | 870 | goto out_unlock; |
diff --git a/kernel/acct.c b/kernel/acct.c index 5be01017d30f..08354195eecc 100644 --- a/kernel/acct.c +++ b/kernel/acct.c | |||
@@ -260,10 +260,10 @@ SYSCALL_DEFINE1(acct, const char __user *, name) | |||
260 | return -EPERM; | 260 | return -EPERM; |
261 | 261 | ||
262 | if (name) { | 262 | if (name) { |
263 | char *tmp = getname(name); | 263 | struct filename *tmp = getname(name); |
264 | if (IS_ERR(tmp)) | 264 | if (IS_ERR(tmp)) |
265 | return (PTR_ERR(tmp)); | 265 | return (PTR_ERR(tmp)); |
266 | error = acct_on(tmp); | 266 | error = acct_on(tmp->name); |
267 | putname(tmp); | 267 | putname(tmp); |
268 | } else { | 268 | } else { |
269 | struct bsd_acct_struct *acct; | 269 | struct bsd_acct_struct *acct; |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index d147585e9ef3..d4d82319eed5 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -103,28 +103,29 @@ struct audit_cap_data { | |||
103 | * we don't let putname() free it (instead we free all of the saved | 103 | * we don't let putname() free it (instead we free all of the saved |
104 | * pointers at syscall exit time). | 104 | * pointers at syscall exit time). |
105 | * | 105 | * |
106 | * Further, in fs/namei.c:path_lookup() we store the inode and device. */ | 106 | * Further, in fs/namei.c:path_lookup() we store the inode and device. |
107 | */ | ||
107 | struct audit_names { | 108 | struct audit_names { |
108 | struct list_head list; /* audit_context->names_list */ | 109 | struct list_head list; /* audit_context->names_list */ |
109 | const char *name; | 110 | struct filename *name; |
110 | unsigned long ino; | 111 | unsigned long ino; |
111 | dev_t dev; | 112 | dev_t dev; |
112 | umode_t mode; | 113 | umode_t mode; |
113 | kuid_t uid; | 114 | kuid_t uid; |
114 | kgid_t gid; | 115 | kgid_t gid; |
115 | dev_t rdev; | 116 | dev_t rdev; |
116 | u32 osid; | 117 | u32 osid; |
117 | struct audit_cap_data fcap; | 118 | struct audit_cap_data fcap; |
118 | unsigned int fcap_ver; | 119 | unsigned int fcap_ver; |
119 | int name_len; /* number of name's characters to log */ | 120 | int name_len; /* number of name's characters to log */ |
120 | unsigned char type; /* record type */ | 121 | unsigned char type; /* record type */ |
121 | bool name_put; /* call __putname() for this name */ | 122 | bool name_put; /* call __putname() for this name */ |
122 | /* | 123 | /* |
123 | * This was an allocated audit_names and not from the array of | 124 | * This was an allocated audit_names and not from the array of |
124 | * names allocated in the task audit context. Thus this name | 125 | * names allocated in the task audit context. Thus this name |
125 | * should be freed on syscall exit | 126 | * should be freed on syscall exit |
126 | */ | 127 | */ |
127 | bool should_free; | 128 | bool should_free; |
128 | }; | 129 | }; |
129 | 130 | ||
130 | struct audit_aux_data { | 131 | struct audit_aux_data { |
@@ -996,7 +997,7 @@ static inline void audit_free_names(struct audit_context *context) | |||
996 | context->ino_count); | 997 | context->ino_count); |
997 | list_for_each_entry(n, &context->names_list, list) { | 998 | list_for_each_entry(n, &context->names_list, list) { |
998 | printk(KERN_ERR "names[%d] = %p = %s\n", i, | 999 | printk(KERN_ERR "names[%d] = %p = %s\n", i, |
999 | n->name, n->name ?: "(null)"); | 1000 | n->name, n->name->name ?: "(null)"); |
1000 | } | 1001 | } |
1001 | dump_stack(); | 1002 | dump_stack(); |
1002 | return; | 1003 | return; |
@@ -1553,7 +1554,7 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n, | |||
1553 | case AUDIT_NAME_FULL: | 1554 | case AUDIT_NAME_FULL: |
1554 | /* log the full path */ | 1555 | /* log the full path */ |
1555 | audit_log_format(ab, " name="); | 1556 | audit_log_format(ab, " name="); |
1556 | audit_log_untrustedstring(ab, n->name); | 1557 | audit_log_untrustedstring(ab, n->name->name); |
1557 | break; | 1558 | break; |
1558 | case 0: | 1559 | case 0: |
1559 | /* name was specified as a relative path and the | 1560 | /* name was specified as a relative path and the |
@@ -1563,7 +1564,7 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n, | |||
1563 | default: | 1564 | default: |
1564 | /* log the name's directory component */ | 1565 | /* log the name's directory component */ |
1565 | audit_log_format(ab, " name="); | 1566 | audit_log_format(ab, " name="); |
1566 | audit_log_n_untrustedstring(ab, n->name, | 1567 | audit_log_n_untrustedstring(ab, n->name->name, |
1567 | n->name_len); | 1568 | n->name_len); |
1568 | } | 1569 | } |
1569 | } else | 1570 | } else |
@@ -2026,7 +2027,7 @@ static struct audit_names *audit_alloc_name(struct audit_context *context, | |||
2026 | * Add a name to the list of audit names for this context. | 2027 | * Add a name to the list of audit names for this context. |
2027 | * Called from fs/namei.c:getname(). | 2028 | * Called from fs/namei.c:getname(). |
2028 | */ | 2029 | */ |
2029 | void __audit_getname(const char *name) | 2030 | void __audit_getname(struct filename *name) |
2030 | { | 2031 | { |
2031 | struct audit_context *context = current->audit_context; | 2032 | struct audit_context *context = current->audit_context; |
2032 | struct audit_names *n; | 2033 | struct audit_names *n; |
@@ -2040,6 +2041,11 @@ void __audit_getname(const char *name) | |||
2040 | return; | 2041 | return; |
2041 | } | 2042 | } |
2042 | 2043 | ||
2044 | #if AUDIT_DEBUG | ||
2045 | /* The filename _must_ have a populated ->name */ | ||
2046 | BUG_ON(!name->name); | ||
2047 | #endif | ||
2048 | |||
2043 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); | 2049 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); |
2044 | if (!n) | 2050 | if (!n) |
2045 | return; | 2051 | return; |
@@ -2059,7 +2065,7 @@ void __audit_getname(const char *name) | |||
2059 | * then we delay the putname until syscall exit. | 2065 | * then we delay the putname until syscall exit. |
2060 | * Called from include/linux/fs.h:putname(). | 2066 | * Called from include/linux/fs.h:putname(). |
2061 | */ | 2067 | */ |
2062 | void audit_putname(const char *name) | 2068 | void audit_putname(struct filename *name) |
2063 | { | 2069 | { |
2064 | struct audit_context *context = current->audit_context; | 2070 | struct audit_context *context = current->audit_context; |
2065 | 2071 | ||
@@ -2074,7 +2080,7 @@ void audit_putname(const char *name) | |||
2074 | 2080 | ||
2075 | list_for_each_entry(n, &context->names_list, list) | 2081 | list_for_each_entry(n, &context->names_list, list) |
2076 | printk(KERN_ERR "name[%d] = %p = %s\n", i, | 2082 | printk(KERN_ERR "name[%d] = %p = %s\n", i, |
2077 | n->name, n->name ?: "(null)"); | 2083 | n->name, n->name->name ?: "(null)"); |
2078 | } | 2084 | } |
2079 | #endif | 2085 | #endif |
2080 | __putname(name); | 2086 | __putname(name); |
@@ -2088,8 +2094,8 @@ void audit_putname(const char *name) | |||
2088 | " put_count=%d\n", | 2094 | " put_count=%d\n", |
2089 | __FILE__, __LINE__, | 2095 | __FILE__, __LINE__, |
2090 | context->serial, context->major, | 2096 | context->serial, context->major, |
2091 | context->in_syscall, name, context->name_count, | 2097 | context->in_syscall, name->name, |
2092 | context->put_count); | 2098 | context->name_count, context->put_count); |
2093 | dump_stack(); | 2099 | dump_stack(); |
2094 | } | 2100 | } |
2095 | } | 2101 | } |
@@ -2152,7 +2158,7 @@ void __audit_inode(const char *name, const struct dentry *dentry, | |||
2152 | 2158 | ||
2153 | list_for_each_entry_reverse(n, &context->names_list, list) { | 2159 | list_for_each_entry_reverse(n, &context->names_list, list) { |
2154 | /* does the name pointer match? */ | 2160 | /* does the name pointer match? */ |
2155 | if (n->name != name) | 2161 | if (!n->name || n->name->name != name) |
2156 | continue; | 2162 | continue; |
2157 | 2163 | ||
2158 | /* match the correct record type */ | 2164 | /* match the correct record type */ |
@@ -2175,7 +2181,7 @@ out_alloc: | |||
2175 | return; | 2181 | return; |
2176 | out: | 2182 | out: |
2177 | if (parent) { | 2183 | if (parent) { |
2178 | n->name_len = n->name ? parent_len(n->name) : AUDIT_NAME_FULL; | 2184 | n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL; |
2179 | n->type = AUDIT_TYPE_PARENT; | 2185 | n->type = AUDIT_TYPE_PARENT; |
2180 | } else { | 2186 | } else { |
2181 | n->name_len = AUDIT_NAME_FULL; | 2187 | n->name_len = AUDIT_NAME_FULL; |
@@ -2220,7 +2226,7 @@ void __audit_inode_child(const struct inode *parent, | |||
2220 | continue; | 2226 | continue; |
2221 | 2227 | ||
2222 | if (n->ino == parent->i_ino && | 2228 | if (n->ino == parent->i_ino && |
2223 | !audit_compare_dname_path(dname, n->name, n->name_len)) { | 2229 | !audit_compare_dname_path(dname, n->name->name, n->name_len)) { |
2224 | found_parent = n; | 2230 | found_parent = n; |
2225 | break; | 2231 | break; |
2226 | } | 2232 | } |
@@ -2236,8 +2242,8 @@ void __audit_inode_child(const struct inode *parent, | |||
2236 | if (found_parent && (n->name != found_parent->name)) | 2242 | if (found_parent && (n->name != found_parent->name)) |
2237 | continue; | 2243 | continue; |
2238 | 2244 | ||
2239 | if (!strcmp(dname, n->name) || | 2245 | if (!strcmp(dname, n->name->name) || |
2240 | !audit_compare_dname_path(dname, n->name, | 2246 | !audit_compare_dname_path(dname, n->name->name, |
2241 | found_parent ? | 2247 | found_parent ? |
2242 | found_parent->name_len : | 2248 | found_parent->name_len : |
2243 | AUDIT_NAME_FULL)) { | 2249 | AUDIT_NAME_FULL)) { |
diff --git a/mm/swapfile.c b/mm/swapfile.c index 14e254c768fc..90d2ed591de9 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c | |||
@@ -1483,7 +1483,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) | |||
1483 | struct file *swap_file, *victim; | 1483 | struct file *swap_file, *victim; |
1484 | struct address_space *mapping; | 1484 | struct address_space *mapping; |
1485 | struct inode *inode; | 1485 | struct inode *inode; |
1486 | char *pathname; | 1486 | struct filename *pathname; |
1487 | int oom_score_adj; | 1487 | int oom_score_adj; |
1488 | int i, type, prev; | 1488 | int i, type, prev; |
1489 | int err; | 1489 | int err; |
@@ -1498,8 +1498,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) | |||
1498 | if (IS_ERR(pathname)) | 1498 | if (IS_ERR(pathname)) |
1499 | goto out; | 1499 | goto out; |
1500 | 1500 | ||
1501 | victim = filp_open(pathname, O_RDWR|O_LARGEFILE, 0); | 1501 | victim = filp_open(pathname->name, O_RDWR|O_LARGEFILE, 0); |
1502 | putname(pathname); | ||
1503 | err = PTR_ERR(victim); | 1502 | err = PTR_ERR(victim); |
1504 | if (IS_ERR(victim)) | 1503 | if (IS_ERR(victim)) |
1505 | goto out; | 1504 | goto out; |
@@ -1936,7 +1935,7 @@ static int setup_swap_map_and_extents(struct swap_info_struct *p, | |||
1936 | SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | 1935 | SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) |
1937 | { | 1936 | { |
1938 | struct swap_info_struct *p; | 1937 | struct swap_info_struct *p; |
1939 | char *name; | 1938 | struct filename *name; |
1940 | struct file *swap_file = NULL; | 1939 | struct file *swap_file = NULL; |
1941 | struct address_space *mapping; | 1940 | struct address_space *mapping; |
1942 | int i; | 1941 | int i; |
@@ -1967,7 +1966,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | |||
1967 | name = NULL; | 1966 | name = NULL; |
1968 | goto bad_swap; | 1967 | goto bad_swap; |
1969 | } | 1968 | } |
1970 | swap_file = filp_open(name, O_RDWR|O_LARGEFILE, 0); | 1969 | swap_file = filp_open(name->name, O_RDWR|O_LARGEFILE, 0); |
1971 | if (IS_ERR(swap_file)) { | 1970 | if (IS_ERR(swap_file)) { |
1972 | error = PTR_ERR(swap_file); | 1971 | error = PTR_ERR(swap_file); |
1973 | swap_file = NULL; | 1972 | swap_file = NULL; |
@@ -2053,7 +2052,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) | |||
2053 | 2052 | ||
2054 | printk(KERN_INFO "Adding %uk swap on %s. " | 2053 | printk(KERN_INFO "Adding %uk swap on %s. " |
2055 | "Priority:%d extents:%d across:%lluk %s%s%s\n", | 2054 | "Priority:%d extents:%d across:%lluk %s%s%s\n", |
2056 | p->pages<<(PAGE_SHIFT-10), name, p->prio, | 2055 | p->pages<<(PAGE_SHIFT-10), name->name, p->prio, |
2057 | nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10), | 2056 | nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10), |
2058 | (p->flags & SWP_SOLIDSTATE) ? "SS" : "", | 2057 | (p->flags & SWP_SOLIDSTATE) ? "SS" : "", |
2059 | (p->flags & SWP_DISCARDABLE) ? "D" : "", | 2058 | (p->flags & SWP_DISCARDABLE) ? "D" : "", |