]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Oct 2012 01:04:42 +0000 (10:04 +0900)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 13 Oct 2012 01:04:42 +0000 (10:04 +0900)
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:
arch/alpha/kernel/osf_sys.c
arch/arm64/kernel/sys.c
arch/arm64/kernel/sys_compat.c
arch/avr32/kernel/process.c
arch/blackfin/kernel/process.c
arch/cris/arch-v10/kernel/process.c
arch/cris/arch-v32/kernel/process.c
arch/h8300/kernel/process.c
arch/hexagon/kernel/syscall.c
arch/ia64/kernel/process.c
arch/m32r/kernel/process.c
arch/microblaze/kernel/sys_microblaze.c
arch/mips/kernel/linux32.c
arch/mips/kernel/syscall.c
arch/openrisc/kernel/process.c
arch/parisc/hpux/fs.c
arch/parisc/kernel/process.c
arch/parisc/kernel/sys_parisc32.c
arch/score/kernel/sys_score.c
arch/sh/kernel/process_32.c
arch/sh/kernel/process_64.c
arch/sparc/kernel/process_32.c
arch/sparc/kernel/process_64.c
arch/sparc/kernel/sys_sparc32.c
arch/tile/kernel/process.c
arch/unicore32/kernel/sys.c
arch/xtensa/kernel/process.c
fs/btrfs/ioctl.c
fs/compat.c
fs/exec.c
fs/filesystems.c
fs/internal.h
fs/namei.c
fs/namespace.c
fs/open.c
fs/proc/base.c
fs/quota/quota.c
fs/xattr.c
include/linux/audit.h
include/linux/fs.h
include/linux/fsnotify.h
init/do_mounts.c
ipc/mqueue.c
kernel/acct.c
kernel/audit.h
kernel/audit_watch.c
kernel/auditfilter.c
kernel/auditsc.c
mm/swapfile.c

