diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-12 21:04:42 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-12 21:04:42 -0400 |
| commit | 8418263e3547ed3816475e4c55a77004f0426ee6 (patch) | |
| tree | 97c548b16e6753e1911870d824a07b7e726b6229 | |
| parent | ccff9b1db693062b0a9c9070f4304deb47ef215c (diff) | |
| parent | f81700bd831efcd12eb7f0e66b24b16c2ad00a32 (diff) | |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull third pile of VFS updates from Al Viro:
"Stuff from Jeff Layton, mostly. Sanitizing interplay between audit
and namei, removing a lot of insanity from audit_inode() mess and
getting things ready for his ESTALE patchset."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
procfs: don't need a PATH_MAX allocation to hold a string representation of an int
vfs: embed struct filename inside of names_cache allocation if possible
audit: make audit_inode take struct filename
vfs: make path_openat take a struct filename pointer
vfs: turn do_path_lookup into wrapper around struct filename variant
audit: allow audit code to satisfy getname requests from its names_list
vfs: define struct filename and have getname() return it
vfs: unexport getname and putname symbols
acct: constify the name arg to acct_on
vfs: allocate page instead of names_cache buffer in mount_block_root
audit: overhaul __audit_inode_child to accomodate retrying
audit: optimize audit_compare_dname_path
audit: make audit_compare_dname_path use parent_len helper
audit: remove dirlen argument to audit_compare_dname_path
audit: set the name_len in audit_inode for parent lookups
audit: add a new "type" field to audit_names struct
audit: reverse arguments to audit_inode_child
audit: no need to walk list in audit_inode if name is NULL
audit: pass in dentry to audit_copy_inode wherever possible
audit: remove unnecessary NULL ptr checks from do_path_lookup
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" : "", |
