diff options
49 files changed, 544 insertions, 312 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/btrfs/ioctl.c b/fs/btrfs/ioctl.c index e568c472f807..61168805f175 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
@@ -638,7 +638,7 @@ static int btrfs_may_delete(struct inode *dir,struct dentry *victim,int isdir) | |||
638 | return -ENOENT; | 638 | return -ENOENT; |
639 | 639 | ||
640 | BUG_ON(victim->d_parent->d_inode != dir); | 640 | BUG_ON(victim->d_parent->d_inode != dir); |
641 | audit_inode_child(victim, dir); | 641 | audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE); |
642 | 642 | ||
643 | error = inode_permission(dir, MAY_WRITE | MAY_EXEC); | 643 | error = inode_permission(dir, MAY_WRITE | MAY_EXEC); |
644 | if (error) | 644 | if (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, |
@@ -751,13 +751,14 @@ struct file *open_exec(const char *name) | |||
751 | { | 751 | { |
752 | struct file *file; | 752 | struct file *file; |
753 | int err; | 753 | int err; |
754 | struct filename tmp = { .name = name }; | ||
754 | static const struct open_flags open_exec_flags = { | 755 | static const struct open_flags open_exec_flags = { |
755 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, | 756 | .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC, |
756 | .acc_mode = MAY_EXEC | MAY_OPEN, | 757 | .acc_mode = MAY_EXEC | MAY_OPEN, |
757 | .intent = LOOKUP_OPEN | 758 | .intent = LOOKUP_OPEN |
758 | }; | 759 | }; |
759 | 760 | ||
760 | file = do_filp_open(AT_FDCWD, name, &open_exec_flags, LOOKUP_FOLLOW); | 761 | file = do_filp_open(AT_FDCWD, &tmp, &open_exec_flags, LOOKUP_FOLLOW); |
761 | if (IS_ERR(file)) | 762 | if (IS_ERR(file)) |
762 | goto out; | 763 | goto out; |
763 | 764 | ||
@@ -1664,10 +1665,10 @@ SYSCALL_DEFINE3(execve, | |||
1664 | const char __user *const __user *, argv, | 1665 | const char __user *const __user *, argv, |
1665 | const char __user *const __user *, envp) | 1666 | const char __user *const __user *, envp) |
1666 | { | 1667 | { |
1667 | const char *path = getname(filename); | 1668 | struct filename *path = getname(filename); |
1668 | int error = PTR_ERR(path); | 1669 | int error = PTR_ERR(path); |
1669 | if (!IS_ERR(path)) { | 1670 | if (!IS_ERR(path)) { |
1670 | error = do_execve(path, argv, envp, current_pt_regs()); | 1671 | error = do_execve(path->name, argv, envp, current_pt_regs()); |
1671 | putname(path); | 1672 | putname(path); |
1672 | } | 1673 | } |
1673 | return error; | 1674 | return error; |
@@ -1677,10 +1678,11 @@ asmlinkage long compat_sys_execve(const char __user * filename, | |||
1677 | const compat_uptr_t __user * argv, | 1678 | const compat_uptr_t __user * argv, |
1678 | const compat_uptr_t __user * envp) | 1679 | const compat_uptr_t __user * envp) |
1679 | { | 1680 | { |
1680 | const char *path = getname(filename); | 1681 | struct filename *path = getname(filename); |
1681 | int error = PTR_ERR(path); | 1682 | int error = PTR_ERR(path); |
1682 | if (!IS_ERR(path)) { | 1683 | if (!IS_ERR(path)) { |
1683 | error = compat_do_execve(path, argv, envp, current_pt_regs()); | 1684 | error = compat_do_execve(path->name, argv, envp, |
1685 | current_pt_regs()); | ||
1684 | putname(path); | 1686 | putname(path); |
1685 | } | 1687 | } |
1686 | return error; | 1688 | 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/internal.h b/fs/internal.h index 371bcc4b1697..916b7cbf3e3e 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
@@ -97,8 +97,8 @@ struct open_flags { | |||
97 | int acc_mode; | 97 | int acc_mode; |
98 | int intent; | 98 | int intent; |
99 | }; | 99 | }; |
100 | extern struct file *do_filp_open(int dfd, const char *pathname, | 100 | extern struct file *do_filp_open(int dfd, struct filename *pathname, |
101 | const struct open_flags *op, int lookup_flags); | 101 | const struct open_flags *op, int flags); |
102 | extern struct file *do_file_open_root(struct dentry *, struct vfsmount *, | 102 | extern struct file *do_file_open_root(struct dentry *, struct vfsmount *, |
103 | const char *, const struct open_flags *, int lookup_flags); | 103 | const char *, const struct open_flags *, int lookup_flags); |
104 | 104 | ||
diff --git a/fs/namei.c b/fs/namei.c index c1f18e4f034c..d1895f308156 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -117,18 +117,70 @@ | |||
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 | if (name->separate) { |
123 | __putname(name->name); | ||
124 | kfree(name); | ||
125 | } else { | ||
126 | __putname(name); | ||
127 | } | ||
128 | } | ||
129 | |||
130 | #define EMBEDDED_NAME_MAX (PATH_MAX - sizeof(struct filename)) | ||
131 | |||
132 | static struct filename * | ||
133 | getname_flags(const char __user *filename, int flags, int *empty) | ||
134 | { | ||
135 | struct filename *result, *err; | ||
123 | int len; | 136 | int len; |
137 | long max; | ||
138 | char *kname; | ||
124 | 139 | ||
140 | result = audit_reusename(filename); | ||
141 | if (result) | ||
142 | return result; | ||
143 | |||
144 | result = __getname(); | ||
125 | if (unlikely(!result)) | 145 | if (unlikely(!result)) |
126 | return ERR_PTR(-ENOMEM); | 146 | return ERR_PTR(-ENOMEM); |
127 | 147 | ||
128 | len = strncpy_from_user(result, filename, PATH_MAX); | 148 | /* |
129 | err = ERR_PTR(len); | 149 | * First, try to embed the struct filename inside the names_cache |
130 | if (unlikely(len < 0)) | 150 | * allocation |
151 | */ | ||
152 | kname = (char *)result + sizeof(*result); | ||
153 | result->name = kname; | ||
154 | result->separate = false; | ||
155 | max = EMBEDDED_NAME_MAX; | ||
156 | |||
157 | recopy: | ||
158 | len = strncpy_from_user(kname, filename, max); | ||
159 | if (unlikely(len < 0)) { | ||
160 | err = ERR_PTR(len); | ||
131 | goto error; | 161 | goto error; |
162 | } | ||
163 | |||
164 | /* | ||
165 | * Uh-oh. We have a name that's approaching PATH_MAX. Allocate a | ||
166 | * separate struct filename so we can dedicate the entire | ||
167 | * names_cache allocation for the pathname, and re-do the copy from | ||
168 | * userland. | ||
169 | */ | ||
170 | if (len == EMBEDDED_NAME_MAX && max == EMBEDDED_NAME_MAX) { | ||
171 | kname = (char *)result; | ||
172 | |||
173 | result = kzalloc(sizeof(*result), GFP_KERNEL); | ||
174 | if (!result) { | ||
175 | err = ERR_PTR(-ENOMEM); | ||
176 | result = (struct filename *)kname; | ||
177 | goto error; | ||
178 | } | ||
179 | result->name = kname; | ||
180 | result->separate = true; | ||
181 | max = PATH_MAX; | ||
182 | goto recopy; | ||
183 | } | ||
132 | 184 | ||
133 | /* The empty path is special. */ | 185 | /* The empty path is special. */ |
134 | if (unlikely(!len)) { | 186 | if (unlikely(!len)) { |
@@ -140,30 +192,32 @@ static char *getname_flags(const char __user *filename, int flags, int *empty) | |||
140 | } | 192 | } |
141 | 193 | ||
142 | err = ERR_PTR(-ENAMETOOLONG); | 194 | err = ERR_PTR(-ENAMETOOLONG); |
143 | if (likely(len < PATH_MAX)) { | 195 | if (unlikely(len >= PATH_MAX)) |
144 | audit_getname(result); | 196 | goto error; |
145 | return result; | 197 | |
146 | } | 198 | result->uptr = filename; |
199 | audit_getname(result); | ||
200 | return result; | ||
147 | 201 | ||
148 | error: | 202 | error: |
149 | __putname(result); | 203 | final_putname(result); |
150 | return err; | 204 | return err; |
151 | } | 205 | } |
152 | 206 | ||
153 | char *getname(const char __user * filename) | 207 | struct filename * |
208 | getname(const char __user * filename) | ||
154 | { | 209 | { |
155 | return getname_flags(filename, 0, NULL); | 210 | return getname_flags(filename, 0, NULL); |
156 | } | 211 | } |
212 | EXPORT_SYMBOL(getname); | ||
157 | 213 | ||
158 | #ifdef CONFIG_AUDITSYSCALL | 214 | #ifdef CONFIG_AUDITSYSCALL |
159 | void putname(const char *name) | 215 | void putname(struct filename *name) |
160 | { | 216 | { |
161 | if (unlikely(!audit_dummy_context())) | 217 | if (unlikely(!audit_dummy_context())) |
162 | audit_putname(name); | 218 | return audit_putname(name); |
163 | else | 219 | final_putname(name); |
164 | __putname(name); | ||
165 | } | 220 | } |
166 | EXPORT_SYMBOL(putname); | ||
167 | #endif | 221 | #endif |
168 | 222 | ||
169 | static int check_acl(struct inode *inode, int mask) | 223 | static int check_acl(struct inode *inode, int mask) |
@@ -1963,24 +2017,29 @@ static int path_lookupat(int dfd, const char *name, | |||
1963 | return err; | 2017 | return err; |
1964 | } | 2018 | } |
1965 | 2019 | ||
1966 | static int do_path_lookup(int dfd, const char *name, | 2020 | static int filename_lookup(int dfd, struct filename *name, |
1967 | unsigned int flags, struct nameidata *nd) | 2021 | unsigned int flags, struct nameidata *nd) |
1968 | { | 2022 | { |
1969 | int retval = path_lookupat(dfd, name, flags | LOOKUP_RCU, nd); | 2023 | int retval = path_lookupat(dfd, name->name, flags | LOOKUP_RCU, nd); |
1970 | if (unlikely(retval == -ECHILD)) | 2024 | if (unlikely(retval == -ECHILD)) |
1971 | retval = path_lookupat(dfd, name, flags, nd); | 2025 | retval = path_lookupat(dfd, name->name, flags, nd); |
1972 | if (unlikely(retval == -ESTALE)) | 2026 | if (unlikely(retval == -ESTALE)) |
1973 | retval = path_lookupat(dfd, name, flags | LOOKUP_REVAL, nd); | 2027 | retval = path_lookupat(dfd, name->name, |
2028 | flags | LOOKUP_REVAL, nd); | ||
1974 | 2029 | ||
1975 | if (likely(!retval)) { | 2030 | if (likely(!retval)) |
1976 | if (unlikely(!audit_dummy_context())) { | 2031 | audit_inode(name, nd->path.dentry, flags & LOOKUP_PARENT); |
1977 | if (nd->path.dentry && nd->inode) | ||
1978 | audit_inode(name, nd->path.dentry); | ||
1979 | } | ||
1980 | } | ||
1981 | return retval; | 2032 | return retval; |
1982 | } | 2033 | } |
1983 | 2034 | ||
2035 | static int do_path_lookup(int dfd, const char *name, | ||
2036 | unsigned int flags, struct nameidata *nd) | ||
2037 | { | ||
2038 | struct filename filename = { .name = name }; | ||
2039 | |||
2040 | return filename_lookup(dfd, &filename, flags, nd); | ||
2041 | } | ||
2042 | |||
1984 | /* does lookup, returns the object with parent locked */ | 2043 | /* does lookup, returns the object with parent locked */ |
1985 | struct dentry *kern_path_locked(const char *name, struct path *path) | 2044 | struct dentry *kern_path_locked(const char *name, struct path *path) |
1986 | { | 2045 | { |
@@ -2098,13 +2157,13 @@ int user_path_at_empty(int dfd, const char __user *name, unsigned flags, | |||
2098 | struct path *path, int *empty) | 2157 | struct path *path, int *empty) |
2099 | { | 2158 | { |
2100 | struct nameidata nd; | 2159 | struct nameidata nd; |
2101 | char *tmp = getname_flags(name, flags, empty); | 2160 | struct filename *tmp = getname_flags(name, flags, empty); |
2102 | int err = PTR_ERR(tmp); | 2161 | int err = PTR_ERR(tmp); |
2103 | if (!IS_ERR(tmp)) { | 2162 | if (!IS_ERR(tmp)) { |
2104 | 2163 | ||
2105 | BUG_ON(flags & LOOKUP_PARENT); | 2164 | BUG_ON(flags & LOOKUP_PARENT); |
2106 | 2165 | ||
2107 | err = do_path_lookup(dfd, tmp, flags, &nd); | 2166 | err = filename_lookup(dfd, tmp, flags, &nd); |
2108 | putname(tmp); | 2167 | putname(tmp); |
2109 | if (!err) | 2168 | if (!err) |
2110 | *path = nd.path; | 2169 | *path = nd.path; |
@@ -2118,22 +2177,28 @@ int user_path_at(int dfd, const char __user *name, unsigned flags, | |||
2118 | return user_path_at_empty(dfd, name, flags, path, NULL); | 2177 | return user_path_at_empty(dfd, name, flags, path, NULL); |
2119 | } | 2178 | } |
2120 | 2179 | ||
2121 | static int user_path_parent(int dfd, const char __user *path, | 2180 | /* |
2122 | struct nameidata *nd, char **name) | 2181 | * NB: most callers don't do anything directly with the reference to the |
2182 | * to struct filename, but the nd->last pointer points into the name string | ||
2183 | * allocated by getname. So we must hold the reference to it until all | ||
2184 | * path-walking is complete. | ||
2185 | */ | ||
2186 | static struct filename * | ||
2187 | user_path_parent(int dfd, const char __user *path, struct nameidata *nd) | ||
2123 | { | 2188 | { |
2124 | char *s = getname(path); | 2189 | struct filename *s = getname(path); |
2125 | int error; | 2190 | int error; |
2126 | 2191 | ||
2127 | if (IS_ERR(s)) | 2192 | if (IS_ERR(s)) |
2128 | return PTR_ERR(s); | 2193 | return s; |
2129 | 2194 | ||
2130 | error = do_path_lookup(dfd, s, LOOKUP_PARENT, nd); | 2195 | error = filename_lookup(dfd, s, LOOKUP_PARENT, nd); |
2131 | if (error) | 2196 | if (error) { |
2132 | putname(s); | 2197 | putname(s); |
2133 | else | 2198 | return ERR_PTR(error); |
2134 | *name = s; | 2199 | } |
2135 | 2200 | ||
2136 | return error; | 2201 | return s; |
2137 | } | 2202 | } |
2138 | 2203 | ||
2139 | /* | 2204 | /* |
@@ -2180,7 +2245,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir) | |||
2180 | return -ENOENT; | 2245 | return -ENOENT; |
2181 | 2246 | ||
2182 | BUG_ON(victim->d_parent->d_inode != dir); | 2247 | BUG_ON(victim->d_parent->d_inode != dir); |
2183 | audit_inode_child(victim, dir); | 2248 | audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE); |
2184 | 2249 | ||
2185 | error = inode_permission(dir, MAY_WRITE | MAY_EXEC); | 2250 | error = inode_permission(dir, MAY_WRITE | MAY_EXEC); |
2186 | if (error) | 2251 | if (error) |
@@ -2625,7 +2690,7 @@ out_dput: | |||
2625 | */ | 2690 | */ |
2626 | static int do_last(struct nameidata *nd, struct path *path, | 2691 | static int do_last(struct nameidata *nd, struct path *path, |
2627 | struct file *file, const struct open_flags *op, | 2692 | struct file *file, const struct open_flags *op, |
2628 | int *opened, const char *pathname) | 2693 | int *opened, struct filename *name) |
2629 | { | 2694 | { |
2630 | struct dentry *dir = nd->path.dentry; | 2695 | struct dentry *dir = nd->path.dentry; |
2631 | int open_flag = op->open_flag; | 2696 | int open_flag = op->open_flag; |
@@ -2652,7 +2717,7 @@ static int do_last(struct nameidata *nd, struct path *path, | |||
2652 | error = complete_walk(nd); | 2717 | error = complete_walk(nd); |
2653 | if (error) | 2718 | if (error) |
2654 | return error; | 2719 | return error; |
2655 | audit_inode(pathname, nd->path.dentry); | 2720 | audit_inode(name, nd->path.dentry, 0); |
2656 | if (open_flag & O_CREAT) { | 2721 | if (open_flag & O_CREAT) { |
2657 | error = -EISDIR; | 2722 | error = -EISDIR; |
2658 | goto out; | 2723 | goto out; |
@@ -2662,7 +2727,7 @@ static int do_last(struct nameidata *nd, struct path *path, | |||
2662 | error = complete_walk(nd); | 2727 | error = complete_walk(nd); |
2663 | if (error) | 2728 | if (error) |
2664 | return error; | 2729 | return error; |
2665 | audit_inode(pathname, dir); | 2730 | audit_inode(name, dir, 0); |
2666 | goto finish_open; | 2731 | goto finish_open; |
2667 | } | 2732 | } |
2668 | 2733 | ||
@@ -2691,7 +2756,7 @@ static int do_last(struct nameidata *nd, struct path *path, | |||
2691 | if (error) | 2756 | if (error) |
2692 | return error; | 2757 | return error; |
2693 | 2758 | ||
2694 | audit_inode(pathname, dir); | 2759 | audit_inode(name, dir, 0); |
2695 | error = -EISDIR; | 2760 | error = -EISDIR; |
2696 | /* trailing slashes? */ | 2761 | /* trailing slashes? */ |
2697 | if (nd->last.name[nd->last.len]) | 2762 | if (nd->last.name[nd->last.len]) |
@@ -2721,7 +2786,7 @@ retry_lookup: | |||
2721 | !S_ISREG(file->f_path.dentry->d_inode->i_mode)) | 2786 | !S_ISREG(file->f_path.dentry->d_inode->i_mode)) |
2722 | will_truncate = false; | 2787 | will_truncate = false; |
2723 | 2788 | ||
2724 | audit_inode(pathname, file->f_path.dentry); | 2789 | audit_inode(name, file->f_path.dentry, 0); |
2725 | goto opened; | 2790 | goto opened; |
2726 | } | 2791 | } |
2727 | 2792 | ||
@@ -2738,7 +2803,7 @@ retry_lookup: | |||
2738 | * create/update audit record if it already exists. | 2803 | * create/update audit record if it already exists. |
2739 | */ | 2804 | */ |
2740 | if (path->dentry->d_inode) | 2805 | if (path->dentry->d_inode) |
2741 | audit_inode(pathname, path->dentry); | 2806 | audit_inode(name, path->dentry, 0); |
2742 | 2807 | ||
2743 | /* | 2808 | /* |
2744 | * If atomic_open() acquired write access it is dropped now due to | 2809 | * If atomic_open() acquired write access it is dropped now due to |
@@ -2803,7 +2868,7 @@ finish_lookup: | |||
2803 | error = -ENOTDIR; | 2868 | error = -ENOTDIR; |
2804 | if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup) | 2869 | if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup) |
2805 | goto out; | 2870 | goto out; |
2806 | audit_inode(pathname, nd->path.dentry); | 2871 | audit_inode(name, nd->path.dentry, 0); |
2807 | finish_open: | 2872 | finish_open: |
2808 | if (!S_ISREG(nd->inode->i_mode)) | 2873 | if (!S_ISREG(nd->inode->i_mode)) |
2809 | will_truncate = false; | 2874 | will_truncate = false; |
@@ -2871,7 +2936,7 @@ stale_open: | |||
2871 | goto retry_lookup; | 2936 | goto retry_lookup; |
2872 | } | 2937 | } |
2873 | 2938 | ||
2874 | static struct file *path_openat(int dfd, const char *pathname, | 2939 | static struct file *path_openat(int dfd, struct filename *pathname, |
2875 | struct nameidata *nd, const struct open_flags *op, int flags) | 2940 | struct nameidata *nd, const struct open_flags *op, int flags) |
2876 | { | 2941 | { |
2877 | struct file *base = NULL; | 2942 | struct file *base = NULL; |
@@ -2886,12 +2951,12 @@ static struct file *path_openat(int dfd, const char *pathname, | |||
2886 | 2951 | ||
2887 | file->f_flags = op->open_flag; | 2952 | file->f_flags = op->open_flag; |
2888 | 2953 | ||
2889 | error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base); | 2954 | error = path_init(dfd, pathname->name, flags | LOOKUP_PARENT, nd, &base); |
2890 | if (unlikely(error)) | 2955 | if (unlikely(error)) |
2891 | goto out; | 2956 | goto out; |
2892 | 2957 | ||
2893 | current->total_link_count = 0; | 2958 | current->total_link_count = 0; |
2894 | error = link_path_walk(pathname, nd); | 2959 | error = link_path_walk(pathname->name, nd); |
2895 | if (unlikely(error)) | 2960 | if (unlikely(error)) |
2896 | goto out; | 2961 | goto out; |
2897 | 2962 | ||
@@ -2937,7 +3002,7 @@ out: | |||
2937 | return file; | 3002 | return file; |
2938 | } | 3003 | } |
2939 | 3004 | ||
2940 | struct file *do_filp_open(int dfd, const char *pathname, | 3005 | struct file *do_filp_open(int dfd, struct filename *pathname, |
2941 | const struct open_flags *op, int flags) | 3006 | const struct open_flags *op, int flags) |
2942 | { | 3007 | { |
2943 | struct nameidata nd; | 3008 | struct nameidata nd; |
@@ -2956,6 +3021,7 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt, | |||
2956 | { | 3021 | { |
2957 | struct nameidata nd; | 3022 | struct nameidata nd; |
2958 | struct file *file; | 3023 | struct file *file; |
3024 | struct filename filename = { .name = name }; | ||
2959 | 3025 | ||
2960 | nd.root.mnt = mnt; | 3026 | nd.root.mnt = mnt; |
2961 | nd.root.dentry = dentry; | 3027 | nd.root.dentry = dentry; |
@@ -2965,11 +3031,11 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt, | |||
2965 | if (dentry->d_inode->i_op->follow_link && op->intent & LOOKUP_OPEN) | 3031 | if (dentry->d_inode->i_op->follow_link && op->intent & LOOKUP_OPEN) |
2966 | return ERR_PTR(-ELOOP); | 3032 | return ERR_PTR(-ELOOP); |
2967 | 3033 | ||
2968 | file = path_openat(-1, name, &nd, op, flags | LOOKUP_RCU); | 3034 | file = path_openat(-1, &filename, &nd, op, flags | LOOKUP_RCU); |
2969 | if (unlikely(file == ERR_PTR(-ECHILD))) | 3035 | if (unlikely(file == ERR_PTR(-ECHILD))) |
2970 | file = path_openat(-1, name, &nd, op, flags); | 3036 | file = path_openat(-1, &filename, &nd, op, flags); |
2971 | if (unlikely(file == ERR_PTR(-ESTALE))) | 3037 | if (unlikely(file == ERR_PTR(-ESTALE))) |
2972 | file = path_openat(-1, name, &nd, op, flags | LOOKUP_REVAL); | 3038 | file = path_openat(-1, &filename, &nd, op, flags | LOOKUP_REVAL); |
2973 | return file; | 3039 | return file; |
2974 | } | 3040 | } |
2975 | 3041 | ||
@@ -3044,11 +3110,11 @@ EXPORT_SYMBOL(done_path_create); | |||
3044 | 3110 | ||
3045 | struct dentry *user_path_create(int dfd, const char __user *pathname, struct path *path, int is_dir) | 3111 | struct dentry *user_path_create(int dfd, const char __user *pathname, struct path *path, int is_dir) |
3046 | { | 3112 | { |
3047 | char *tmp = getname(pathname); | 3113 | struct filename *tmp = getname(pathname); |
3048 | struct dentry *res; | 3114 | struct dentry *res; |
3049 | if (IS_ERR(tmp)) | 3115 | if (IS_ERR(tmp)) |
3050 | return ERR_CAST(tmp); | 3116 | return ERR_CAST(tmp); |
3051 | res = kern_path_create(dfd, tmp, path, is_dir); | 3117 | res = kern_path_create(dfd, tmp->name, path, is_dir); |
3052 | putname(tmp); | 3118 | putname(tmp); |
3053 | return res; | 3119 | return res; |
3054 | } | 3120 | } |
@@ -3253,13 +3319,13 @@ out: | |||
3253 | static long do_rmdir(int dfd, const char __user *pathname) | 3319 | static long do_rmdir(int dfd, const char __user *pathname) |
3254 | { | 3320 | { |
3255 | int error = 0; | 3321 | int error = 0; |
3256 | char * name; | 3322 | struct filename *name; |
3257 | struct dentry *dentry; | 3323 | struct dentry *dentry; |
3258 | struct nameidata nd; | 3324 | struct nameidata nd; |
3259 | 3325 | ||
3260 | error = user_path_parent(dfd, pathname, &nd, &name); | 3326 | name = user_path_parent(dfd, pathname, &nd); |
3261 | if (error) | 3327 | if (IS_ERR(name)) |
3262 | return error; | 3328 | return PTR_ERR(name); |
3263 | 3329 | ||
3264 | switch(nd.last_type) { | 3330 | switch(nd.last_type) { |
3265 | case LAST_DOTDOT: | 3331 | case LAST_DOTDOT: |
@@ -3348,14 +3414,14 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) | |||
3348 | static long do_unlinkat(int dfd, const char __user *pathname) | 3414 | static long do_unlinkat(int dfd, const char __user *pathname) |
3349 | { | 3415 | { |
3350 | int error; | 3416 | int error; |
3351 | char *name; | 3417 | struct filename *name; |
3352 | struct dentry *dentry; | 3418 | struct dentry *dentry; |
3353 | struct nameidata nd; | 3419 | struct nameidata nd; |
3354 | struct inode *inode = NULL; | 3420 | struct inode *inode = NULL; |
3355 | 3421 | ||
3356 | error = user_path_parent(dfd, pathname, &nd, &name); | 3422 | name = user_path_parent(dfd, pathname, &nd); |
3357 | if (error) | 3423 | if (IS_ERR(name)) |
3358 | return error; | 3424 | return PTR_ERR(name); |
3359 | 3425 | ||
3360 | error = -EISDIR; | 3426 | error = -EISDIR; |
3361 | if (nd.last_type != LAST_NORM) | 3427 | if (nd.last_type != LAST_NORM) |
@@ -3439,7 +3505,7 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname, | |||
3439 | int, newdfd, const char __user *, newname) | 3505 | int, newdfd, const char __user *, newname) |
3440 | { | 3506 | { |
3441 | int error; | 3507 | int error; |
3442 | char *from; | 3508 | struct filename *from; |
3443 | struct dentry *dentry; | 3509 | struct dentry *dentry; |
3444 | struct path path; | 3510 | struct path path; |
3445 | 3511 | ||
@@ -3452,9 +3518,9 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname, | |||
3452 | if (IS_ERR(dentry)) | 3518 | if (IS_ERR(dentry)) |
3453 | goto out_putname; | 3519 | goto out_putname; |
3454 | 3520 | ||
3455 | error = security_path_symlink(&path, dentry, from); | 3521 | error = security_path_symlink(&path, dentry, from->name); |
3456 | if (!error) | 3522 | if (!error) |
3457 | error = vfs_symlink(path.dentry->d_inode, dentry, from); | 3523 | error = vfs_symlink(path.dentry->d_inode, dentry, from->name); |
3458 | done_path_create(&path, dentry); | 3524 | done_path_create(&path, dentry); |
3459 | out_putname: | 3525 | out_putname: |
3460 | putname(from); | 3526 | putname(from); |
@@ -3734,17 +3800,21 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, | |||
3734 | struct dentry *old_dentry, *new_dentry; | 3800 | struct dentry *old_dentry, *new_dentry; |
3735 | struct dentry *trap; | 3801 | struct dentry *trap; |
3736 | struct nameidata oldnd, newnd; | 3802 | struct nameidata oldnd, newnd; |
3737 | char *from; | 3803 | struct filename *from; |
3738 | char *to; | 3804 | struct filename *to; |
3739 | int error; | 3805 | int error; |
3740 | 3806 | ||
3741 | error = user_path_parent(olddfd, oldname, &oldnd, &from); | 3807 | from = user_path_parent(olddfd, oldname, &oldnd); |
3742 | if (error) | 3808 | if (IS_ERR(from)) { |
3809 | error = PTR_ERR(from); | ||
3743 | goto exit; | 3810 | goto exit; |
3811 | } | ||
3744 | 3812 | ||
3745 | error = user_path_parent(newdfd, newname, &newnd, &to); | 3813 | to = user_path_parent(newdfd, newname, &newnd); |
3746 | if (error) | 3814 | if (IS_ERR(to)) { |
3815 | error = PTR_ERR(to); | ||
3747 | goto exit1; | 3816 | goto exit1; |
3817 | } | ||
3748 | 3818 | ||
3749 | error = -EXDEV; | 3819 | error = -EXDEV; |
3750 | if (oldnd.path.mnt != newnd.path.mnt) | 3820 | if (oldnd.path.mnt != newnd.path.mnt) |
@@ -3968,7 +4038,6 @@ EXPORT_SYMBOL(follow_down_one); | |||
3968 | EXPORT_SYMBOL(follow_down); | 4038 | EXPORT_SYMBOL(follow_down); |
3969 | EXPORT_SYMBOL(follow_up); | 4039 | EXPORT_SYMBOL(follow_up); |
3970 | EXPORT_SYMBOL(get_write_access); /* nfsd */ | 4040 | EXPORT_SYMBOL(get_write_access); /* nfsd */ |
3971 | EXPORT_SYMBOL(getname); | ||
3972 | EXPORT_SYMBOL(lock_rename); | 4041 | EXPORT_SYMBOL(lock_rename); |
3973 | EXPORT_SYMBOL(lookup_one_len); | 4042 | EXPORT_SYMBOL(lookup_one_len); |
3974 | EXPORT_SYMBOL(page_follow_link_light); | 4043 | EXPORT_SYMBOL(page_follow_link_light); |
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); |
@@ -478,7 +478,7 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode) | |||
478 | 478 | ||
479 | file = fget(fd); | 479 | file = fget(fd); |
480 | if (file) { | 480 | if (file) { |
481 | audit_inode(NULL, file->f_path.dentry); | 481 | audit_inode(NULL, file->f_path.dentry, 0); |
482 | err = chmod_common(&file->f_path, mode); | 482 | err = chmod_common(&file->f_path, mode); |
483 | fput(file); | 483 | fput(file); |
484 | } | 484 | } |
@@ -588,7 +588,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group) | |||
588 | error = mnt_want_write_file(f.file); | 588 | error = mnt_want_write_file(f.file); |
589 | if (error) | 589 | if (error) |
590 | goto out_fput; | 590 | goto out_fput; |
591 | audit_inode(NULL, f.file->f_path.dentry); | 591 | audit_inode(NULL, f.file->f_path.dentry, 0); |
592 | error = chown_common(&f.file->f_path, user, group); | 592 | error = chown_common(&f.file->f_path, user, group); |
593 | mnt_drop_write_file(f.file); | 593 | mnt_drop_write_file(f.file); |
594 | out_fput: | 594 | out_fput: |
@@ -859,6 +859,24 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o | |||
859 | } | 859 | } |
860 | 860 | ||
861 | /** | 861 | /** |
862 | * file_open_name - open file and return file pointer | ||
863 | * | ||
864 | * @name: struct filename containing path to open | ||
865 | * @flags: open flags as per the open(2) second argument | ||
866 | * @mode: mode for the new file if O_CREAT is set, else ignored | ||
867 | * | ||
868 | * This is the helper to open a file from kernelspace if you really | ||
869 | * have to. But in generally you should not do this, so please move | ||
870 | * along, nothing to see here.. | ||
871 | */ | ||
872 | struct file *file_open_name(struct filename *name, int flags, umode_t mode) | ||
873 | { | ||
874 | struct open_flags op; | ||
875 | int lookup = build_open_flags(flags, mode, &op); | ||
876 | return do_filp_open(AT_FDCWD, name, &op, lookup); | ||
877 | } | ||
878 | |||
879 | /** | ||
862 | * filp_open - open file and return file pointer | 880 | * filp_open - open file and return file pointer |
863 | * | 881 | * |
864 | * @filename: path to open | 882 | * @filename: path to open |
@@ -871,9 +889,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o | |||
871 | */ | 889 | */ |
872 | struct file *filp_open(const char *filename, int flags, umode_t mode) | 890 | struct file *filp_open(const char *filename, int flags, umode_t mode) |
873 | { | 891 | { |
874 | struct open_flags op; | 892 | struct filename name = {.name = filename}; |
875 | int lookup = build_open_flags(flags, mode, &op); | 893 | return file_open_name(&name, flags, mode); |
876 | return do_filp_open(AT_FDCWD, filename, &op, lookup); | ||
877 | } | 894 | } |
878 | EXPORT_SYMBOL(filp_open); | 895 | EXPORT_SYMBOL(filp_open); |
879 | 896 | ||
@@ -895,7 +912,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) | |||
895 | { | 912 | { |
896 | struct open_flags op; | 913 | struct open_flags op; |
897 | int lookup = build_open_flags(flags, mode, &op); | 914 | int lookup = build_open_flags(flags, mode, &op); |
898 | char *tmp = getname(filename); | 915 | struct filename *tmp = getname(filename); |
899 | int fd = PTR_ERR(tmp); | 916 | int fd = PTR_ERR(tmp); |
900 | 917 | ||
901 | if (!IS_ERR(tmp)) { | 918 | if (!IS_ERR(tmp)) { |
diff --git a/fs/proc/base.c b/fs/proc/base.c index ef5c84be66f9..144a96732dd7 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -2258,7 +2258,8 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd) | |||
2258 | pid_t tgid = task_tgid_nr_ns(current, ns); | 2258 | pid_t tgid = task_tgid_nr_ns(current, ns); |
2259 | char *name = ERR_PTR(-ENOENT); | 2259 | char *name = ERR_PTR(-ENOENT); |
2260 | if (tgid) { | 2260 | if (tgid) { |
2261 | name = __getname(); | 2261 | /* 11 for max length of signed int in decimal + NULL term */ |
2262 | name = kmalloc(12, GFP_KERNEL); | ||
2262 | if (!name) | 2263 | if (!name) |
2263 | name = ERR_PTR(-ENOMEM); | 2264 | name = ERR_PTR(-ENOMEM); |
2264 | else | 2265 | else |
@@ -2273,7 +2274,7 @@ static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd, | |||
2273 | { | 2274 | { |
2274 | char *s = nd_get_link(nd); | 2275 | char *s = nd_get_link(nd); |
2275 | if (!IS_ERR(s)) | 2276 | if (!IS_ERR(s)) |
2276 | __putname(s); | 2277 | kfree(s); |
2277 | } | 2278 | } |
2278 | 2279 | ||
2279 | static const struct inode_operations proc_self_inode_operations = { | 2280 | static const struct inode_operations proc_self_inode_operations = { |
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/fs/xattr.c b/fs/xattr.c index 1780f062dbaf..e164dddb8e96 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
@@ -412,7 +412,7 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name, | |||
412 | if (!f.file) | 412 | if (!f.file) |
413 | return error; | 413 | return error; |
414 | dentry = f.file->f_path.dentry; | 414 | dentry = f.file->f_path.dentry; |
415 | audit_inode(NULL, dentry); | 415 | audit_inode(NULL, dentry, 0); |
416 | error = mnt_want_write_file(f.file); | 416 | error = mnt_want_write_file(f.file); |
417 | if (!error) { | 417 | if (!error) { |
418 | error = setxattr(dentry, name, value, size, flags); | 418 | error = setxattr(dentry, name, value, size, flags); |
@@ -507,7 +507,7 @@ SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name, | |||
507 | 507 | ||
508 | if (!f.file) | 508 | if (!f.file) |
509 | return error; | 509 | return error; |
510 | audit_inode(NULL, f.file->f_path.dentry); | 510 | audit_inode(NULL, f.file->f_path.dentry, 0); |
511 | error = getxattr(f.file->f_path.dentry, name, value, size); | 511 | error = getxattr(f.file->f_path.dentry, name, value, size); |
512 | fdput(f); | 512 | fdput(f); |
513 | return error; | 513 | return error; |
@@ -586,7 +586,7 @@ SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size) | |||
586 | 586 | ||
587 | if (!f.file) | 587 | if (!f.file) |
588 | return error; | 588 | return error; |
589 | audit_inode(NULL, f.file->f_path.dentry); | 589 | audit_inode(NULL, f.file->f_path.dentry, 0); |
590 | error = listxattr(f.file->f_path.dentry, list, size); | 590 | error = listxattr(f.file->f_path.dentry, list, size); |
591 | fdput(f); | 591 | fdput(f); |
592 | return error; | 592 | return error; |
@@ -655,7 +655,7 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name) | |||
655 | if (!f.file) | 655 | if (!f.file) |
656 | return error; | 656 | return error; |
657 | dentry = f.file->f_path.dentry; | 657 | dentry = f.file->f_path.dentry; |
658 | audit_inode(NULL, dentry); | 658 | audit_inode(NULL, dentry, 0); |
659 | error = mnt_want_write_file(f.file); | 659 | error = mnt_want_write_file(f.file); |
660 | if (!error) { | 660 | if (!error) { |
661 | error = removexattr(dentry, name); | 661 | error = removexattr(dentry, name); |
diff --git a/include/linux/audit.h b/include/linux/audit.h index 2c83e5f7edb1..e5884f950b4b 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
@@ -452,6 +452,16 @@ struct audit_field { | |||
452 | extern int __init audit_register_class(int class, unsigned *list); | 452 | extern int __init audit_register_class(int class, unsigned *list); |
453 | extern int audit_classify_syscall(int abi, unsigned syscall); | 453 | extern int audit_classify_syscall(int abi, unsigned syscall); |
454 | extern int audit_classify_arch(int arch); | 454 | extern int audit_classify_arch(int arch); |
455 | |||
456 | /* audit_names->type values */ | ||
457 | #define AUDIT_TYPE_UNKNOWN 0 /* we don't know yet */ | ||
458 | #define AUDIT_TYPE_NORMAL 1 /* a "normal" audit record */ | ||
459 | #define AUDIT_TYPE_PARENT 2 /* a parent audit record */ | ||
460 | #define AUDIT_TYPE_CHILD_DELETE 3 /* a child being deleted */ | ||
461 | #define AUDIT_TYPE_CHILD_CREATE 4 /* a child being created */ | ||
462 | |||
463 | struct filename; | ||
464 | |||
455 | #ifdef CONFIG_AUDITSYSCALL | 465 | #ifdef CONFIG_AUDITSYSCALL |
456 | /* These are defined in auditsc.c */ | 466 | /* These are defined in auditsc.c */ |
457 | /* Public API */ | 467 | /* Public API */ |
@@ -461,11 +471,14 @@ extern void __audit_syscall_entry(int arch, | |||
461 | int major, unsigned long a0, unsigned long a1, | 471 | int major, unsigned long a0, unsigned long a1, |
462 | unsigned long a2, unsigned long a3); | 472 | unsigned long a2, unsigned long a3); |
463 | extern void __audit_syscall_exit(int ret_success, long ret_value); | 473 | extern void __audit_syscall_exit(int ret_success, long ret_value); |
464 | extern void __audit_getname(const char *name); | 474 | extern struct filename *__audit_reusename(const __user char *uptr); |
465 | extern void audit_putname(const char *name); | 475 | extern void __audit_getname(struct filename *name); |
466 | extern void __audit_inode(const char *name, const struct dentry *dentry); | 476 | extern void audit_putname(struct filename *name); |
467 | extern void __audit_inode_child(const struct dentry *dentry, | 477 | extern void __audit_inode(struct filename *name, const struct dentry *dentry, |
468 | const struct inode *parent); | 478 | unsigned int parent); |
479 | extern void __audit_inode_child(const struct inode *parent, | ||
480 | const struct dentry *dentry, | ||
481 | const unsigned char type); | ||
469 | extern void __audit_seccomp(unsigned long syscall, long signr, int code); | 482 | extern void __audit_seccomp(unsigned long syscall, long signr, int code); |
470 | extern void __audit_ptrace(struct task_struct *t); | 483 | extern void __audit_ptrace(struct task_struct *t); |
471 | 484 | ||
@@ -495,19 +508,27 @@ static inline void audit_syscall_exit(void *pt_regs) | |||
495 | __audit_syscall_exit(success, return_code); | 508 | __audit_syscall_exit(success, return_code); |
496 | } | 509 | } |
497 | } | 510 | } |
498 | static inline void audit_getname(const char *name) | 511 | static inline struct filename *audit_reusename(const __user char *name) |
512 | { | ||
513 | if (unlikely(!audit_dummy_context())) | ||
514 | return __audit_reusename(name); | ||
515 | return NULL; | ||
516 | } | ||
517 | static inline void audit_getname(struct filename *name) | ||
499 | { | 518 | { |
500 | if (unlikely(!audit_dummy_context())) | 519 | if (unlikely(!audit_dummy_context())) |
501 | __audit_getname(name); | 520 | __audit_getname(name); |
502 | } | 521 | } |
503 | static inline void audit_inode(const char *name, const struct dentry *dentry) { | 522 | static inline void audit_inode(struct filename *name, const struct dentry *dentry, |
523 | unsigned int parent) { | ||
504 | if (unlikely(!audit_dummy_context())) | 524 | if (unlikely(!audit_dummy_context())) |
505 | __audit_inode(name, dentry); | 525 | __audit_inode(name, dentry, parent); |
506 | } | 526 | } |
507 | static inline void audit_inode_child(const struct dentry *dentry, | 527 | static inline void audit_inode_child(const struct inode *parent, |
508 | const struct inode *parent) { | 528 | const struct dentry *dentry, |
529 | const unsigned char type) { | ||
509 | if (unlikely(!audit_dummy_context())) | 530 | if (unlikely(!audit_dummy_context())) |
510 | __audit_inode_child(dentry, parent); | 531 | __audit_inode_child(parent, dentry, type); |
511 | } | 532 | } |
512 | void audit_core_dumps(long signr); | 533 | void audit_core_dumps(long signr); |
513 | 534 | ||
@@ -651,19 +672,29 @@ static inline int audit_dummy_context(void) | |||
651 | { | 672 | { |
652 | return 1; | 673 | return 1; |
653 | } | 674 | } |
654 | static inline void audit_getname(const char *name) | 675 | static inline struct filename *audit_reusename(const __user char *name) |
676 | { | ||
677 | return NULL; | ||
678 | } | ||
679 | static inline void audit_getname(struct filename *name) | ||
655 | { } | 680 | { } |
656 | static inline void audit_putname(const char *name) | 681 | static inline void audit_putname(struct filename *name) |
657 | { } | 682 | { } |
658 | static inline void __audit_inode(const char *name, const struct dentry *dentry) | 683 | static inline void __audit_inode(struct filename *name, |
684 | const struct dentry *dentry, | ||
685 | unsigned int parent) | ||
659 | { } | 686 | { } |
660 | static inline void __audit_inode_child(const struct dentry *dentry, | 687 | static inline void __audit_inode_child(const struct inode *parent, |
661 | const struct inode *parent) | 688 | const struct dentry *dentry, |
689 | const unsigned char type) | ||
662 | { } | 690 | { } |
663 | static inline void audit_inode(const char *name, const struct dentry *dentry) | 691 | static inline void audit_inode(struct filename *name, |
692 | const struct dentry *dentry, | ||
693 | unsigned int parent) | ||
664 | { } | 694 | { } |
665 | static inline void audit_inode_child(const struct dentry *dentry, | 695 | static inline void audit_inode_child(const struct inode *parent, |
666 | const struct inode *parent) | 696 | const struct dentry *dentry, |
697 | const unsigned char type) | ||
667 | { } | 698 | { } |
668 | static inline void audit_core_dumps(long signr) | 699 | static inline void audit_core_dumps(long signr) |
669 | { } | 700 | { } |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 8ef2fc9f1f08..65fbf571023f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2196,6 +2196,13 @@ 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 audit_names; | ||
2200 | struct filename { | ||
2201 | const char *name; /* pointer to actual string */ | ||
2202 | const __user char *uptr; /* original userland pointer */ | ||
2203 | struct audit_names *aname; | ||
2204 | bool separate; /* should "name" be freed? */ | ||
2205 | }; | ||
2199 | 2206 | ||
2200 | extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs, | 2207 | extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs, |
2201 | struct file *filp); | 2208 | struct file *filp); |
@@ -2203,12 +2210,15 @@ extern int do_fallocate(struct file *file, int mode, loff_t offset, | |||
2203 | loff_t len); | 2210 | loff_t len); |
2204 | extern long do_sys_open(int dfd, const char __user *filename, int flags, | 2211 | extern long do_sys_open(int dfd, const char __user *filename, int flags, |
2205 | umode_t mode); | 2212 | umode_t mode); |
2213 | extern struct file *file_open_name(struct filename *, int, umode_t); | ||
2206 | extern struct file *filp_open(const char *, int, umode_t); | 2214 | extern struct file *filp_open(const char *, int, umode_t); |
2207 | extern struct file *file_open_root(struct dentry *, struct vfsmount *, | 2215 | extern struct file *file_open_root(struct dentry *, struct vfsmount *, |
2208 | const char *, int); | 2216 | const char *, int); |
2209 | extern struct file * dentry_open(const struct path *, int, const struct cred *); | 2217 | extern struct file * dentry_open(const struct path *, int, const struct cred *); |
2210 | extern int filp_close(struct file *, fl_owner_t id); | 2218 | extern int filp_close(struct file *, fl_owner_t id); |
2211 | extern char * getname(const char __user *); | 2219 | |
2220 | extern struct filename *getname(const char __user *); | ||
2221 | |||
2212 | enum { | 2222 | enum { |
2213 | FILE_CREATED = 1, | 2223 | FILE_CREATED = 1, |
2214 | FILE_OPENED = 2 | 2224 | FILE_OPENED = 2 |
@@ -2228,13 +2238,14 @@ extern void __init vfs_caches_init(unsigned long); | |||
2228 | 2238 | ||
2229 | extern struct kmem_cache *names_cachep; | 2239 | extern struct kmem_cache *names_cachep; |
2230 | 2240 | ||
2231 | #define __getname_gfp(gfp) kmem_cache_alloc(names_cachep, (gfp)) | 2241 | extern void final_putname(struct filename *name); |
2232 | #define __getname() __getname_gfp(GFP_KERNEL) | 2242 | |
2243 | #define __getname() kmem_cache_alloc(names_cachep, GFP_KERNEL) | ||
2233 | #define __putname(name) kmem_cache_free(names_cachep, (void *)(name)) | 2244 | #define __putname(name) kmem_cache_free(names_cachep, (void *)(name)) |
2234 | #ifndef CONFIG_AUDITSYSCALL | 2245 | #ifndef CONFIG_AUDITSYSCALL |
2235 | #define putname(name) __putname(name) | 2246 | #define putname(name) final_putname(name) |
2236 | #else | 2247 | #else |
2237 | extern void putname(const char *name); | 2248 | extern void putname(struct filename *name); |
2238 | #endif | 2249 | #endif |
2239 | 2250 | ||
2240 | #ifdef CONFIG_BLOCK | 2251 | #ifdef CONFIG_BLOCK |
diff --git a/include/linux/fsnotify.h b/include/linux/fsnotify.h index a6dfe6944564..0fbfb4646d1b 100644 --- a/include/linux/fsnotify.h +++ b/include/linux/fsnotify.h | |||
@@ -109,7 +109,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir, | |||
109 | 109 | ||
110 | if (source) | 110 | if (source) |
111 | fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0); | 111 | fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0); |
112 | audit_inode_child(moved, new_dir); | 112 | audit_inode_child(new_dir, moved, AUDIT_TYPE_CHILD_CREATE); |
113 | } | 113 | } |
114 | 114 | ||
115 | /* | 115 | /* |
@@ -155,7 +155,7 @@ static inline void fsnotify_inoderemove(struct inode *inode) | |||
155 | */ | 155 | */ |
156 | static inline void fsnotify_create(struct inode *inode, struct dentry *dentry) | 156 | static inline void fsnotify_create(struct inode *inode, struct dentry *dentry) |
157 | { | 157 | { |
158 | audit_inode_child(dentry, inode); | 158 | audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE); |
159 | 159 | ||
160 | fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0); | 160 | fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0); |
161 | } | 161 | } |
@@ -168,7 +168,7 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry) | |||
168 | static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry) | 168 | static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry) |
169 | { | 169 | { |
170 | fsnotify_link_count(inode); | 170 | fsnotify_link_count(inode); |
171 | audit_inode_child(new_dentry, dir); | 171 | audit_inode_child(dir, new_dentry, AUDIT_TYPE_CHILD_CREATE); |
172 | 172 | ||
173 | fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, new_dentry->d_name.name, 0); | 173 | fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, new_dentry->d_name.name, 0); |
174 | } | 174 | } |
@@ -181,7 +181,7 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry) | |||
181 | __u32 mask = (FS_CREATE | FS_ISDIR); | 181 | __u32 mask = (FS_CREATE | FS_ISDIR); |
182 | struct inode *d_inode = dentry->d_inode; | 182 | struct inode *d_inode = dentry->d_inode; |
183 | 183 | ||
184 | audit_inode_child(dentry, inode); | 184 | audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE); |
185 | 185 | ||
186 | fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0); | 186 | fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0); |
187 | } | 187 | } |
diff --git a/init/do_mounts.c b/init/do_mounts.c index d3f0aeed2d39..f8a66424360d 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c | |||
@@ -353,8 +353,9 @@ static int __init do_mount_root(char *name, char *fs, int flags, void *data) | |||
353 | 353 | ||
354 | void __init mount_block_root(char *name, int flags) | 354 | void __init mount_block_root(char *name, int flags) |
355 | { | 355 | { |
356 | char *fs_names = __getname_gfp(GFP_KERNEL | 356 | struct page *page = alloc_page(GFP_KERNEL | |
357 | | __GFP_NOTRACK_FALSE_POSITIVE); | 357 | __GFP_NOTRACK_FALSE_POSITIVE); |
358 | char *fs_names = page_address(page); | ||
358 | char *p; | 359 | char *p; |
359 | #ifdef CONFIG_BLOCK | 360 | #ifdef CONFIG_BLOCK |
360 | char b[BDEVNAME_SIZE]; | 361 | char b[BDEVNAME_SIZE]; |
@@ -406,7 +407,7 @@ retry: | |||
406 | #endif | 407 | #endif |
407 | panic("VFS: Unable to mount root fs on %s", b); | 408 | panic("VFS: Unable to mount root fs on %s", b); |
408 | out: | 409 | out: |
409 | putname(fs_names); | 410 | put_page(page); |
410 | } | 411 | } |
411 | 412 | ||
412 | #ifdef CONFIG_ROOT_NFS | 413 | #ifdef CONFIG_ROOT_NFS |
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 6b97e2466fad..71a3ca18c873 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); | 807 | audit_inode(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); | 827 | audit_inode(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; |
@@ -978,7 +979,7 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr, | |||
978 | goto out_fput; | 979 | goto out_fput; |
979 | } | 980 | } |
980 | info = MQUEUE_I(inode); | 981 | info = MQUEUE_I(inode); |
981 | audit_inode(NULL, f.file->f_path.dentry); | 982 | audit_inode(NULL, f.file->f_path.dentry, 0); |
982 | 983 | ||
983 | if (unlikely(!(f.file->f_mode & FMODE_WRITE))) { | 984 | if (unlikely(!(f.file->f_mode & FMODE_WRITE))) { |
984 | ret = -EBADF; | 985 | ret = -EBADF; |
@@ -1094,7 +1095,7 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr, | |||
1094 | goto out_fput; | 1095 | goto out_fput; |
1095 | } | 1096 | } |
1096 | info = MQUEUE_I(inode); | 1097 | info = MQUEUE_I(inode); |
1097 | audit_inode(NULL, f.file->f_path.dentry); | 1098 | audit_inode(NULL, f.file->f_path.dentry, 0); |
1098 | 1099 | ||
1099 | if (unlikely(!(f.file->f_mode & FMODE_READ))) { | 1100 | if (unlikely(!(f.file->f_mode & FMODE_READ))) { |
1100 | ret = -EBADF; | 1101 | ret = -EBADF; |
diff --git a/kernel/acct.c b/kernel/acct.c index 6cd7529c9e6a..051e071a06e7 100644 --- a/kernel/acct.c +++ b/kernel/acct.c | |||
@@ -193,7 +193,7 @@ static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file, | |||
193 | } | 193 | } |
194 | } | 194 | } |
195 | 195 | ||
196 | static int acct_on(char *name) | 196 | static int acct_on(struct filename *pathname) |
197 | { | 197 | { |
198 | struct file *file; | 198 | struct file *file; |
199 | struct vfsmount *mnt; | 199 | struct vfsmount *mnt; |
@@ -201,7 +201,7 @@ static int acct_on(char *name) | |||
201 | struct bsd_acct_struct *acct = NULL; | 201 | struct bsd_acct_struct *acct = NULL; |
202 | 202 | ||
203 | /* Difference from BSD - they don't do O_APPEND */ | 203 | /* Difference from BSD - they don't do O_APPEND */ |
204 | file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0); | 204 | file = file_open_name(pathname, O_WRONLY|O_APPEND|O_LARGEFILE, 0); |
205 | if (IS_ERR(file)) | 205 | if (IS_ERR(file)) |
206 | return PTR_ERR(file); | 206 | return PTR_ERR(file); |
207 | 207 | ||
@@ -260,7 +260,7 @@ 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); |
diff --git a/kernel/audit.h b/kernel/audit.h index 9eb3d79482b6..d51cba868e1b 100644 --- a/kernel/audit.h +++ b/kernel/audit.h | |||
@@ -74,12 +74,15 @@ static inline int audit_hash_ino(u32 ino) | |||
74 | return (ino & (AUDIT_INODE_BUCKETS-1)); | 74 | return (ino & (AUDIT_INODE_BUCKETS-1)); |
75 | } | 75 | } |
76 | 76 | ||
77 | /* Indicates that audit should log the full pathname. */ | ||
78 | #define AUDIT_NAME_FULL -1 | ||
79 | |||
77 | extern int audit_match_class(int class, unsigned syscall); | 80 | extern int audit_match_class(int class, unsigned syscall); |
78 | extern int audit_comparator(const u32 left, const u32 op, const u32 right); | 81 | extern int audit_comparator(const u32 left, const u32 op, const u32 right); |
79 | extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right); | 82 | extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right); |
80 | extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right); | 83 | extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right); |
81 | extern int audit_compare_dname_path(const char *dname, const char *path, | 84 | extern int parent_len(const char *path); |
82 | int *dirlen); | 85 | extern int audit_compare_dname_path(const char *dname, const char *path, int plen); |
83 | extern struct sk_buff * audit_make_reply(int pid, int seq, int type, | 86 | extern struct sk_buff * audit_make_reply(int pid, int seq, int type, |
84 | int done, int multi, | 87 | int done, int multi, |
85 | const void *payload, int size); | 88 | const void *payload, int size); |
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index 1c22ec3d87bc..9a9ae6e3d290 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c | |||
@@ -265,7 +265,8 @@ static void audit_update_watch(struct audit_parent *parent, | |||
265 | /* Run all of the watches on this parent looking for the one that | 265 | /* Run all of the watches on this parent looking for the one that |
266 | * matches the given dname */ | 266 | * matches the given dname */ |
267 | list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) { | 267 | list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) { |
268 | if (audit_compare_dname_path(dname, owatch->path, NULL)) | 268 | if (audit_compare_dname_path(dname, owatch->path, |
269 | AUDIT_NAME_FULL)) | ||
269 | continue; | 270 | continue; |
270 | 271 | ||
271 | /* If the update involves invalidating rules, do the inode-based | 272 | /* If the update involves invalidating rules, do the inode-based |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index c4bcdbaf4d4d..7f19f23d38a3 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
@@ -1298,41 +1298,60 @@ int audit_gid_comparator(kgid_t left, u32 op, kgid_t right) | |||
1298 | } | 1298 | } |
1299 | } | 1299 | } |
1300 | 1300 | ||
1301 | /* Compare given dentry name with last component in given path, | 1301 | /** |
1302 | * return of 0 indicates a match. */ | 1302 | * parent_len - find the length of the parent portion of a pathname |
1303 | int audit_compare_dname_path(const char *dname, const char *path, | 1303 | * @path: pathname of which to determine length |
1304 | int *dirlen) | 1304 | */ |
1305 | int parent_len(const char *path) | ||
1305 | { | 1306 | { |
1306 | int dlen, plen; | 1307 | int plen; |
1307 | const char *p; | 1308 | const char *p; |
1308 | 1309 | ||
1309 | if (!dname || !path) | ||
1310 | return 1; | ||
1311 | |||
1312 | dlen = strlen(dname); | ||
1313 | plen = strlen(path); | 1310 | plen = strlen(path); |
1314 | if (plen < dlen) | 1311 | |
1315 | return 1; | 1312 | if (plen == 0) |
1313 | return plen; | ||
1316 | 1314 | ||
1317 | /* disregard trailing slashes */ | 1315 | /* disregard trailing slashes */ |
1318 | p = path + plen - 1; | 1316 | p = path + plen - 1; |
1319 | while ((*p == '/') && (p > path)) | 1317 | while ((*p == '/') && (p > path)) |
1320 | p--; | 1318 | p--; |
1321 | 1319 | ||
1322 | /* find last path component */ | 1320 | /* walk backward until we find the next slash or hit beginning */ |
1323 | p = p - dlen + 1; | 1321 | while ((*p != '/') && (p > path)) |
1324 | if (p < path) | 1322 | p--; |
1323 | |||
1324 | /* did we find a slash? Then increment to include it in path */ | ||
1325 | if (*p == '/') | ||
1326 | p++; | ||
1327 | |||
1328 | return p - path; | ||
1329 | } | ||
1330 | |||
1331 | /** | ||
1332 | * audit_compare_dname_path - compare given dentry name with last component in | ||
1333 | * given path. Return of 0 indicates a match. | ||
1334 | * @dname: dentry name that we're comparing | ||
1335 | * @path: full pathname that we're comparing | ||
1336 | * @parentlen: length of the parent if known. Passing in AUDIT_NAME_FULL | ||
1337 | * here indicates that we must compute this value. | ||
1338 | */ | ||
1339 | int audit_compare_dname_path(const char *dname, const char *path, int parentlen) | ||
1340 | { | ||
1341 | int dlen, pathlen; | ||
1342 | const char *p; | ||
1343 | |||
1344 | dlen = strlen(dname); | ||
1345 | pathlen = strlen(path); | ||
1346 | if (pathlen < dlen) | ||
1325 | return 1; | 1347 | return 1; |
1326 | else if (p > path) { | ||
1327 | if (*--p != '/') | ||
1328 | return 1; | ||
1329 | else | ||
1330 | p++; | ||
1331 | } | ||
1332 | 1348 | ||
1333 | /* return length of path's directory component */ | 1349 | parentlen = parentlen == AUDIT_NAME_FULL ? parent_len(path) : parentlen; |
1334 | if (dirlen) | 1350 | if (pathlen - parentlen != dlen) |
1335 | *dirlen = p - path; | 1351 | return 1; |
1352 | |||
1353 | p = path + parentlen; | ||
1354 | |||
1336 | return strncmp(p, dname, dlen); | 1355 | return strncmp(p, dname, dlen); |
1337 | } | 1356 | } |
1338 | 1357 | ||
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index f4a7756f999c..2f186ed80c40 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -81,9 +81,6 @@ | |||
81 | * a name dynamically and also add those to the list anchored by names_list. */ | 81 | * a name dynamically and also add those to the list anchored by names_list. */ |
82 | #define AUDIT_NAMES 5 | 82 | #define AUDIT_NAMES 5 |
83 | 83 | ||
84 | /* Indicates that audit should log the full pathname. */ | ||
85 | #define AUDIT_NAME_FULL -1 | ||
86 | |||
87 | /* no execve audit message should be longer than this (userspace limits) */ | 84 | /* no execve audit message should be longer than this (userspace limits) */ |
88 | #define MAX_EXECVE_AUDIT_LEN 7500 | 85 | #define MAX_EXECVE_AUDIT_LEN 7500 |
89 | 86 | ||
@@ -106,27 +103,29 @@ struct audit_cap_data { | |||
106 | * 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 |
107 | * pointers at syscall exit time). | 104 | * pointers at syscall exit time). |
108 | * | 105 | * |
109 | * 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 | */ | ||
110 | struct audit_names { | 108 | struct audit_names { |
111 | struct list_head list; /* audit_context->names_list */ | 109 | struct list_head list; /* audit_context->names_list */ |
112 | const char *name; | 110 | struct filename *name; |
113 | unsigned long ino; | 111 | unsigned long ino; |
114 | dev_t dev; | 112 | dev_t dev; |
115 | umode_t mode; | 113 | umode_t mode; |
116 | kuid_t uid; | 114 | kuid_t uid; |
117 | kgid_t gid; | 115 | kgid_t gid; |
118 | dev_t rdev; | 116 | dev_t rdev; |
119 | u32 osid; | 117 | u32 osid; |
120 | struct audit_cap_data fcap; | 118 | struct audit_cap_data fcap; |
121 | unsigned int fcap_ver; | 119 | unsigned int fcap_ver; |
122 | int name_len; /* number of name's characters to log */ | 120 | int name_len; /* number of name's characters to log */ |
123 | bool name_put; /* call __putname() for this name */ | 121 | unsigned char type; /* record type */ |
122 | bool name_put; /* call __putname() for this name */ | ||
124 | /* | 123 | /* |
125 | * 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 |
126 | * names allocated in the task audit context. Thus this name | 125 | * names allocated in the task audit context. Thus this name |
127 | * should be freed on syscall exit | 126 | * should be freed on syscall exit |
128 | */ | 127 | */ |
129 | bool should_free; | 128 | bool should_free; |
130 | }; | 129 | }; |
131 | 130 | ||
132 | struct audit_aux_data { | 131 | struct audit_aux_data { |
@@ -998,7 +997,7 @@ static inline void audit_free_names(struct audit_context *context) | |||
998 | context->ino_count); | 997 | context->ino_count); |
999 | list_for_each_entry(n, &context->names_list, list) { | 998 | list_for_each_entry(n, &context->names_list, list) { |
1000 | printk(KERN_ERR "names[%d] = %p = %s\n", i, | 999 | printk(KERN_ERR "names[%d] = %p = %s\n", i, |
1001 | n->name, n->name ?: "(null)"); | 1000 | n->name, n->name->name ?: "(null)"); |
1002 | } | 1001 | } |
1003 | dump_stack(); | 1002 | dump_stack(); |
1004 | return; | 1003 | return; |
@@ -1555,7 +1554,7 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n, | |||
1555 | case AUDIT_NAME_FULL: | 1554 | case AUDIT_NAME_FULL: |
1556 | /* log the full path */ | 1555 | /* log the full path */ |
1557 | audit_log_format(ab, " name="); | 1556 | audit_log_format(ab, " name="); |
1558 | audit_log_untrustedstring(ab, n->name); | 1557 | audit_log_untrustedstring(ab, n->name->name); |
1559 | break; | 1558 | break; |
1560 | case 0: | 1559 | case 0: |
1561 | /* name was specified as a relative path and the | 1560 | /* name was specified as a relative path and the |
@@ -1565,7 +1564,7 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n, | |||
1565 | default: | 1564 | default: |
1566 | /* log the name's directory component */ | 1565 | /* log the name's directory component */ |
1567 | audit_log_format(ab, " name="); | 1566 | audit_log_format(ab, " name="); |
1568 | audit_log_n_untrustedstring(ab, n->name, | 1567 | audit_log_n_untrustedstring(ab, n->name->name, |
1569 | n->name_len); | 1568 | n->name_len); |
1570 | } | 1569 | } |
1571 | } else | 1570 | } else |
@@ -1995,7 +1994,8 @@ retry: | |||
1995 | #endif | 1994 | #endif |
1996 | } | 1995 | } |
1997 | 1996 | ||
1998 | static struct audit_names *audit_alloc_name(struct audit_context *context) | 1997 | static struct audit_names *audit_alloc_name(struct audit_context *context, |
1998 | unsigned char type) | ||
1999 | { | 1999 | { |
2000 | struct audit_names *aname; | 2000 | struct audit_names *aname; |
2001 | 2001 | ||
@@ -2010,6 +2010,7 @@ static struct audit_names *audit_alloc_name(struct audit_context *context) | |||
2010 | } | 2010 | } |
2011 | 2011 | ||
2012 | aname->ino = (unsigned long)-1; | 2012 | aname->ino = (unsigned long)-1; |
2013 | aname->type = type; | ||
2013 | list_add_tail(&aname->list, &context->names_list); | 2014 | list_add_tail(&aname->list, &context->names_list); |
2014 | 2015 | ||
2015 | context->name_count++; | 2016 | context->name_count++; |
@@ -2020,13 +2021,36 @@ static struct audit_names *audit_alloc_name(struct audit_context *context) | |||
2020 | } | 2021 | } |
2021 | 2022 | ||
2022 | /** | 2023 | /** |
2024 | * audit_reusename - fill out filename with info from existing entry | ||
2025 | * @uptr: userland ptr to pathname | ||
2026 | * | ||
2027 | * Search the audit_names list for the current audit context. If there is an | ||
2028 | * existing entry with a matching "uptr" then return the filename | ||
2029 | * associated with that audit_name. If not, return NULL. | ||
2030 | */ | ||
2031 | struct filename * | ||
2032 | __audit_reusename(const __user char *uptr) | ||
2033 | { | ||
2034 | struct audit_context *context = current->audit_context; | ||
2035 | struct audit_names *n; | ||
2036 | |||
2037 | list_for_each_entry(n, &context->names_list, list) { | ||
2038 | if (!n->name) | ||
2039 | continue; | ||
2040 | if (n->name->uptr == uptr) | ||
2041 | return n->name; | ||
2042 | } | ||
2043 | return NULL; | ||
2044 | } | ||
2045 | |||
2046 | /** | ||
2023 | * audit_getname - add a name to the list | 2047 | * audit_getname - add a name to the list |
2024 | * @name: name to add | 2048 | * @name: name to add |
2025 | * | 2049 | * |
2026 | * Add a name to the list of audit names for this context. | 2050 | * Add a name to the list of audit names for this context. |
2027 | * Called from fs/namei.c:getname(). | 2051 | * Called from fs/namei.c:getname(). |
2028 | */ | 2052 | */ |
2029 | void __audit_getname(const char *name) | 2053 | void __audit_getname(struct filename *name) |
2030 | { | 2054 | { |
2031 | struct audit_context *context = current->audit_context; | 2055 | struct audit_context *context = current->audit_context; |
2032 | struct audit_names *n; | 2056 | struct audit_names *n; |
@@ -2040,13 +2064,19 @@ void __audit_getname(const char *name) | |||
2040 | return; | 2064 | return; |
2041 | } | 2065 | } |
2042 | 2066 | ||
2043 | n = audit_alloc_name(context); | 2067 | #if AUDIT_DEBUG |
2068 | /* The filename _must_ have a populated ->name */ | ||
2069 | BUG_ON(!name->name); | ||
2070 | #endif | ||
2071 | |||
2072 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); | ||
2044 | if (!n) | 2073 | if (!n) |
2045 | return; | 2074 | return; |
2046 | 2075 | ||
2047 | n->name = name; | 2076 | n->name = name; |
2048 | n->name_len = AUDIT_NAME_FULL; | 2077 | n->name_len = AUDIT_NAME_FULL; |
2049 | n->name_put = true; | 2078 | n->name_put = true; |
2079 | name->aname = n; | ||
2050 | 2080 | ||
2051 | if (!context->pwd.dentry) | 2081 | if (!context->pwd.dentry) |
2052 | get_fs_pwd(current->fs, &context->pwd); | 2082 | get_fs_pwd(current->fs, &context->pwd); |
@@ -2059,7 +2089,7 @@ void __audit_getname(const char *name) | |||
2059 | * then we delay the putname until syscall exit. | 2089 | * then we delay the putname until syscall exit. |
2060 | * Called from include/linux/fs.h:putname(). | 2090 | * Called from include/linux/fs.h:putname(). |
2061 | */ | 2091 | */ |
2062 | void audit_putname(const char *name) | 2092 | void audit_putname(struct filename *name) |
2063 | { | 2093 | { |
2064 | struct audit_context *context = current->audit_context; | 2094 | struct audit_context *context = current->audit_context; |
2065 | 2095 | ||
@@ -2074,7 +2104,7 @@ void audit_putname(const char *name) | |||
2074 | 2104 | ||
2075 | list_for_each_entry(n, &context->names_list, list) | 2105 | list_for_each_entry(n, &context->names_list, list) |
2076 | printk(KERN_ERR "name[%d] = %p = %s\n", i, | 2106 | printk(KERN_ERR "name[%d] = %p = %s\n", i, |
2077 | n->name, n->name ?: "(null)"); | 2107 | n->name, n->name->name ?: "(null)"); |
2078 | } | 2108 | } |
2079 | #endif | 2109 | #endif |
2080 | __putname(name); | 2110 | __putname(name); |
@@ -2088,8 +2118,8 @@ void audit_putname(const char *name) | |||
2088 | " put_count=%d\n", | 2118 | " put_count=%d\n", |
2089 | __FILE__, __LINE__, | 2119 | __FILE__, __LINE__, |
2090 | context->serial, context->major, | 2120 | context->serial, context->major, |
2091 | context->in_syscall, name, context->name_count, | 2121 | context->in_syscall, name->name, |
2092 | context->put_count); | 2122 | context->name_count, context->put_count); |
2093 | dump_stack(); | 2123 | dump_stack(); |
2094 | } | 2124 | } |
2095 | } | 2125 | } |
@@ -2132,13 +2162,13 @@ static void audit_copy_inode(struct audit_names *name, const struct dentry *dent | |||
2132 | } | 2162 | } |
2133 | 2163 | ||
2134 | /** | 2164 | /** |
2135 | * audit_inode - store the inode and device from a lookup | 2165 | * __audit_inode - store the inode and device from a lookup |
2136 | * @name: name being audited | 2166 | * @name: name being audited |
2137 | * @dentry: dentry being audited | 2167 | * @dentry: dentry being audited |
2138 | * | 2168 | * @parent: does this dentry represent the parent? |
2139 | * Called from fs/namei.c:path_lookup(). | ||
2140 | */ | 2169 | */ |
2141 | void __audit_inode(const char *name, const struct dentry *dentry) | 2170 | void __audit_inode(struct filename *name, const struct dentry *dentry, |
2171 | unsigned int parent) | ||
2142 | { | 2172 | { |
2143 | struct audit_context *context = current->audit_context; | 2173 | struct audit_context *context = current->audit_context; |
2144 | const struct inode *inode = dentry->d_inode; | 2174 | const struct inode *inode = dentry->d_inode; |
@@ -2147,24 +2177,69 @@ void __audit_inode(const char *name, const struct dentry *dentry) | |||
2147 | if (!context->in_syscall) | 2177 | if (!context->in_syscall) |
2148 | return; | 2178 | return; |
2149 | 2179 | ||
2180 | if (!name) | ||
2181 | goto out_alloc; | ||
2182 | |||
2183 | #if AUDIT_DEBUG | ||
2184 | /* The struct filename _must_ have a populated ->name */ | ||
2185 | BUG_ON(!name->name); | ||
2186 | #endif | ||
2187 | /* | ||
2188 | * If we have a pointer to an audit_names entry already, then we can | ||
2189 | * just use it directly if the type is correct. | ||
2190 | */ | ||
2191 | n = name->aname; | ||
2192 | if (n) { | ||
2193 | if (parent) { | ||
2194 | if (n->type == AUDIT_TYPE_PARENT || | ||
2195 | n->type == AUDIT_TYPE_UNKNOWN) | ||
2196 | goto out; | ||
2197 | } else { | ||
2198 | if (n->type != AUDIT_TYPE_PARENT) | ||
2199 | goto out; | ||
2200 | } | ||
2201 | } | ||
2202 | |||
2150 | list_for_each_entry_reverse(n, &context->names_list, list) { | 2203 | list_for_each_entry_reverse(n, &context->names_list, list) { |
2151 | if (n->name && (n->name == name)) | 2204 | /* does the name pointer match? */ |
2152 | goto out; | 2205 | if (!n->name || n->name->name != name->name) |
2206 | continue; | ||
2207 | |||
2208 | /* match the correct record type */ | ||
2209 | if (parent) { | ||
2210 | if (n->type == AUDIT_TYPE_PARENT || | ||
2211 | n->type == AUDIT_TYPE_UNKNOWN) | ||
2212 | goto out; | ||
2213 | } else { | ||
2214 | if (n->type != AUDIT_TYPE_PARENT) | ||
2215 | goto out; | ||
2216 | } | ||
2153 | } | 2217 | } |
2154 | 2218 | ||
2155 | /* unable to find the name from a previous getname() */ | 2219 | out_alloc: |
2156 | n = audit_alloc_name(context); | 2220 | /* unable to find the name from a previous getname(). Allocate a new |
2221 | * anonymous entry. | ||
2222 | */ | ||
2223 | n = audit_alloc_name(context, AUDIT_TYPE_NORMAL); | ||
2157 | if (!n) | 2224 | if (!n) |
2158 | return; | 2225 | return; |
2159 | out: | 2226 | out: |
2227 | if (parent) { | ||
2228 | n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL; | ||
2229 | n->type = AUDIT_TYPE_PARENT; | ||
2230 | } else { | ||
2231 | n->name_len = AUDIT_NAME_FULL; | ||
2232 | n->type = AUDIT_TYPE_NORMAL; | ||
2233 | } | ||
2160 | handle_path(dentry); | 2234 | handle_path(dentry); |
2161 | audit_copy_inode(n, dentry, inode); | 2235 | audit_copy_inode(n, dentry, inode); |
2162 | } | 2236 | } |
2163 | 2237 | ||
2164 | /** | 2238 | /** |
2165 | * audit_inode_child - collect inode info for created/removed objects | 2239 | * __audit_inode_child - collect inode info for created/removed objects |
2166 | * @dentry: dentry being audited | ||
2167 | * @parent: inode of dentry parent | 2240 | * @parent: inode of dentry parent |
2241 | * @dentry: dentry being audited | ||
2242 | * @type: AUDIT_TYPE_* value that we're looking for | ||
2168 | * | 2243 | * |
2169 | * For syscalls that create or remove filesystem objects, audit_inode | 2244 | * For syscalls that create or remove filesystem objects, audit_inode |
2170 | * can only collect information for the filesystem object's parent. | 2245 | * can only collect information for the filesystem object's parent. |
@@ -2174,15 +2249,14 @@ out: | |||
2174 | * must be hooked prior, in order to capture the target inode during | 2249 | * must be hooked prior, in order to capture the target inode during |
2175 | * unsuccessful attempts. | 2250 | * unsuccessful attempts. |
2176 | */ | 2251 | */ |
2177 | void __audit_inode_child(const struct dentry *dentry, | 2252 | void __audit_inode_child(const struct inode *parent, |
2178 | const struct inode *parent) | 2253 | const struct dentry *dentry, |
2254 | const unsigned char type) | ||
2179 | { | 2255 | { |
2180 | struct audit_context *context = current->audit_context; | 2256 | struct audit_context *context = current->audit_context; |
2181 | const char *found_parent = NULL, *found_child = NULL; | ||
2182 | const struct inode *inode = dentry->d_inode; | 2257 | const struct inode *inode = dentry->d_inode; |
2183 | const char *dname = dentry->d_name.name; | 2258 | const char *dname = dentry->d_name.name; |
2184 | struct audit_names *n; | 2259 | struct audit_names *n, *found_parent = NULL, *found_child = NULL; |
2185 | int dirlen = 0; | ||
2186 | 2260 | ||
2187 | if (!context->in_syscall) | 2261 | if (!context->in_syscall) |
2188 | return; | 2262 | return; |
@@ -2190,62 +2264,65 @@ void __audit_inode_child(const struct dentry *dentry, | |||
2190 | if (inode) | 2264 | if (inode) |
2191 | handle_one(inode); | 2265 | handle_one(inode); |
2192 | 2266 | ||
2193 | /* parent is more likely, look for it first */ | 2267 | /* look for a parent entry first */ |
2194 | list_for_each_entry(n, &context->names_list, list) { | 2268 | list_for_each_entry(n, &context->names_list, list) { |
2195 | if (!n->name) | 2269 | if (!n->name || n->type != AUDIT_TYPE_PARENT) |
2196 | continue; | 2270 | continue; |
2197 | 2271 | ||
2198 | if (n->ino == parent->i_ino && | 2272 | if (n->ino == parent->i_ino && |
2199 | !audit_compare_dname_path(dname, n->name, &dirlen)) { | 2273 | !audit_compare_dname_path(dname, n->name->name, n->name_len)) { |
2200 | n->name_len = dirlen; /* update parent data in place */ | 2274 | found_parent = n; |
2201 | found_parent = n->name; | 2275 | break; |
2202 | goto add_names; | ||
2203 | } | 2276 | } |
2204 | } | 2277 | } |
2205 | 2278 | ||
2206 | /* no matching parent, look for matching child */ | 2279 | /* is there a matching child entry? */ |
2207 | list_for_each_entry(n, &context->names_list, list) { | 2280 | list_for_each_entry(n, &context->names_list, list) { |
2208 | if (!n->name) | 2281 | /* can only match entries that have a name */ |
2282 | if (!n->name || n->type != type) | ||
2209 | continue; | 2283 | continue; |
2210 | 2284 | ||
2211 | /* strcmp() is the more likely scenario */ | 2285 | /* if we found a parent, make sure this one is a child of it */ |
2212 | if (!strcmp(dname, n->name) || | 2286 | if (found_parent && (n->name != found_parent->name)) |
2213 | !audit_compare_dname_path(dname, n->name, &dirlen)) { | 2287 | continue; |
2214 | if (inode) | 2288 | |
2215 | audit_copy_inode(n, NULL, inode); | 2289 | if (!strcmp(dname, n->name->name) || |
2216 | else | 2290 | !audit_compare_dname_path(dname, n->name->name, |
2217 | n->ino = (unsigned long)-1; | 2291 | found_parent ? |
2218 | found_child = n->name; | 2292 | found_parent->name_len : |
2219 | goto add_names; | 2293 | AUDIT_NAME_FULL)) { |
2294 | found_child = n; | ||
2295 | break; | ||
2220 | } | 2296 | } |
2221 | } | 2297 | } |
2222 | 2298 | ||
2223 | add_names: | ||
2224 | if (!found_parent) { | 2299 | if (!found_parent) { |
2225 | n = audit_alloc_name(context); | 2300 | /* create a new, "anonymous" parent record */ |
2301 | n = audit_alloc_name(context, AUDIT_TYPE_PARENT); | ||
2226 | if (!n) | 2302 | if (!n) |
2227 | return; | 2303 | return; |
2228 | audit_copy_inode(n, NULL, parent); | 2304 | audit_copy_inode(n, NULL, parent); |
2229 | } | 2305 | } |
2230 | 2306 | ||
2231 | if (!found_child) { | 2307 | if (!found_child) { |
2232 | n = audit_alloc_name(context); | 2308 | found_child = audit_alloc_name(context, type); |
2233 | if (!n) | 2309 | if (!found_child) |
2234 | return; | 2310 | return; |
2235 | 2311 | ||
2236 | /* Re-use the name belonging to the slot for a matching parent | 2312 | /* Re-use the name belonging to the slot for a matching parent |
2237 | * directory. All names for this context are relinquished in | 2313 | * directory. All names for this context are relinquished in |
2238 | * audit_free_names() */ | 2314 | * audit_free_names() */ |
2239 | if (found_parent) { | 2315 | if (found_parent) { |
2240 | n->name = found_parent; | 2316 | found_child->name = found_parent->name; |
2241 | n->name_len = AUDIT_NAME_FULL; | 2317 | found_child->name_len = AUDIT_NAME_FULL; |
2242 | /* don't call __putname() */ | 2318 | /* don't call __putname() */ |
2243 | n->name_put = false; | 2319 | found_child->name_put = false; |
2244 | } | 2320 | } |
2245 | |||
2246 | if (inode) | ||
2247 | audit_copy_inode(n, NULL, inode); | ||
2248 | } | 2321 | } |
2322 | if (inode) | ||
2323 | audit_copy_inode(found_child, dentry, inode); | ||
2324 | else | ||
2325 | found_child->ino = (unsigned long)-1; | ||
2249 | } | 2326 | } |
2250 | EXPORT_SYMBOL_GPL(__audit_inode_child); | 2327 | EXPORT_SYMBOL_GPL(__audit_inode_child); |
2251 | 2328 | ||
diff --git a/mm/swapfile.c b/mm/swapfile.c index 14e254c768fc..71cd288b2001 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 = file_open_name(pathname, 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 = file_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" : "", |