index 63e77e3944ced280724c964b7690502341383695..9eb090582cf1eb2c557e03025bafc73846fde02f 100644 (file)
@@ -449,7 +449,7 @@ osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
 {
        int retval;
        struct cdfs_args tmp;
-       char *devname;
+       struct filename *devname;
 
        retval = -EFAULT;
        if (copy_from_user(&tmp, args, sizeof(tmp)))
@@ -458,7 +458,7 @@ osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
        retval = PTR_ERR(devname);
        if (IS_ERR(devname))
                goto out;
-       retval = do_mount(devname, dirname, "ext2", flags, NULL);
+       retval = do_mount(devname->name, dirname, "ext2", flags, NULL);
        putname(devname);
  out:
        return retval;
@@ -469,7 +469,7 @@ osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
 {
        int retval;
        struct cdfs_args tmp;
-       char *devname;
+       struct filename *devname;
 
        retval = -EFAULT;
        if (copy_from_user(&tmp, args, sizeof(tmp)))
@@ -478,7 +478,7 @@ osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
        retval = PTR_ERR(devname);
        if (IS_ERR(devname))
                goto out;
-       retval = do_mount(devname, dirname, "iso9660", flags, NULL);
+       retval = do_mount(devname->name, dirname, "iso9660", flags, NULL);
        putname(devname);
  out:
        return retval;
@@ -499,7 +499,7 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, const char __user *, path,
                int, flag, void __user *, data)
 {
        int retval;
-       char *name;
+       struct filename *name;
 
        name = getname(path);
        retval = PTR_ERR(name);
@@ -507,13 +507,13 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, const char __user *, path,
                goto out;
        switch (typenr) {
        case 1:
-               retval = osf_ufs_mount(name, data, flag);
+               retval = osf_ufs_mount(name->name, data, flag);
                break;
        case 6:
-               retval = osf_cdfs_mount(name, data, flag);
+               retval = osf_cdfs_mount(name->name, data, flag);
                break;
        case 9:
-               retval = osf_procfs_mount(name, data, flag);
+               retval = osf_procfs_mount(name->name, data, flag);
                break;
        default:
                retval = -EINVAL;
index 905fcfb0ddd0b284b42237e82da9041e3050cee3..b120df37de3552e5a68479294ef9e6b037ea97fb 100644 (file)
@@ -50,13 +50,13 @@ asmlinkage long sys_execve(const char __user *filenamei,
                           struct pt_regs *regs)
 {
        long error;
-       char * filename;
+       struct filename *filename;
 
        filename = getname(filenamei);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = do_execve(filename, argv, envp, regs);
+       error = do_execve(filename->name, argv, envp, regs);
        putname(filename);
 out:
        return error;
index 93f10e27dc796764d50d6c4d18b7310cd36cbeb5..e521087cb0c424df4f628bbef6cb6e184098e487 100644 (file)
@@ -56,14 +56,14 @@ asmlinkage int compat_sys_execve(const char __user *filenamei,
                                 struct pt_regs *regs)
 {
        int error;
-       char * filename;
+       struct filename *filename;
 
        filename = getname(filenamei);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = compat_do_execve(filename, compat_ptr(argv), compat_ptr(envp),
-                                regs);
+       error = compat_do_execve(filename->name, compat_ptr(argv),
+                                       compat_ptr(envp), regs);
        putname(filename);
 out:
        return error;
index 92c5af98a6f76be5f762b2e8c05936ddde5dfdc4..1bb0a8abd79b5078267ad4e6c9c84832033d0e92 100644 (file)
@@ -388,14 +388,14 @@ asmlinkage int sys_execve(const char __user *ufilename,
                          struct pt_regs *regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname(ufilename);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
 
-       error = do_execve(filename, uargv, uenvp, regs);
+       error = do_execve(filename->name, uargv, uenvp, regs);
        putname(filename);
 
 out:
index 62bcea7dcc6dff30bdaa5a4793ab336aef5ed688..bb1cc721fcf7e18ee26b5bf7a7bc0b2912815ad6 100644 (file)
@@ -213,14 +213,14 @@ asmlinkage int sys_execve(const char __user *name,
                          const char __user *const __user *envp)
 {
        int error;
-       char *filename;
+       struct filename *filename;
        struct pt_regs *regs = (struct pt_regs *)((&name) + 6);
 
        filename = getname(name);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                return error;
-       error = do_execve(filename, argv, envp, regs);
+       error = do_execve(filename->name, argv, envp, regs);
        putname(filename);
        return error;
 }
index bee8df43c201848e6c20439b88811efae05dfdd8..15ac7150371f719965479c9447a4bfd70b600512 100644 (file)
@@ -212,14 +212,14 @@ asmlinkage int sys_execve(const char *fname,
                          struct pt_regs *regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname(fname);
        error = PTR_ERR(filename);
 
        if (IS_ERR(filename))
                goto out;
-       error = do_execve(filename, argv, envp, regs);
+       error = do_execve(filename->name, argv, envp, regs);
        putname(filename);
  out:
        return error;
index 0570e8ce603d1575943e24271cbb1f597d2dfe73..4e9992246359ee7a21e9052f56f60e589b8c72a8 100644 (file)
@@ -224,7 +224,7 @@ sys_execve(const char *fname,
           struct pt_regs *regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname(fname);
        error = PTR_ERR(filename);
@@ -232,7 +232,7 @@ sys_execve(const char *fname,
        if (IS_ERR(filename))
                goto out;
 
-       error = do_execve(filename, argv, envp, regs);
+       error = do_execve(filename->name, argv, envp, regs);
        putname(filename);
  out:
        return error;
index f153ed1a4c080bf73fb4be51389fec566910825d..e8dc1393a13a9c646f382b02d6111e085442012b 100644 (file)
@@ -217,14 +217,14 @@ asmlinkage int sys_execve(const char *name,
                          int dummy, ...)
 {
        int error;
-       char * filename;
+       struct filename *filename;
        struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4);
 
        filename = getname(name);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                return error;
-       error = do_execve(filename, argv, envp, regs);
+       error = do_execve(filename->name, argv, envp, regs);
        putname(filename);
        return error;
 }
index 553cd60ee659d8bcc13fff4dbde40cd646a2c86c..25a9bfe3445d941f3386e05dd8ae5c0c2ece0f95 100644 (file)
@@ -40,7 +40,7 @@ asmlinkage int sys_execve(char __user *ufilename,
                          const char __user *const __user *envp)
 {
        struct pt_regs *pregs = current_thread_info()->regs;
-       char *filename;
+       struct filename *filename;
        int retval;
 
        filename = getname(ufilename);
@@ -48,7 +48,7 @@ asmlinkage int sys_execve(char __user *ufilename,
        if (IS_ERR(filename))
                return retval;
 
-       retval = do_execve(filename, argv, envp, pregs);
+       retval = do_execve(filename->name, argv, envp, pregs);
        putname(filename);
 
        return retval;
index ee31fe9b310e3d93de0e46ab29486e920b51763a..35e106f2ed13e81a8509d9db0d0285cba10a0e8f 100644 (file)
@@ -614,14 +614,14 @@ sys_execve (const char __user *filename,
            const char __user *const __user *envp,
            struct pt_regs *regs)
 {
-       char *fname;
+       struct filename *fname;
        int error;
 
        fname = getname(filename);
        error = PTR_ERR(fname);
        if (IS_ERR(fname))
                goto out;
-       error = do_execve(fname, argv, envp, regs);
+       error = do_execve(fname->name, argv, envp, regs);
        putname(fname);
 out:
        return error;
index 384e63f3a4c4e96ea2ea3cf54c76058c54edf88b..e7366276ef30067ad22f9fd4b9db3252d69f8b66 100644 (file)
@@ -296,14 +296,14 @@ asmlinkage int sys_execve(const char __user *ufilename,
                          unsigned long r6, struct pt_regs regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname(ufilename);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
 
-       error = do_execve(filename, uargv, uenvp, &regs);
+       error = do_execve(filename->name, uargv, uenvp, &regs);
        putname(filename);
 out:
        return error;
index e5b154f24f85e059229544cde92714fa7e8caa54..404c0f24bd41a7acaf5496e86120b15f9e715cd8 100644 (file)
@@ -54,13 +54,13 @@ asmlinkage long microblaze_execve(const char __user *filenamei,
                                  struct pt_regs *regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname(filenamei);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = do_execve(filename, argv, envp, regs);
+       error = do_execve(filename->name, argv, envp, regs);
        putname(filename);
 out:
        return error;
index 922a554cd10802336aa5c23ce030dcbf8432c017..3a21acedf88231403703c3ca842916f325f88a6f 100644 (file)
@@ -83,13 +83,13 @@ out:
 asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs)
 {
        int error;
-       char * filename;
+       struct filename *filename;
 
        filename = getname(compat_ptr(regs.regs[4]));
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = compat_do_execve(filename, compat_ptr(regs.regs[5]),
+       error = compat_do_execve(filename->name, compat_ptr(regs.regs[5]),
                                 compat_ptr(regs.regs[6]), &regs);
        putname(filename);
 
index b08220c82113ccd4a30a2dceac6832e2c199fabc..2bd561bc05ae2b4e7b814ac866d21faaddd046a2 100644 (file)
@@ -133,13 +133,13 @@ _sys_clone(nabi_no_regargs struct pt_regs regs)
 asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs)
 {
        int error;
-       char * filename;
+       struct filename *filename;
 
        filename = getname((const char __user *) (long)regs.regs[4]);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = do_execve(filename,
+       error = do_execve(filename->name,
                          (const char __user *const __user *) (long)regs.regs[5],
                          (const char __user *const __user *) (long)regs.regs[6],
                          &regs);
index 55210f37d1a3e2a74ed1a30cc8cad3e6c600231f..c35f3ab1a8d34749d3f32648e82d826f27f350e1 100644 (file)
@@ -271,7 +271,7 @@ asmlinkage long _sys_execve(const char __user *name,
                            struct pt_regs *regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname(name);
        error = PTR_ERR(filename);
@@ -279,7 +279,7 @@ asmlinkage long _sys_execve(const char __user *name,
        if (IS_ERR(filename))
                goto out;
 
-       error = do_execve(filename, argv, envp, regs);
+       error = do_execve(filename->name, argv, envp, regs);
        putname(filename);
 
 out:
index 6785de7bd2a0298c58f025bda474b037e3ea07f9..a0760b87fd4ec8c5c8531de43833a12fdd97bad1 100644 (file)
 int hpux_execve(struct pt_regs *regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname((const char __user *) regs->gr[26]);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
 
-       error = do_execve(filename,
+       error = do_execve(filename->name,
                          (const char __user *const __user *) regs->gr[25],
                          (const char __user *const __user *) regs->gr[24],
                          regs);
index 8c6b6b6561f0de7025ea5a24b6fed7cb2e6dc677..cbc37216bf90f2fa5c64b5b1956272b9db237b8f 100644 (file)
@@ -342,13 +342,13 @@ unsigned long thread_saved_pc(struct task_struct *t)
 asmlinkage int sys_execve(struct pt_regs *regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname((const char __user *) regs->gr[26]);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = do_execve(filename,
+       error = do_execve(filename->name,
                          (const char __user *const __user *) regs->gr[25],
                          (const char __user *const __user *) regs->gr[24],
                          regs);
index dc9a624623233e0e9f084e3659e65e37bf28df47..bf5b93a885d3cc6eb1b6ccd2ded74223b6cd2d32 100644 (file)
 asmlinkage int sys32_execve(struct pt_regs *regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26]));
        filename = getname((const char __user *) regs->gr[26]);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = compat_do_execve(filename, compat_ptr(regs->gr[25]),
+       error = compat_do_execve(filename->name, compat_ptr(regs->gr[25]),
                                 compat_ptr(regs->gr[24]), regs);
        putname(filename);
 out:
index 21e8679740667c8d1a2e314252f7f35cad143159..d45cf00a33511aee8c6616fc419569714bc6ebf8 100644 (file)
@@ -92,14 +92,14 @@ asmlinkage long
 score_execve(struct pt_regs *regs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname((char __user*)regs->regs[4]);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                return error;
 
-       error = do_execve(filename,
+       error = do_execve(filename->name,
                          (const char __user *const __user *)regs->regs[5],
                          (const char __user *const __user *)regs->regs[6],
                          regs);
index 59521e8a164dae01da367f2f60aef2e0a737551e..ba7345f37bc9d0c6a1e4cc62760ca5e34fe65342 100644 (file)
@@ -298,14 +298,14 @@ asmlinkage int sys_execve(const char __user *ufilename,
 {
        struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname(ufilename);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
 
-       error = do_execve(filename, uargv, uenvp, regs);
+       error = do_execve(filename->name, uargv, uenvp, regs);
        putname(filename);
 out:
        return error;
index 602545b12a8678857c8752407be691a1bd511baa..98a709f0c3c45c1f6ece40d34b79a69cd4de4e2c 100644 (file)
@@ -491,14 +491,14 @@ asmlinkage int sys_execve(const char *ufilename, char **uargv,
                          struct pt_regs *pregs)
 {
        int error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname((char __user *)ufilename);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
 
-       error = do_execve(filename,
+       error = do_execve(filename->name,
                          (const char __user *const __user *)uargv,
                          (const char __user *const __user *)uenvp,
                          pregs);
index 14006d8aca2849899d2ce1821f70f42d8ac50633..487bffb36f5eb4a2792808e317e845cdaa8553d1 100644 (file)
@@ -482,7 +482,7 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
 asmlinkage int sparc_execve(struct pt_regs *regs)
 {
        int error, base = 0;
-       char *filename;
+       struct filename *filename;
 
        /* Check for indirect call. */
        if(regs->u_regs[UREG_G1] == 0)
@@ -492,7 +492,7 @@ asmlinkage int sparc_execve(struct pt_regs *regs)
        error = PTR_ERR(filename);
        if(IS_ERR(filename))
                goto out;
-       error = do_execve(filename,
+       error = do_execve(filename->name,
                          (const char __user *const  __user *)
                          regs->u_regs[base + UREG_I1],
                          (const char __user *const  __user *)
index aff0c72fac0999b70a4407179aad99eebfe84c29..fcaa59421126edf297d4e14dbbf2b90239d5d406 100644 (file)
@@ -722,7 +722,7 @@ EXPORT_SYMBOL(dump_fpu);
 asmlinkage int sparc_execve(struct pt_regs *regs)
 {
        int error, base = 0;
-       char *filename;
+       struct filename *filename;
 
        /* User register window flush is done by entry.S */
 
@@ -734,7 +734,7 @@ asmlinkage int sparc_execve(struct pt_regs *regs)
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = do_execve(filename,
+       error = do_execve(filename->name,
                          (const char __user *const __user *)
                          regs->u_regs[base + UREG_I1],
                          (const char __user *const __user *)
index d862499eb01ccfe298b7101190dfc29f3ebcf44d..c3239811a1b5775903c77e64057e78d01130fdd0 100644 (file)
@@ -403,7 +403,7 @@ asmlinkage long compat_sys_rt_sigaction(int sig,
 asmlinkage long sparc32_execve(struct pt_regs *regs)
 {
        int error, base = 0;
-       char *filename;
+       struct filename *filename;
 
        /* User register window flush is done by entry.S */
 
@@ -416,7 +416,7 @@ asmlinkage long sparc32_execve(struct pt_regs *regs)
        if (IS_ERR(filename))
                goto out;
 
-       error = compat_do_execve(filename,
+       error = compat_do_execve(filename->name,
                                 compat_ptr(regs->u_regs[base + UREG_I1]),
                                 compat_ptr(regs->u_regs[base + UREG_I2]), regs);
 
index 6be7991505019a30ce3ff6268c275a931a088644..622560030a5839c1e93d0fb5a1753809f2e0db5e 100644 (file)
@@ -594,13 +594,13 @@ SYSCALL_DEFINE4(execve, const char __user *, path,
                struct pt_regs *, regs)
 {
        long error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname(path);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = do_execve(filename, argv, envp, regs);
+       error = do_execve(filename->name, argv, envp, regs);
        putname(filename);
        if (error == 0)
                single_step_execve();
@@ -615,13 +615,13 @@ long compat_sys_execve(const char __user *path,
                       struct pt_regs *regs)
 {
        long error;
-       char *filename;
+       struct filename *filename;
 
        filename = getname(path);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = compat_do_execve(filename, argv, envp, regs);
+       error = compat_do_execve(filename->name, argv, envp, regs);
        putname(filename);
        if (error == 0)
                single_step_execve();
index 5fd9af773e15f2752002555b1af787c6a610d334..fabdee96110b46821c911fa9de0be5ba30460b57 100644 (file)
@@ -51,13 +51,13 @@ asmlinkage long __sys_execve(const char __user *filename,
                          struct pt_regs *regs)
 {
        int error;
-       char *fn;
+       struct filename *fn;
 
        fn = getname(filename);
        error = PTR_ERR(fn);
        if (IS_ERR(fn))
                goto out;
-       error = do_execve(fn, argv, envp, regs);
+       error = do_execve(fn->name, argv, envp, regs);
        putname(fn);
 out:
        return error;
index bc44311aa18cc7207dd0e4bde95585cc6b81c3c0..bc020825cce55197e6aaf7dfc127203a143e3553 100644 (file)
@@ -328,13 +328,13 @@ long xtensa_execve(const char __user *name,
                    struct pt_regs *regs)
 {
        long error;
-       char * filename;
+       struct filename *filename;
 
        filename = getname(name);
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = do_execve(filename, argv, envp, regs);
+       error = do_execve(filename->name, argv, envp, regs);
        putname(filename);
 out:
        return error;
index e568c472f80771c9230b9967e8a2e4169e1e452c..61168805f175b3c50ffef99b87e97fdeb2643ebd 100644 (file)
@@ -638,7 +638,7 @@ static int btrfs_may_delete(struct inode *dir,struct dentry *victim,int isdir)
                return -ENOENT;
 
        BUG_ON(victim->d_parent->d_inode != dir);
-       audit_inode_child(victim, dir);
+       audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
 
        error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
        if (error)
index b7a24d0ca30df9d82beee3866b0dc30861946c0f..015e1e1f87c649ff48df282c6c04780569c3192d 100644 (file)
@@ -776,16 +776,16 @@ asmlinkage long compat_sys_mount(const char __user * dev_name,
        char *kernel_type;
        unsigned long data_page;
        char *kernel_dev;
-       char *dir_page;
+       struct filename *dir;
        int retval;
 
        retval = copy_mount_string(type, &kernel_type);
        if (retval < 0)
                goto out;
 
-       dir_page = getname(dir_name);
-       retval = PTR_ERR(dir_page);
-       if (IS_ERR(dir_page))
+       dir = getname(dir_name);
+       retval = PTR_ERR(dir);
+       if (IS_ERR(dir))
                goto out1;
 
        retval = copy_mount_string(dev_name, &kernel_dev);
@@ -807,7 +807,7 @@ asmlinkage long compat_sys_mount(const char __user * dev_name,
                }
        }
 
-       retval = do_mount(kernel_dev, dir_page, kernel_type,
+       retval = do_mount(kernel_dev, dir->name, kernel_type,
                        flags, (void*)data_page);
 
  out4:
@@ -815,7 +815,7 @@ asmlinkage long compat_sys_mount(const char __user * dev_name,
  out3:
        kfree(kernel_dev);
  out2:
-       putname(dir_page);
+       putname(dir);
  out1:
        kfree(kernel_type);
  out:
index ca434534ae9abd43ee320e308b22199fb2d53849..8b9011b67041ddcd57dbcc42e77fa7d0d8b05f7e 100644 (file)
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -105,7 +105,7 @@ static inline void put_binfmt(struct linux_binfmt * fmt)
 SYSCALL_DEFINE1(uselib, const char __user *, library)
 {
        struct file *file;
-       char *tmp = getname(library);
+       struct filename *tmp = getname(library);
        int error = PTR_ERR(tmp);
        static const struct open_flags uselib_flags = {
                .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
@@ -751,13 +751,14 @@ struct file *open_exec(const char *name)
 {
        struct file *file;
        int err;
+       struct filename tmp = { .name = name };
        static const struct open_flags open_exec_flags = {
                .open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
                .acc_mode = MAY_EXEC | MAY_OPEN,
                .intent = LOOKUP_OPEN
        };
 
-       file = do_filp_open(AT_FDCWD, name, &open_exec_flags, LOOKUP_FOLLOW);
+       file = do_filp_open(AT_FDCWD, &tmp, &open_exec_flags, LOOKUP_FOLLOW);
        if (IS_ERR(file))
                goto out;
 
@@ -1664,10 +1665,10 @@ SYSCALL_DEFINE3(execve,
                const char __user *const __user *, argv,
                const char __user *const __user *, envp)
 {
-       const char *path = getname(filename);
+       struct filename *path = getname(filename);
        int error = PTR_ERR(path);
        if (!IS_ERR(path)) {
-               error = do_execve(path, argv, envp, current_pt_regs());
+               error = do_execve(path->name, argv, envp, current_pt_regs());
                putname(path);
        }
        return error;
@@ -1677,10 +1678,11 @@ asmlinkage long compat_sys_execve(const char __user * filename,
        const compat_uptr_t __user * argv,
        const compat_uptr_t __user * envp)
 {
-       const char *path = getname(filename);
+       struct filename *path = getname(filename);
        int error = PTR_ERR(path);
        if (!IS_ERR(path)) {
-               error = compat_do_execve(path, argv, envp, current_pt_regs());
+               error = compat_do_execve(path->name, argv, envp,
+                                                       current_pt_regs());
                putname(path);
        }
        return error;
index 96f24286667adf1aefe4a4c2b4fc2fc67eb19880..da165f6adcbfa67a12f9f19363692ab6c5d00d19 100644 (file)
@@ -124,7 +124,7 @@ EXPORT_SYMBOL(unregister_filesystem);
 static int fs_index(const char __user * __name)
 {
        struct file_system_type * tmp;
-       char * name;
+       struct filename *name;
        int err, index;
 
        name = getname(__name);
@@ -135,7 +135,7 @@ static int fs_index(const char __user * __name)
        err = -EINVAL;
        read_lock(&file_systems_lock);
        for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
-               if (strcmp(tmp->name,name) == 0) {
+               if (strcmp(tmp->name, name->name) == 0) {
                        err = index;
                        break;
                }
index 371bcc4b1697df808e506a6f88735209dec17dd8..916b7cbf3e3e4fae7bc831c66373b5d5ea7a3c4a 100644 (file)
@@ -97,8 +97,8 @@ struct open_flags {
        int acc_mode;
        int intent;
 };
-extern struct file *do_filp_open(int dfd, const char *pathname,
-               const struct open_flags *op, int lookup_flags);
+extern struct file *do_filp_open(int dfd, struct filename *pathname,
+               const struct open_flags *op, int flags);
 extern struct file *do_file_open_root(struct dentry *, struct vfsmount *,
                const char *, const struct open_flags *, int lookup_flags);
 
index c1f18e4f034c7f21ea424782d2dfabedc99f68a6..d1895f30815670de8abd8a6c921443035c21a364 100644 (file)
  * POSIX.1 2.4: an empty pathname is invalid (ENOENT).
  * PATH_MAX includes the nul terminator --RR.
  */
-static char *getname_flags(const char __user *filename, int flags, int *empty)
+void final_putname(struct filename *name)
 {
-       char *result = __getname(), *err;
+       if (name->separate) {
+               __putname(name->name);
+               kfree(name);
+       } else {
+               __putname(name);
+       }
+}
+
+#define EMBEDDED_NAME_MAX      (PATH_MAX - sizeof(struct filename))
+
+static struct filename *
+getname_flags(const char __user *filename, int flags, int *empty)
+{
+       struct filename *result, *err;
        int len;
+       long max;
+       char *kname;
 
+       result = audit_reusename(filename);
+       if (result)
+               return result;
+
+       result = __getname();
        if (unlikely(!result))
                return ERR_PTR(-ENOMEM);
 
-       len = strncpy_from_user(result, filename, PATH_MAX);
-       err = ERR_PTR(len);
-       if (unlikely(len < 0))
+       /*
+        * First, try to embed the struct filename inside the names_cache
+        * allocation
+        */
+       kname = (char *)result + sizeof(*result);
+       result->name = kname;
+       result->separate = false;
+       max = EMBEDDED_NAME_MAX;
+
+recopy:
+       len = strncpy_from_user(kname, filename, max);
+       if (unlikely(len < 0)) {
+               err = ERR_PTR(len);
                goto error;
+       }
+
+       /*
+        * Uh-oh. We have a name that's approaching PATH_MAX. Allocate a
+        * separate struct filename so we can dedicate the entire
+        * names_cache allocation for the pathname, and re-do the copy from
+        * userland.
+        */
+       if (len == EMBEDDED_NAME_MAX && max == EMBEDDED_NAME_MAX) {
+               kname = (char *)result;
+
+               result = kzalloc(sizeof(*result), GFP_KERNEL);
+               if (!result) {
+                       err = ERR_PTR(-ENOMEM);
+                       result = (struct filename *)kname;
+                       goto error;
+               }
+               result->name = kname;
+               result->separate = true;
+               max = PATH_MAX;
+               goto recopy;
+       }
 
        /* The empty path is special. */
        if (unlikely(!len)) {
@@ -140,30 +192,32 @@ static char *getname_flags(const char __user *filename, int flags, int *empty)
        }
 
        err = ERR_PTR(-ENAMETOOLONG);
-       if (likely(len < PATH_MAX)) {
-               audit_getname(result);
-               return result;
-       }
+       if (unlikely(len >= PATH_MAX))
+               goto error;
+
+       result->uptr = filename;
+       audit_getname(result);
+       return result;
 
 error:
-       __putname(result);
+       final_putname(result);
        return err;
 }
 
-char *getname(const char __user * filename)
+struct filename *
+getname(const char __user * filename)
 {
        return getname_flags(filename, 0, NULL);
 }
+EXPORT_SYMBOL(getname);
 
 #ifdef CONFIG_AUDITSYSCALL
-void putname(const char *name)
+void putname(struct filename *name)
 {
        if (unlikely(!audit_dummy_context()))
-               audit_putname(name);
-       else
-               __putname(name);
+               return audit_putname(name);
+       final_putname(name);
 }
-EXPORT_SYMBOL(putname);
 #endif
 
 static int check_acl(struct inode *inode, int mask)
@@ -1963,24 +2017,29 @@ static int path_lookupat(int dfd, const char *name,
        return err;
 }
 
-static int do_path_lookup(int dfd, const char *name,
+static int filename_lookup(int dfd, struct filename *name,
                                unsigned int flags, struct nameidata *nd)
 {
-       int retval = path_lookupat(dfd, name, flags | LOOKUP_RCU, nd);
+       int retval = path_lookupat(dfd, name->name, flags | LOOKUP_RCU, nd);
        if (unlikely(retval == -ECHILD))
-               retval = path_lookupat(dfd, name, flags, nd);
+               retval = path_lookupat(dfd, name->name, flags, nd);
        if (unlikely(retval == -ESTALE))
-               retval = path_lookupat(dfd, name, flags | LOOKUP_REVAL, nd);
+               retval = path_lookupat(dfd, name->name,
+                                               flags | LOOKUP_REVAL, nd);
 
-       if (likely(!retval)) {
-               if (unlikely(!audit_dummy_context())) {
-                       if (nd->path.dentry && nd->inode)
-                               audit_inode(name, nd->path.dentry);
-               }
-       }
+       if (likely(!retval))
+               audit_inode(name, nd->path.dentry, flags & LOOKUP_PARENT);
        return retval;
 }
 
+static int do_path_lookup(int dfd, const char *name,
+                               unsigned int flags, struct nameidata *nd)
+{
+       struct filename filename = { .name = name };
+
+       return filename_lookup(dfd, &filename, flags, nd);
+}
+
 /* does lookup, returns the object with parent locked */
 struct dentry *kern_path_locked(const char *name, struct path *path)
 {
@@ -2098,13 +2157,13 @@ int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
                 struct path *path, int *empty)
 {
        struct nameidata nd;
-       char *tmp = getname_flags(name, flags, empty);
+       struct filename *tmp = getname_flags(name, flags, empty);
        int err = PTR_ERR(tmp);
        if (!IS_ERR(tmp)) {
 
                BUG_ON(flags & LOOKUP_PARENT);
 
-               err = do_path_lookup(dfd, tmp, flags, &nd);
+               err = filename_lookup(dfd, tmp, flags, &nd);
                putname(tmp);
                if (!err)
                        *path = nd.path;
@@ -2118,22 +2177,28 @@ int user_path_at(int dfd, const char __user *name, unsigned flags,
        return user_path_at_empty(dfd, name, flags, path, NULL);
 }
 
-static int user_path_parent(int dfd, const char __user *path,
-                       struct nameidata *nd, char **name)
+/*
+ * NB: most callers don't do anything directly with the reference to the
+ *     to struct filename, but the nd->last pointer points into the name string
+ *     allocated by getname. So we must hold the reference to it until all
+ *     path-walking is complete.
+ */
+static struct filename *
+user_path_parent(int dfd, const char __user *path, struct nameidata *nd)
 {
-       char *s = getname(path);
+       struct filename *s = getname(path);
        int error;
 
        if (IS_ERR(s))
-               return PTR_ERR(s);
+               return s;
 
-       error = do_path_lookup(dfd, s, LOOKUP_PARENT, nd);
-       if (error)
+       error = filename_lookup(dfd, s, LOOKUP_PARENT, nd);
+       if (error) {
                putname(s);
-       else
-               *name = s;
+               return ERR_PTR(error);
+       }
 
-       return error;
+       return s;
 }
 
 /*
@@ -2180,7 +2245,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
                return -ENOENT;
 
        BUG_ON(victim->d_parent->d_inode != dir);
-       audit_inode_child(victim, dir);
+       audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
 
        error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
        if (error)
@@ -2625,7 +2690,7 @@ out_dput:
  */
 static int do_last(struct nameidata *nd, struct path *path,
                   struct file *file, const struct open_flags *op,
-                  int *opened, const char *pathname)
+                  int *opened, struct filename *name)
 {
        struct dentry *dir = nd->path.dentry;
        int open_flag = op->open_flag;
@@ -2652,7 +2717,7 @@ static int do_last(struct nameidata *nd, struct path *path,
                error = complete_walk(nd);
                if (error)
                        return error;
-               audit_inode(pathname, nd->path.dentry);
+               audit_inode(name, nd->path.dentry, 0);
                if (open_flag & O_CREAT) {
                        error = -EISDIR;
                        goto out;
@@ -2662,7 +2727,7 @@ static int do_last(struct nameidata *nd, struct path *path,
                error = complete_walk(nd);
                if (error)
                        return error;
-               audit_inode(pathname, dir);
+               audit_inode(name, dir, 0);
                goto finish_open;
        }
 
@@ -2691,7 +2756,7 @@ static int do_last(struct nameidata *nd, struct path *path,
                if (error)
                        return error;
 
-               audit_inode(pathname, dir);
+               audit_inode(name, dir, 0);
                error = -EISDIR;
                /* trailing slashes? */
                if (nd->last.name[nd->last.len])
@@ -2721,7 +2786,7 @@ retry_lookup:
                    !S_ISREG(file->f_path.dentry->d_inode->i_mode))
                        will_truncate = false;
 
-               audit_inode(pathname, file->f_path.dentry);
+               audit_inode(name, file->f_path.dentry, 0);
                goto opened;
        }
 
@@ -2738,7 +2803,7 @@ retry_lookup:
         * create/update audit record if it already exists.
         */
        if (path->dentry->d_inode)
-               audit_inode(pathname, path->dentry);
+               audit_inode(name, path->dentry, 0);
 
        /*
         * If atomic_open() acquired write access it is dropped now due to
@@ -2803,7 +2868,7 @@ finish_lookup:
        error = -ENOTDIR;
        if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup)
                goto out;
-       audit_inode(pathname, nd->path.dentry);
+       audit_inode(name, nd->path.dentry, 0);
 finish_open:
        if (!S_ISREG(nd->inode->i_mode))
                will_truncate = false;
@@ -2871,7 +2936,7 @@ stale_open:
        goto retry_lookup;
 }
 
-static struct file *path_openat(int dfd, const char *pathname,
+static struct file *path_openat(int dfd, struct filename *pathname,
                struct nameidata *nd, const struct open_flags *op, int flags)
 {
        struct file *base = NULL;
@@ -2886,12 +2951,12 @@ static struct file *path_openat(int dfd, const char *pathname,
 
        file->f_flags = op->open_flag;
 
-       error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base);
+       error = path_init(dfd, pathname->name, flags | LOOKUP_PARENT, nd, &base);
        if (unlikely(error))
                goto out;
 
        current->total_link_count = 0;
-       error = link_path_walk(pathname, nd);
+       error = link_path_walk(pathname->name, nd);
        if (unlikely(error))
                goto out;
 
@@ -2937,7 +3002,7 @@ out:
        return file;
 }
 
-struct file *do_filp_open(int dfd, const char *pathname,
+struct file *do_filp_open(int dfd, struct filename *pathname,
                const struct open_flags *op, int flags)
 {
        struct nameidata nd;
@@ -2956,6 +3021,7 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
 {
        struct nameidata nd;
        struct file *file;
+       struct filename filename = { .name = name };
 
        nd.root.mnt = mnt;
        nd.root.dentry = dentry;
@@ -2965,11 +3031,11 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
        if (dentry->d_inode->i_op->follow_link && op->intent & LOOKUP_OPEN)
                return ERR_PTR(-ELOOP);
 
-       file = path_openat(-1, name, &nd, op, flags | LOOKUP_RCU);
+       file = path_openat(-1, &filename, &nd, op, flags | LOOKUP_RCU);
        if (unlikely(file == ERR_PTR(-ECHILD)))
-               file = path_openat(-1, name, &nd, op, flags);
+               file = path_openat(-1, &filename, &nd, op, flags);
        if (unlikely(file == ERR_PTR(-ESTALE)))
-               file = path_openat(-1, name, &nd, op, flags | LOOKUP_REVAL);
+               file = path_openat(-1, &filename, &nd, op, flags | LOOKUP_REVAL);
        return file;
 }
 
@@ -3044,11 +3110,11 @@ EXPORT_SYMBOL(done_path_create);
 
 struct dentry *user_path_create(int dfd, const char __user *pathname, struct path *path, int is_dir)
 {
-       char *tmp = getname(pathname);
+       struct filename *tmp = getname(pathname);
        struct dentry *res;
        if (IS_ERR(tmp))
                return ERR_CAST(tmp);
-       res = kern_path_create(dfd, tmp, path, is_dir);
+       res = kern_path_create(dfd, tmp->name, path, is_dir);
        putname(tmp);
        return res;
 }
@@ -3253,13 +3319,13 @@ out:
 static long do_rmdir(int dfd, const char __user *pathname)
 {
        int error = 0;
-       char * name;
+       struct filename *name;
        struct dentry *dentry;
        struct nameidata nd;
 
-       error = user_path_parent(dfd, pathname, &nd, &name);
-       if (error)
-               return error;
+       name = user_path_parent(dfd, pathname, &nd);
+       if (IS_ERR(name))
+               return PTR_ERR(name);
 
        switch(nd.last_type) {
        case LAST_DOTDOT:
@@ -3348,14 +3414,14 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry)
 static long do_unlinkat(int dfd, const char __user *pathname)
 {
        int error;
-       char *name;
+       struct filename *name;
        struct dentry *dentry;
        struct nameidata nd;
        struct inode *inode = NULL;
 
-       error = user_path_parent(dfd, pathname, &nd, &name);
-       if (error)
-               return error;
+       name = user_path_parent(dfd, pathname, &nd);
+       if (IS_ERR(name))
+               return PTR_ERR(name);
 
        error = -EISDIR;
        if (nd.last_type != LAST_NORM)
@@ -3439,7 +3505,7 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
                int, newdfd, const char __user *, newname)
 {
        int error;
-       char *from;
+       struct filename *from;
        struct dentry *dentry;
        struct path path;
 
@@ -3452,9 +3518,9 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
        if (IS_ERR(dentry))
                goto out_putname;
 
-       error = security_path_symlink(&path, dentry, from);
+       error = security_path_symlink(&path, dentry, from->name);
        if (!error)
-               error = vfs_symlink(path.dentry->d_inode, dentry, from);
+               error = vfs_symlink(path.dentry->d_inode, dentry, from->name);
        done_path_create(&path, dentry);
 out_putname:
        putname(from);
@@ -3734,17 +3800,21 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
        struct dentry *old_dentry, *new_dentry;
        struct dentry *trap;
        struct nameidata oldnd, newnd;
-       char *from;
-       char *to;
+       struct filename *from;
+       struct filename *to;
        int error;
 
-       error = user_path_parent(olddfd, oldname, &oldnd, &from);
-       if (error)
+       from = user_path_parent(olddfd, oldname, &oldnd);
+       if (IS_ERR(from)) {
+               error = PTR_ERR(from);
                goto exit;
+       }
 
-       error = user_path_parent(newdfd, newname, &newnd, &to);
-       if (error)
+       to = user_path_parent(newdfd, newname, &newnd);
+       if (IS_ERR(to)) {
+               error = PTR_ERR(to);
                goto exit1;
+       }
 
        error = -EXDEV;
        if (oldnd.path.mnt != newnd.path.mnt)
@@ -3968,7 +4038,6 @@ EXPORT_SYMBOL(follow_down_one);
 EXPORT_SYMBOL(follow_down);
 EXPORT_SYMBOL(follow_up);
 EXPORT_SYMBOL(get_write_access); /* nfsd */
-EXPORT_SYMBOL(getname);
 EXPORT_SYMBOL(lock_rename);
 EXPORT_SYMBOL(lookup_one_len);
 EXPORT_SYMBOL(page_follow_link_light);
index fc33207e28adb7af647b64ebc82bcf1e6f7cee37..24960626bb6bfc7b9eff78631876d4eb7ca7a40e 100644 (file)
@@ -2408,7 +2408,7 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
 {
        int ret;
        char *kernel_type;
-       char *kernel_dir;
+       struct filename *kernel_dir;
        char *kernel_dev;
        unsigned long data_page;
 
@@ -2430,7 +2430,7 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
        if (ret < 0)
                goto out_data;
 
-       ret = do_mount(kernel_dev, kernel_dir, kernel_type, flags,
+       ret = do_mount(kernel_dev, kernel_dir->name, kernel_type, flags,
                (void *) data_page);
 
        free_page(data_page);
index 44da0feeca2c94c980c2723bda63b1fcf74caedc..59071f55bf7fe97545cc691e5dc845a05cbe8f64 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -478,7 +478,7 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode)
 
        file = fget(fd);
        if (file) {
-               audit_inode(NULL, file->f_path.dentry);
+               audit_inode(NULL, file->f_path.dentry, 0);
                err = chmod_common(&file->f_path, mode);
                fput(file);
        }
@@ -588,7 +588,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
        error = mnt_want_write_file(f.file);
        if (error)
                goto out_fput;
-       audit_inode(NULL, f.file->f_path.dentry);
+       audit_inode(NULL, f.file->f_path.dentry, 0);
        error = chown_common(&f.file->f_path, user, group);
        mnt_drop_write_file(f.file);
 out_fput:
@@ -858,6 +858,24 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
        return lookup_flags;
 }
 
+/**
+ * file_open_name - open file and return file pointer
+ *
+ * @name:      struct filename containing path to open
+ * @flags:     open flags as per the open(2) second argument
+ * @mode:      mode for the new file if O_CREAT is set, else ignored
+ *
+ * This is the helper to open a file from kernelspace if you really
+ * have to.  But in generally you should not do this, so please move
+ * along, nothing to see here..
+ */
+struct file *file_open_name(struct filename *name, int flags, umode_t mode)
+{
+       struct open_flags op;
+       int lookup = build_open_flags(flags, mode, &op);
+       return do_filp_open(AT_FDCWD, name, &op, lookup);
+}
+
 /**
  * filp_open - open file and return file pointer
  *
@@ -871,9 +889,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
  */
 struct file *filp_open(const char *filename, int flags, umode_t mode)
 {
-       struct open_flags op;
-       int lookup = build_open_flags(flags, mode, &op);
-       return do_filp_open(AT_FDCWD, filename, &op, lookup);
+       struct filename name = {.name = filename};
+       return file_open_name(&name, flags, mode);
 }
 EXPORT_SYMBOL(filp_open);
 
@@ -895,7 +912,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
 {
        struct open_flags op;
        int lookup = build_open_flags(flags, mode, &op);
-       char *tmp = getname(filename);
+       struct filename *tmp = getname(filename);
        int fd = PTR_ERR(tmp);
 
        if (!IS_ERR(tmp)) {
index ef5c84be66f90d58c830be7f1634b76f1936537a..144a96732dd7d602df0d5f8a504e435cfdb07229 100644 (file)
@@ -2258,7 +2258,8 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
        pid_t tgid = task_tgid_nr_ns(current, ns);
        char *name = ERR_PTR(-ENOENT);
        if (tgid) {
-               name = __getname();
+               /* 11 for max length of signed int in decimal + NULL term */
+               name = kmalloc(12, GFP_KERNEL);
                if (!name)
                        name = ERR_PTR(-ENOMEM);
                else
@@ -2273,7 +2274,7 @@ static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd,
 {
        char *s = nd_get_link(nd);
        if (!IS_ERR(s))
-               __putname(s);
+               kfree(s);
 }
 
 static const struct inode_operations proc_self_inode_operations = {
index ff0135d6bc51a5d8ddbe1eb16f845a2b9d37c009..af1661f7a54f1700faa9a129ec76dad81e7e0961 100644 (file)
@@ -331,11 +331,11 @@ static struct super_block *quotactl_block(const char __user *special, int cmd)
 #ifdef CONFIG_BLOCK
        struct block_device *bdev;
        struct super_block *sb;
-       char *tmp = getname(special);
+       struct filename *tmp = getname(special);
 
        if (IS_ERR(tmp))
                return ERR_CAST(tmp);
-       bdev = lookup_bdev(tmp);
+       bdev = lookup_bdev(tmp->name);
        putname(tmp);
        if (IS_ERR(bdev))
                return ERR_CAST(bdev);
index 1780f062dbaf1cd504f491af5962f3dfbd8db4ee..e164dddb8e9660dc1de0cfb1d6a6abd3da13ed6b 100644 (file)
@@ -412,7 +412,7 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
        if (!f.file)
                return error;
        dentry = f.file->f_path.dentry;
-       audit_inode(NULL, dentry);
+       audit_inode(NULL, dentry, 0);
        error = mnt_want_write_file(f.file);
        if (!error) {
                error = setxattr(dentry, name, value, size, flags);
@@ -507,7 +507,7 @@ SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name,
 
        if (!f.file)
                return error;
-       audit_inode(NULL, f.file->f_path.dentry);
+       audit_inode(NULL, f.file->f_path.dentry, 0);
        error = getxattr(f.file->f_path.dentry, name, value, size);
        fdput(f);
        return error;
@@ -586,7 +586,7 @@ SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size)
 
        if (!f.file)
                return error;
-       audit_inode(NULL, f.file->f_path.dentry);
+       audit_inode(NULL, f.file->f_path.dentry, 0);
        error = listxattr(f.file->f_path.dentry, list, size);
        fdput(f);
        return error;
@@ -655,7 +655,7 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
        if (!f.file)
                return error;
        dentry = f.file->f_path.dentry;
-       audit_inode(NULL, dentry);
+       audit_inode(NULL, dentry, 0);
        error = mnt_want_write_file(f.file);
        if (!error) {
                error = removexattr(dentry, name);
index 2c83e5f7edb12882330d2958f9c1db6b2d708c69..e5884f950b4bac3160b667e44d258bda1e522550 100644 (file)
@@ -452,6 +452,16 @@ struct audit_field {
 extern int __init audit_register_class(int class, unsigned *list);
 extern int audit_classify_syscall(int abi, unsigned syscall);
 extern int audit_classify_arch(int arch);
+
+/* audit_names->type values */
+#define        AUDIT_TYPE_UNKNOWN      0       /* we don't know yet */
+#define        AUDIT_TYPE_NORMAL       1       /* a "normal" audit record */
+#define        AUDIT_TYPE_PARENT       2       /* a parent audit record */
+#define        AUDIT_TYPE_CHILD_DELETE 3       /* a child being deleted */
+#define        AUDIT_TYPE_CHILD_CREATE 4       /* a child being created */
+
+struct filename;
+
 #ifdef CONFIG_AUDITSYSCALL
 /* These are defined in auditsc.c */
                                /* Public API */
@@ -461,11 +471,14 @@ extern void __audit_syscall_entry(int arch,
                                  int major, unsigned long a0, unsigned long a1,
                                  unsigned long a2, unsigned long a3);
 extern void __audit_syscall_exit(int ret_success, long ret_value);
-extern void __audit_getname(const char *name);
-extern void audit_putname(const char *name);
-extern void __audit_inode(const char *name, const struct dentry *dentry);
-extern void __audit_inode_child(const struct dentry *dentry,
-                               const struct inode *parent);
+extern struct filename *__audit_reusename(const __user char *uptr);
+extern void __audit_getname(struct filename *name);
+extern void audit_putname(struct filename *name);
+extern void __audit_inode(struct filename *name, const struct dentry *dentry,
+                               unsigned int parent);
+extern void __audit_inode_child(const struct inode *parent,
+                               const struct dentry *dentry,
+                               const unsigned char type);
 extern void __audit_seccomp(unsigned long syscall, long signr, int code);
 extern void __audit_ptrace(struct task_struct *t);
 
@@ -495,19 +508,27 @@ static inline void audit_syscall_exit(void *pt_regs)
                __audit_syscall_exit(success, return_code);
        }
 }
-static inline void audit_getname(const char *name)
+static inline struct filename *audit_reusename(const __user char *name)
+{
+       if (unlikely(!audit_dummy_context()))
+               return __audit_reusename(name);
+       return NULL;
+}
+static inline void audit_getname(struct filename *name)
 {
        if (unlikely(!audit_dummy_context()))
                __audit_getname(name);
 }
-static inline void audit_inode(const char *name, const struct dentry *dentry) {
+static inline void audit_inode(struct filename *name, const struct dentry *dentry,
+                               unsigned int parent) {
        if (unlikely(!audit_dummy_context()))
-               __audit_inode(name, dentry);
+               __audit_inode(name, dentry, parent);
 }
-static inline void audit_inode_child(const struct dentry *dentry,
-                                    const struct inode *parent) {
+static inline void audit_inode_child(const struct inode *parent,
+                                    const struct dentry *dentry,
+                                    const unsigned char type) {
        if (unlikely(!audit_dummy_context()))
-               __audit_inode_child(dentry, parent);
+               __audit_inode_child(parent, dentry, type);
 }
 void audit_core_dumps(long signr);
 
@@ -651,19 +672,29 @@ static inline int audit_dummy_context(void)
 {
        return 1;
 }
-static inline void audit_getname(const char *name)
+static inline struct filename *audit_reusename(const __user char *name)
+{
+       return NULL;
+}
+static inline void audit_getname(struct filename *name)
 { }
-static inline void audit_putname(const char *name)
+static inline void audit_putname(struct filename *name)
 { }
-static inline void __audit_inode(const char *name, const struct dentry *dentry)
+static inline void __audit_inode(struct filename *name,
+                                       const struct dentry *dentry,
+                                       unsigned int parent)
 { }
-static inline void __audit_inode_child(const struct dentry *dentry,
-                                       const struct inode *parent)
+static inline void __audit_inode_child(const struct inode *parent,
+                                       const struct dentry *dentry,
+                                       const unsigned char type)
 { }
-static inline void audit_inode(const char *name, const struct dentry *dentry)
+static inline void audit_inode(struct filename *name,
+                               const struct dentry *dentry,
+                               unsigned int parent)
 { }
-static inline void audit_inode_child(const struct dentry *dentry,
-                                    const struct inode *parent)
+static inline void audit_inode_child(const struct inode *parent,
+                                    const struct dentry *dentry,
+                                    const unsigned char type)
 { }
 static inline void audit_core_dumps(long signr)
 { }
index 8ef2fc9f1f08225b2d1e2291d578e8a9e814f400..65fbf571023f6f8f2ffb48f686e7fc33fab023c7 100644 (file)
@@ -2196,6 +2196,13 @@ static inline int break_lease(struct inode *inode, unsigned int mode)
 #endif /* CONFIG_FILE_LOCKING */
 
 /* fs/open.c */
+struct audit_names;
+struct filename {
+       const char              *name;  /* pointer to actual string */
+       const __user char       *uptr;  /* original userland pointer */
+       struct audit_names      *aname;
+       bool                    separate; /* should "name" be freed? */
+};
 
 extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
                       struct file *filp);
@@ -2203,12 +2210,15 @@ extern int do_fallocate(struct file *file, int mode, loff_t offset,
                        loff_t len);
 extern long do_sys_open(int dfd, const char __user *filename, int flags,
                        umode_t mode);
+extern struct file *file_open_name(struct filename *, int, umode_t);
 extern struct file *filp_open(const char *, int, umode_t);
 extern struct file *file_open_root(struct dentry *, struct vfsmount *,
                                   const char *, int);
 extern struct file * dentry_open(const struct path *, int, const struct cred *);
 extern int filp_close(struct file *, fl_owner_t id);
-extern char * getname(const char __user *);
+
+extern struct filename *getname(const char __user *);
+
 enum {
        FILE_CREATED = 1,
        FILE_OPENED = 2
@@ -2228,13 +2238,14 @@ extern void __init vfs_caches_init(unsigned long);
 
 extern struct kmem_cache *names_cachep;
 
-#define __getname_gfp(gfp)     kmem_cache_alloc(names_cachep, (gfp))
-#define __getname()            __getname_gfp(GFP_KERNEL)
+extern void final_putname(struct filename *name);
+
+#define __getname()            kmem_cache_alloc(names_cachep, GFP_KERNEL)
 #define __putname(name)                kmem_cache_free(names_cachep, (void *)(name))
 #ifndef CONFIG_AUDITSYSCALL
-#define putname(name)   __putname(name)
+#define putname(name)          final_putname(name)
 #else
-extern void putname(const char *name);
+extern void putname(struct filename *name);
 #endif
 
 #ifdef CONFIG_BLOCK
index a6dfe6944564018d070529e5e42642b8aca31de4..0fbfb4646d1b0e98542908415eef69205e554642 100644 (file)
@@ -109,7 +109,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
 
        if (source)
                fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0);
-       audit_inode_child(moved, new_dir);
+       audit_inode_child(new_dir, moved, AUDIT_TYPE_CHILD_CREATE);
 }
 
 /*
@@ -155,7 +155,7 @@ static inline void fsnotify_inoderemove(struct inode *inode)
  */
 static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
 {
-       audit_inode_child(dentry, inode);
+       audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
 
        fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
 }
@@ -168,7 +168,7 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
 static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry)
 {
        fsnotify_link_count(inode);
-       audit_inode_child(new_dentry, dir);
+       audit_inode_child(dir, new_dentry, AUDIT_TYPE_CHILD_CREATE);
 
        fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, new_dentry->d_name.name, 0);
 }
@@ -181,7 +181,7 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
        __u32 mask = (FS_CREATE | FS_ISDIR);
        struct inode *d_inode = dentry->d_inode;
 
-       audit_inode_child(dentry, inode);
+       audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
 
        fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
 }
index d3f0aeed2d39fe06aa07cb4147f747af8b7597ee..f8a66424360d22803b2c20b906ada8faa0d2a48d 100644 (file)
@@ -353,8 +353,9 @@ static int __init do_mount_root(char *name, char *fs, int flags, void *data)
 
 void __init mount_block_root(char *name, int flags)
 {
-       char *fs_names = __getname_gfp(GFP_KERNEL
-               | __GFP_NOTRACK_FALSE_POSITIVE);
+       struct page *page = alloc_page(GFP_KERNEL |
+                                       __GFP_NOTRACK_FALSE_POSITIVE);
+       char *fs_names = page_address(page);
        char *p;
 #ifdef CONFIG_BLOCK
        char b[BDEVNAME_SIZE];
@@ -406,7 +407,7 @@ retry:
 #endif
        panic("VFS: Unable to mount root fs on %s", b);
 out:
-       putname(fs_names);
+       put_page(page);
 }
  
 #ifdef CONFIG_ROOT_NFS
index 6b97e2466fad3c82f50d914c4bbd1724eb8d2dec..71a3ca18c873938238d03abed6c2cf8bb577d130 100644 (file)
@@ -772,7 +772,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
 {
        struct path path;
        struct file *filp;
-       char *name;
+       struct filename *name;
        struct mq_attr attr;
        int fd, error;
        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,
        ro = mnt_want_write(mnt);       /* we'll drop it in any case */
        error = 0;
        mutex_lock(&root->d_inode->i_mutex);
-       path.dentry = lookup_one_len(name, root, strlen(name));
+       path.dentry = lookup_one_len(name->name, root, strlen(name->name));
        if (IS_ERR(path.dentry)) {
                error = PTR_ERR(path.dentry);
                goto out_putfd;
@@ -804,7 +804,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
 
        if (oflag & O_CREAT) {
                if (path.dentry->d_inode) {     /* entry already exists */
-                       audit_inode(name, path.dentry);
+                       audit_inode(name, path.dentry, 0);
                        if (oflag & O_EXCL) {
                                error = -EEXIST;
                                goto out;
@@ -824,7 +824,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
                        error = -ENOENT;
                        goto out;
                }
-               audit_inode(name, path.dentry);
+               audit_inode(name, path.dentry, 0);
                filp = do_open(&path, oflag);
        }
 
@@ -849,7 +849,7 @@ out_putname:
 SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
 {
        int err;
-       char *name;
+       struct filename *name;
        struct dentry *dentry;
        struct inode *inode = NULL;
        struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
@@ -863,7 +863,8 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
        if (err)
                goto out_name;
        mutex_lock_nested(&mnt->mnt_root->d_inode->i_mutex, I_MUTEX_PARENT);
-       dentry = lookup_one_len(name, mnt->mnt_root, strlen(name));
+       dentry = lookup_one_len(name->name, mnt->mnt_root,
+                               strlen(name->name));
        if (IS_ERR(dentry)) {
                err = PTR_ERR(dentry);
                goto out_unlock;
@@ -978,7 +979,7 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
                goto out_fput;
        }
        info = MQUEUE_I(inode);
-       audit_inode(NULL, f.file->f_path.dentry);
+       audit_inode(NULL, f.file->f_path.dentry, 0);
 
        if (unlikely(!(f.file->f_mode & FMODE_WRITE))) {
                ret = -EBADF;
@@ -1094,7 +1095,7 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
                goto out_fput;
        }
        info = MQUEUE_I(inode);
-       audit_inode(NULL, f.file->f_path.dentry);
+       audit_inode(NULL, f.file->f_path.dentry, 0);
 
        if (unlikely(!(f.file->f_mode & FMODE_READ))) {
                ret = -EBADF;
index 6cd7529c9e6a31a7702c77f38c45289f72d907b8..051e071a06e7a745a96c2fac6317d330dc33da43 100644 (file)
@@ -193,7 +193,7 @@ static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file,
        }
 }
 
-static int acct_on(char *name)
+static int acct_on(struct filename *pathname)
 {
        struct file *file;
        struct vfsmount *mnt;
@@ -201,7 +201,7 @@ static int acct_on(char *name)
        struct bsd_acct_struct *acct = NULL;
 
        /* Difference from BSD - they don't do O_APPEND */
-       file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0);
+       file = file_open_name(pathname, O_WRONLY|O_APPEND|O_LARGEFILE, 0);
        if (IS_ERR(file))
                return PTR_ERR(file);
 
@@ -260,7 +260,7 @@ SYSCALL_DEFINE1(acct, const char __user *, name)
                return -EPERM;
 
        if (name) {
-               char *tmp = getname(name);
+               struct filename *tmp = getname(name);
                if (IS_ERR(tmp))
                        return (PTR_ERR(tmp));
                error = acct_on(tmp);
index 9eb3d79482b64ca398ed38ae4b9ab861048a17a1..d51cba868e1b50fa14877dc4eefdf6be0f3fc1ba 100644 (file)
@@ -74,12 +74,15 @@ static inline int audit_hash_ino(u32 ino)
        return (ino & (AUDIT_INODE_BUCKETS-1));
 }
 
+/* Indicates that audit should log the full pathname. */
+#define AUDIT_NAME_FULL -1
+
 extern int audit_match_class(int class, unsigned syscall);
 extern int audit_comparator(const u32 left, const u32 op, const u32 right);
 extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right);
 extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right);
-extern int audit_compare_dname_path(const char *dname, const char *path,
-                                   int *dirlen);
+extern int parent_len(const char *path);
+extern int audit_compare_dname_path(const char *dname, const char *path, int plen);
 extern struct sk_buff *            audit_make_reply(int pid, int seq, int type,
                                             int done, int multi,
                                             const void *payload, int size);
index 1c22ec3d87bc6f24c2b33a4086cb460812e0387c..9a9ae6e3d290025179a964c577de517f24fbe75c 100644 (file)
@@ -265,7 +265,8 @@ static void audit_update_watch(struct audit_parent *parent,
        /* Run all of the watches on this parent looking for the one that
         * matches the given dname */
        list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) {
-               if (audit_compare_dname_path(dname, owatch->path, NULL))
+               if (audit_compare_dname_path(dname, owatch->path,
+                                            AUDIT_NAME_FULL))
                        continue;
 
                /* If the update involves invalidating rules, do the inode-based
index c4bcdbaf4d4de9bdc6f22de554c4bb18c8e9ca93..7f19f23d38a3347373ec00a629c6c0b39a8f770a 100644 (file)
@@ -1298,41 +1298,60 @@ int audit_gid_comparator(kgid_t left, u32 op, kgid_t right)
        }
 }
 
-/* Compare given dentry name with last component in given path,
- * return of 0 indicates a match. */
-int audit_compare_dname_path(const char *dname, const char *path,
-                            int *dirlen)
+/**
+ * parent_len - find the length of the parent portion of a pathname
+ * @path: pathname of which to determine length
+ */
+int parent_len(const char *path)
 {
-       int dlen, plen;
+       int plen;
        const char *p;
 
-       if (!dname || !path)
-               return 1;
-
-       dlen = strlen(dname);
        plen = strlen(path);
-       if (plen < dlen)
-               return 1;
+
+       if (plen == 0)
+               return plen;
 
        /* disregard trailing slashes */
        p = path + plen - 1;
        while ((*p == '/') && (p > path))
                p--;
 
-       /* find last path component */
-       p = p - dlen + 1;
-       if (p < path)
+       /* walk backward until we find the next slash or hit beginning */
+       while ((*p != '/') && (p > path))
+               p--;
+
+       /* did we find a slash? Then increment to include it in path */
+       if (*p == '/')
+               p++;
+
+       return p - path;
+}
+
+/**
+ * audit_compare_dname_path - compare given dentry name with last component in
+ *                           given path. Return of 0 indicates a match.
+ * @dname:     dentry name that we're comparing
+ * @path:      full pathname that we're comparing
+ * @parentlen: length of the parent if known. Passing in AUDIT_NAME_FULL
+ *             here indicates that we must compute this value.
+ */
+int audit_compare_dname_path(const char *dname, const char *path, int parentlen)
+{
+       int dlen, pathlen;
+       const char *p;
+
+       dlen = strlen(dname);
+       pathlen = strlen(path);
+       if (pathlen < dlen)
                return 1;
-       else if (p > path) {
-               if (*--p != '/')
-                       return 1;
-               else
-                       p++;
-       }
 
-       /* return length of path's directory component */
-       if (dirlen)
-               *dirlen = p - path;
+       parentlen = parentlen == AUDIT_NAME_FULL ? parent_len(path) : parentlen;
+       if (pathlen - parentlen != dlen)
+               return 1;
+
+       p = path + parentlen;
+
        return strncmp(p, dname, dlen);
 }
 
index f4a7756f999cddcf344e685ea561f358812c41fd..2f186ed80c40589ef9662fb400c82c1a95854f6a 100644 (file)
@@ -81,9 +81,6 @@
  * a name dynamically and also add those to the list anchored by names_list. */
 #define AUDIT_NAMES    5
 
-/* Indicates that audit should log the full pathname. */
-#define AUDIT_NAME_FULL -1
-
 /* no execve audit message should be longer than this (userspace limits) */
 #define MAX_EXECVE_AUDIT_LEN 7500
 
@@ -106,27 +103,29 @@ struct audit_cap_data {
  * we don't let putname() free it (instead we free all of the saved
  * pointers at syscall exit time).
  *
- * Further, in fs/namei.c:path_lookup() we store the inode and device. */
+ * Further, in fs/namei.c:path_lookup() we store the inode and device.
+ */
 struct audit_names {
-       struct list_head list;          /* audit_context->names_list */
-       const char      *name;
-       unsigned long   ino;
-       dev_t           dev;
-       umode_t         mode;
-       kuid_t          uid;
-       kgid_t          gid;
-       dev_t           rdev;
-       u32             osid;
-       struct audit_cap_data fcap;
-       unsigned int    fcap_ver;
-       int             name_len;       /* number of name's characters to log */
-       bool            name_put;       /* call __putname() for this name */
+       struct list_head        list;           /* audit_context->names_list */
+       struct filename *name;
+       unsigned long           ino;
+       dev_t                   dev;
+       umode_t                 mode;
+       kuid_t                  uid;
+       kgid_t                  gid;
+       dev_t                   rdev;
+       u32                     osid;
+       struct audit_cap_data    fcap;
+       unsigned int            fcap_ver;
+       int                     name_len;       /* number of name's characters to log */
+       unsigned char           type;           /* record type */
+       bool                    name_put;       /* call __putname() for this name */
        /*
         * This was an allocated audit_names and not from the array of
         * names allocated in the task audit context.  Thus this name
         * should be freed on syscall exit
         */
-       bool            should_free;
+       bool                    should_free;
 };
 
 struct audit_aux_data {
@@ -998,7 +997,7 @@ static inline void audit_free_names(struct audit_context *context)
                       context->ino_count);
                list_for_each_entry(n, &context->names_list, list) {
                        printk(KERN_ERR "names[%d] = %p = %s\n", i,
-                              n->name, n->name ?: "(null)");
+                              n->name, n->name->name ?: "(null)");
                }
                dump_stack();
                return;
@@ -1555,7 +1554,7 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
                case AUDIT_NAME_FULL:
                        /* log the full path */
                        audit_log_format(ab, " name=");
-                       audit_log_untrustedstring(ab, n->name);
+                       audit_log_untrustedstring(ab, n->name->name);
                        break;
                case 0:
                        /* 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,
                default:
                        /* log the name's directory component */
                        audit_log_format(ab, " name=");
-                       audit_log_n_untrustedstring(ab, n->name,
+                       audit_log_n_untrustedstring(ab, n->name->name,
                                                    n->name_len);
                }
        } else
@@ -1995,7 +1994,8 @@ retry:
 #endif
 }
 
-static struct audit_names *audit_alloc_name(struct audit_context *context)
+static struct audit_names *audit_alloc_name(struct audit_context *context,
+                                               unsigned char type)
 {
        struct audit_names *aname;
 
@@ -2010,6 +2010,7 @@ static struct audit_names *audit_alloc_name(struct audit_context *context)
        }
 
        aname->ino = (unsigned long)-1;
+       aname->type = type;
        list_add_tail(&aname->list, &context->names_list);
 
        context->name_count++;
@@ -2019,6 +2020,29 @@ static struct audit_names *audit_alloc_name(struct audit_context *context)
        return aname;
 }
 
+/**
+ * audit_reusename - fill out filename with info from existing entry
+ * @uptr: userland ptr to pathname
+ *
+ * Search the audit_names list for the current audit context. If there is an
+ * existing entry with a matching "uptr" then return the filename
+ * associated with that audit_name. If not, return NULL.
+ */
+struct filename *
+__audit_reusename(const __user char *uptr)
+{
+       struct audit_context *context = current->audit_context;
+       struct audit_names *n;
+
+       list_for_each_entry(n, &context->names_list, list) {
+               if (!n->name)
+                       continue;
+               if (n->name->uptr == uptr)
+                       return n->name;
+       }
+       return NULL;
+}
+
 /**
  * audit_getname - add a name to the list
  * @name: name to add
@@ -2026,7 +2050,7 @@ static struct audit_names *audit_alloc_name(struct audit_context *context)
  * Add a name to the list of audit names for this context.
  * Called from fs/namei.c:getname().
  */
-void __audit_getname(const char *name)
+void __audit_getname(struct filename *name)
 {
        struct audit_context *context = current->audit_context;
        struct audit_names *n;
@@ -2040,13 +2064,19 @@ void __audit_getname(const char *name)
                return;
        }
 
-       n = audit_alloc_name(context);
+#if AUDIT_DEBUG
+       /* The filename _must_ have a populated ->name */
+       BUG_ON(!name->name);
+#endif
+
+       n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN);
        if (!n)
                return;
 
        n->name = name;
        n->name_len = AUDIT_NAME_FULL;
        n->name_put = true;
+       name->aname = n;
 
        if (!context->pwd.dentry)
                get_fs_pwd(current->fs, &context->pwd);
@@ -2059,7 +2089,7 @@ void __audit_getname(const char *name)
  * then we delay the putname until syscall exit.
  * Called from include/linux/fs.h:putname().
  */
-void audit_putname(const char *name)
+void audit_putname(struct filename *name)
 {
        struct audit_context *context = current->audit_context;
 
@@ -2074,7 +2104,7 @@ void audit_putname(const char *name)
 
                        list_for_each_entry(n, &context->names_list, list)
                                printk(KERN_ERR "name[%d] = %p = %s\n", i,
-                                      n->name, n->name ?: "(null)");
+                                      n->name, n->name->name ?: "(null)");
                        }
 #endif
                __putname(name);
@@ -2088,8 +2118,8 @@ void audit_putname(const char *name)
                               " put_count=%d\n",
                               __FILE__, __LINE__,
                               context->serial, context->major,
-                              context->in_syscall, name, context->name_count,
-                              context->put_count);
+                              context->in_syscall, name->name,
+                              context->name_count, context->put_count);
                        dump_stack();
                }
        }
@@ -2132,13 +2162,13 @@ static void audit_copy_inode(struct audit_names *name, const struct dentry *dent
 }
 
 /**
- * audit_inode - store the inode and device from a lookup
+ * __audit_inode - store the inode and device from a lookup
  * @name: name being audited
  * @dentry: dentry being audited
- *
- * Called from fs/namei.c:path_lookup().
+ * @parent: does this dentry represent the parent?
  */
-void __audit_inode(const char *name, const struct dentry *dentry)
+void __audit_inode(struct filename *name, const struct dentry *dentry,
+                  unsigned int parent)
 {
        struct audit_context *context = current->audit_context;
        const struct inode *inode = dentry->d_inode;
@@ -2147,24 +2177,69 @@ void __audit_inode(const char *name, const struct dentry *dentry)
        if (!context->in_syscall)
                return;
 
+       if (!name)
+               goto out_alloc;
+
+#if AUDIT_DEBUG
+       /* The struct filename _must_ have a populated ->name */
+       BUG_ON(!name->name);
+#endif
+       /*
+        * If we have a pointer to an audit_names entry already, then we can
+        * just use it directly if the type is correct.
+        */
+       n = name->aname;
+       if (n) {
+               if (parent) {
+                       if (n->type == AUDIT_TYPE_PARENT ||
+                           n->type == AUDIT_TYPE_UNKNOWN)
+                               goto out;
+               } else {
+                       if (n->type != AUDIT_TYPE_PARENT)
+                               goto out;
+               }
+       }
+
        list_for_each_entry_reverse(n, &context->names_list, list) {
-               if (n->name && (n->name == name))
-                       goto out;
+               /* does the name pointer match? */
+               if (!n->name || n->name->name != name->name)
+                       continue;
+
+               /* match the correct record type */
+               if (parent) {
+                       if (n->type == AUDIT_TYPE_PARENT ||
+                           n->type == AUDIT_TYPE_UNKNOWN)
+                               goto out;
+               } else {
+                       if (n->type != AUDIT_TYPE_PARENT)
+                               goto out;
+               }
        }
 
-       /* unable to find the name from a previous getname() */
-       n = audit_alloc_name(context);
+out_alloc:
+       /* unable to find the name from a previous getname(). Allocate a new
+        * anonymous entry.
+        */
+       n = audit_alloc_name(context, AUDIT_TYPE_NORMAL);
        if (!n)
                return;
 out:
+       if (parent) {
+               n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL;
+               n->type = AUDIT_TYPE_PARENT;
+       } else {
+               n->name_len = AUDIT_NAME_FULL;
+               n->type = AUDIT_TYPE_NORMAL;
+       }
        handle_path(dentry);
        audit_copy_inode(n, dentry, inode);
 }
 
 /**
- * audit_inode_child - collect inode info for created/removed objects
- * @dentry: dentry being audited
+ * __audit_inode_child - collect inode info for created/removed objects
  * @parent: inode of dentry parent
+ * @dentry: dentry being audited
+ * @type:   AUDIT_TYPE_* value that we're looking for
  *
  * For syscalls that create or remove filesystem objects, audit_inode
  * can only collect information for the filesystem object's parent.
@@ -2174,15 +2249,14 @@ out:
  * must be hooked prior, in order to capture the target inode during
  * unsuccessful attempts.
  */
-void __audit_inode_child(const struct dentry *dentry,
-                        const struct inode *parent)
+void __audit_inode_child(const struct inode *parent,
+                        const struct dentry *dentry,
+                        const unsigned char type)
 {
        struct audit_context *context = current->audit_context;
-       const char *found_parent = NULL, *found_child = NULL;
        const struct inode *inode = dentry->d_inode;
        const char *dname = dentry->d_name.name;
-       struct audit_names *n;
-       int dirlen = 0;
+       struct audit_names *n, *found_parent = NULL, *found_child = NULL;
 
        if (!context->in_syscall)
                return;
@@ -2190,62 +2264,65 @@ void __audit_inode_child(const struct dentry *dentry,
        if (inode)
                handle_one(inode);
 
-       /* parent is more likely, look for it first */
+       /* look for a parent entry first */
        list_for_each_entry(n, &context->names_list, list) {
-               if (!n->name)
+               if (!n->name || n->type != AUDIT_TYPE_PARENT)
                        continue;
 
                if (n->ino == parent->i_ino &&
-                   !audit_compare_dname_path(dname, n->name, &dirlen)) {
-                       n->name_len = dirlen; /* update parent data in place */
-                       found_parent = n->name;
-                       goto add_names;
+                   !audit_compare_dname_path(dname, n->name->name, n->name_len)) {
+                       found_parent = n;
+                       break;
                }
        }
 
-       /* no matching parent, look for matching child */
+       /* is there a matching child entry? */
        list_for_each_entry(n, &context->names_list, list) {
-               if (!n->name)
+               /* can only match entries that have a name */
+               if (!n->name || n->type != type)
                        continue;
 
-               /* strcmp() is the more likely scenario */
-               if (!strcmp(dname, n->name) ||
-                    !audit_compare_dname_path(dname, n->name, &dirlen)) {
-                       if (inode)
-                               audit_copy_inode(n, NULL, inode);
-                       else
-                               n->ino = (unsigned long)-1;
-                       found_child = n->name;
-                       goto add_names;
+               /* if we found a parent, make sure this one is a child of it */
+               if (found_parent && (n->name != found_parent->name))
+                       continue;
+
+               if (!strcmp(dname, n->name->name) ||
+                   !audit_compare_dname_path(dname, n->name->name,
+                                               found_parent ?
+                                               found_parent->name_len :
+                                               AUDIT_NAME_FULL)) {
+                       found_child = n;
+                       break;
                }
        }
 
-add_names:
        if (!found_parent) {
-               n = audit_alloc_name(context);
+               /* create a new, "anonymous" parent record */
+               n = audit_alloc_name(context, AUDIT_TYPE_PARENT);
                if (!n)
                        return;
                audit_copy_inode(n, NULL, parent);
        }
 
        if (!found_child) {
-               n = audit_alloc_name(context);
-               if (!n)
+               found_child = audit_alloc_name(context, type);
+               if (!found_child)
                        return;
 
                /* Re-use the name belonging to the slot for a matching parent
                 * directory. All names for this context are relinquished in
                 * audit_free_names() */
                if (found_parent) {
-                       n->name = found_parent;
-                       n->name_len = AUDIT_NAME_FULL;
+                       found_child->name = found_parent->name;
+                       found_child->name_len = AUDIT_NAME_FULL;
                        /* don't call __putname() */
-                       n->name_put = false;
+                       found_child->name_put = false;
                }
-
-               if (inode)
-                       audit_copy_inode(n, NULL, inode);
        }
+       if (inode)
+               audit_copy_inode(found_child, dentry, inode);
+       else
+               found_child->ino = (unsigned long)-1;
 }
 EXPORT_SYMBOL_GPL(__audit_inode_child);
 
index 14e254c768fc5090e9c2276085b3c6f96c6255f6..71cd288b200179d4962222337f3947342fcebe57 100644 (file)
@@ -1483,7 +1483,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        struct file *swap_file, *victim;
        struct address_space *mapping;
        struct inode *inode;
-       char *pathname;
+       struct filename *pathname;
        int oom_score_adj;
        int i, type, prev;
        int err;
@@ -1498,8 +1498,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        if (IS_ERR(pathname))
                goto out;
 
-       victim = filp_open(pathname, O_RDWR|O_LARGEFILE, 0);
-       putname(pathname);
+       victim = file_open_name(pathname, O_RDWR|O_LARGEFILE, 0);
        err = PTR_ERR(victim);
        if (IS_ERR(victim))
                goto out;
@@ -1936,7 +1935,7 @@ static int setup_swap_map_and_extents(struct swap_info_struct *p,
 SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 {
        struct swap_info_struct *p;
-       char *name;
+       struct filename *name;
        struct file *swap_file = NULL;
        struct address_space *mapping;
        int i;
@@ -1967,7 +1966,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
                name = NULL;
                goto bad_swap;
        }
-       swap_file = filp_open(name, O_RDWR|O_LARGEFILE, 0);
+       swap_file = file_open_name(name, O_RDWR|O_LARGEFILE, 0);
        if (IS_ERR(swap_file)) {
                error = PTR_ERR(swap_file);
                swap_file = NULL;
@@ -2053,7 +2052,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
 
        printk(KERN_INFO "Adding %uk swap on %s.  "
                        "Priority:%d extents:%d across:%lluk %s%s%s\n",
-               p->pages<<(PAGE_SHIFT-10), name, p->prio,
+               p->pages<<(PAGE_SHIFT-10), name->name, p->prio,
                nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10),
                (p->flags & SWP_SOLIDSTATE) ? "SS" : "",
                (p->flags & SWP_DISCARDABLE) ? "D" : "",