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
This commit is contained in:
commit
8418263e35
@ -449,7 +449,7 @@ osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
|
|||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
struct cdfs_args tmp;
|
struct cdfs_args tmp;
|
||||||
char *devname;
|
struct filename *devname;
|
||||||
|
|
||||||
retval = -EFAULT;
|
retval = -EFAULT;
|
||||||
if (copy_from_user(&tmp, args, sizeof(tmp)))
|
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);
|
retval = PTR_ERR(devname);
|
||||||
if (IS_ERR(devname))
|
if (IS_ERR(devname))
|
||||||
goto out;
|
goto out;
|
||||||
retval = do_mount(devname, dirname, "ext2", flags, NULL);
|
retval = do_mount(devname->name, dirname, "ext2", flags, NULL);
|
||||||
putname(devname);
|
putname(devname);
|
||||||
out:
|
out:
|
||||||
return retval;
|
return retval;
|
||||||
@ -469,7 +469,7 @@ osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
|
|||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
struct cdfs_args tmp;
|
struct cdfs_args tmp;
|
||||||
char *devname;
|
struct filename *devname;
|
||||||
|
|
||||||
retval = -EFAULT;
|
retval = -EFAULT;
|
||||||
if (copy_from_user(&tmp, args, sizeof(tmp)))
|
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);
|
retval = PTR_ERR(devname);
|
||||||
if (IS_ERR(devname))
|
if (IS_ERR(devname))
|
||||||
goto out;
|
goto out;
|
||||||
retval = do_mount(devname, dirname, "iso9660", flags, NULL);
|
retval = do_mount(devname->name, dirname, "iso9660", flags, NULL);
|
||||||
putname(devname);
|
putname(devname);
|
||||||
out:
|
out:
|
||||||
return retval;
|
return retval;
|
||||||
@ -499,7 +499,7 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, const char __user *, path,
|
|||||||
int, flag, void __user *, data)
|
int, flag, void __user *, data)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
char *name;
|
struct filename *name;
|
||||||
|
|
||||||
name = getname(path);
|
name = getname(path);
|
||||||
retval = PTR_ERR(name);
|
retval = PTR_ERR(name);
|
||||||
@ -507,13 +507,13 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, const char __user *, path,
|
|||||||
goto out;
|
goto out;
|
||||||
switch (typenr) {
|
switch (typenr) {
|
||||||
case 1:
|
case 1:
|
||||||
retval = osf_ufs_mount(name, data, flag);
|
retval = osf_ufs_mount(name->name, data, flag);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
retval = osf_cdfs_mount(name, data, flag);
|
retval = osf_cdfs_mount(name->name, data, flag);
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
retval = osf_procfs_mount(name, data, flag);
|
retval = osf_procfs_mount(name->name, data, flag);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
retval = -EINVAL;
|
retval = -EINVAL;
|
||||||
|
@ -50,13 +50,13 @@ asmlinkage long sys_execve(const char __user *filenamei,
|
|||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
long error;
|
long error;
|
||||||
char * filename;
|
struct filename *filename;
|
||||||
|
|
||||||
filename = getname(filenamei);
|
filename = getname(filenamei);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
goto out;
|
||||||
error = do_execve(filename, argv, envp, regs);
|
error = do_execve(filename->name, argv, envp, regs);
|
||||||
putname(filename);
|
putname(filename);
|
||||||
out:
|
out:
|
||||||
return error;
|
return error;
|
||||||
|
@ -56,14 +56,14 @@ asmlinkage int compat_sys_execve(const char __user *filenamei,
|
|||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char * filename;
|
struct filename *filename;
|
||||||
|
|
||||||
filename = getname(filenamei);
|
filename = getname(filenamei);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
goto out;
|
||||||
error = compat_do_execve(filename, compat_ptr(argv), compat_ptr(envp),
|
error = compat_do_execve(filename->name, compat_ptr(argv),
|
||||||
regs);
|
compat_ptr(envp), regs);
|
||||||
putname(filename);
|
putname(filename);
|
||||||
out:
|
out:
|
||||||
return error;
|
return error;
|
||||||
|
@ -388,14 +388,14 @@ asmlinkage int sys_execve(const char __user *ufilename,
|
|||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char *filename;
|
struct filename *filename;
|
||||||
|
|
||||||
filename = getname(ufilename);
|
filename = getname(ufilename);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
error = do_execve(filename, uargv, uenvp, regs);
|
error = do_execve(filename->name, uargv, uenvp, regs);
|
||||||
putname(filename);
|
putname(filename);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -213,14 +213,14 @@ asmlinkage int sys_execve(const char __user *name,
|
|||||||
const char __user *const __user *envp)
|
const char __user *const __user *envp)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char *filename;
|
struct filename *filename;
|
||||||
struct pt_regs *regs = (struct pt_regs *)((&name) + 6);
|
struct pt_regs *regs = (struct pt_regs *)((&name) + 6);
|
||||||
|
|
||||||
filename = getname(name);
|
filename = getname(name);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
return error;
|
return error;
|
||||||
error = do_execve(filename, argv, envp, regs);
|
error = do_execve(filename->name, argv, envp, regs);
|
||||||
putname(filename);
|
putname(filename);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -212,14 +212,14 @@ asmlinkage int sys_execve(const char *fname,
|
|||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char *filename;
|
struct filename *filename;
|
||||||
|
|
||||||
filename = getname(fname);
|
filename = getname(fname);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
|
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
goto out;
|
||||||
error = do_execve(filename, argv, envp, regs);
|
error = do_execve(filename->name, argv, envp, regs);
|
||||||
putname(filename);
|
putname(filename);
|
||||||
out:
|
out:
|
||||||
return error;
|
return error;
|
||||||
|
@ -224,7 +224,7 @@ sys_execve(const char *fname,
|
|||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char *filename;
|
struct filename *filename;
|
||||||
|
|
||||||
filename = getname(fname);
|
filename = getname(fname);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
@ -232,7 +232,7 @@ sys_execve(const char *fname,
|
|||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
error = do_execve(filename, argv, envp, regs);
|
error = do_execve(filename->name, argv, envp, regs);
|
||||||
putname(filename);
|
putname(filename);
|
||||||
out:
|
out:
|
||||||
return error;
|
return error;
|
||||||
|
@ -217,14 +217,14 @@ asmlinkage int sys_execve(const char *name,
|
|||||||
int dummy, ...)
|
int dummy, ...)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char * filename;
|
struct filename *filename;
|
||||||
struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4);
|
struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4);
|
||||||
|
|
||||||
filename = getname(name);
|
filename = getname(name);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
return error;
|
return error;
|
||||||
error = do_execve(filename, argv, envp, regs);
|
error = do_execve(filename->name, argv, envp, regs);
|
||||||
putname(filename);
|
putname(filename);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ asmlinkage int sys_execve(char __user *ufilename,
|
|||||||
const char __user *const __user *envp)
|
const char __user *const __user *envp)
|
||||||
{
|
{
|
||||||
struct pt_regs *pregs = current_thread_info()->regs;
|
struct pt_regs *pregs = current_thread_info()->regs;
|
||||||
char *filename;
|
struct filename *filename;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
filename = getname(ufilename);
|
filename = getname(ufilename);
|
||||||
@ -48,7 +48,7 @@ asmlinkage int sys_execve(char __user *ufilename,
|
|||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
retval = do_execve(filename, argv, envp, pregs);
|
retval = do_execve(filename->name, argv, envp, pregs);
|
||||||
putname(filename);
|
putname(filename);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -614,14 +614,14 @@ sys_execve (const char __user *filename,
|
|||||||
const char __user *const __user *envp,
|
const char __user *const __user *envp,
|
||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
char *fname;
|
struct filename *fname;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
fname = getname(filename);
|
fname = getname(filename);
|
||||||
error = PTR_ERR(fname);
|
error = PTR_ERR(fname);
|
||||||
if (IS_ERR(fname))
|
if (IS_ERR(fname))
|
||||||
goto out;
|
goto out;
|
||||||
error = do_execve(fname, argv, envp, regs);
|
error = do_execve(fname->name, argv, envp, regs);
|
||||||
putname(fname);
|
putname(fname);
|
||||||
out:
|
out:
|
||||||
return error;
|
return error;
|
||||||
|
@ -296,14 +296,14 @@ asmlinkage int sys_execve(const char __user *ufilename,
|
|||||||
unsigned long r6, struct pt_regs regs)
|
unsigned long r6, struct pt_regs regs)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char *filename;
|
struct filename *filename;
|
||||||
|
|
||||||
filename = getname(ufilename);
|
filename = getname(ufilename);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
error = do_execve(filename, uargv, uenvp, ®s);
|
error = do_execve(filename->name, uargv, uenvp, ®s);
|
||||||
putname(filename);
|
putname(filename);
|
||||||
out:
|
out:
|
||||||
return error;
|
return error;
|
||||||
|
@ -54,13 +54,13 @@ asmlinkage long microblaze_execve(const char __user *filenamei,
|
|||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char *filename;
|
struct filename *filename;
|
||||||
|
|
||||||
filename = getname(filenamei);
|
filename = getname(filenamei);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
goto out;
|
||||||
error = do_execve(filename, argv, envp, regs);
|
error = do_execve(filename->name, argv, envp, regs);
|
||||||
putname(filename);
|
putname(filename);
|
||||||
out:
|
out:
|
||||||
return error;
|
return error;
|
||||||
|
@ -83,13 +83,13 @@ SYSCALL_DEFINE6(32_mmap2, unsigned long, addr, unsigned long, len,
|
|||||||
asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs)
|
asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char * filename;
|
struct filename *filename;
|
||||||
|
|
||||||
filename = getname(compat_ptr(regs.regs[4]));
|
filename = getname(compat_ptr(regs.regs[4]));
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
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]), ®s);
|
compat_ptr(regs.regs[6]), ®s);
|
||||||
putname(filename);
|
putname(filename);
|
||||||
|
|
||||||
|
@ -133,13 +133,13 @@ _sys_clone(nabi_no_regargs struct pt_regs regs)
|
|||||||
asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs)
|
asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char * filename;
|
struct filename *filename;
|
||||||
|
|
||||||
filename = getname((const char __user *) (long)regs.regs[4]);
|
filename = getname((const char __user *) (long)regs.regs[4]);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
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[5],
|
||||||
(const char __user *const __user *) (long)regs.regs[6],
|
(const char __user *const __user *) (long)regs.regs[6],
|
||||||
®s);
|
®s);
|
||||||
|
@ -271,7 +271,7 @@ asmlinkage long _sys_execve(const char __user *name,
|
|||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char *filename;
|
struct filename *filename;
|
||||||
|
|
||||||
filename = getname(name);
|
filename = getname(name);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
@ -279,7 +279,7 @@ asmlinkage long _sys_execve(const char __user *name,
|
|||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
error = do_execve(filename, argv, envp, regs);
|
error = do_execve(filename->name, argv, envp, regs);
|
||||||
putname(filename);
|
putname(filename);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -34,14 +34,14 @@
|
|||||||
int hpux_execve(struct pt_regs *regs)
|
int hpux_execve(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char *filename;
|
struct filename *filename;
|
||||||
|
|
||||||
filename = getname((const char __user *) regs->gr[26]);
|
filename = getname((const char __user *) regs->gr[26]);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
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[25],
|
||||||
(const char __user *const __user *) regs->gr[24],
|
(const char __user *const __user *) regs->gr[24],
|
||||||
regs);
|
regs);
|
||||||
|
@ -342,13 +342,13 @@ unsigned long thread_saved_pc(struct task_struct *t)
|
|||||||
asmlinkage int sys_execve(struct pt_regs *regs)
|
asmlinkage int sys_execve(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char *filename;
|
struct filename *filename;
|
||||||
|
|
||||||
filename = getname((const char __user *) regs->gr[26]);
|
filename = getname((const char __user *) regs->gr[26]);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
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[25],
|
||||||
(const char __user *const __user *) regs->gr[24],
|
(const char __user *const __user *) regs->gr[24],
|
||||||
regs);
|
regs);
|
||||||
|
@ -60,14 +60,14 @@
|
|||||||
asmlinkage int sys32_execve(struct pt_regs *regs)
|
asmlinkage int sys32_execve(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char *filename;
|
struct filename *filename;
|
||||||
|
|
||||||
DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26]));
|
DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26]));
|
||||||
filename = getname((const char __user *) regs->gr[26]);
|
filename = getname((const char __user *) regs->gr[26]);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
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);
|
compat_ptr(regs->gr[24]), regs);
|
||||||
putname(filename);
|
putname(filename);
|
||||||
out:
|
out:
|
||||||
|
@ -92,14 +92,14 @@ asmlinkage long
|
|||||||
score_execve(struct pt_regs *regs)
|
score_execve(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char *filename;
|
struct filename *filename;
|
||||||
|
|
||||||
filename = getname((char __user*)regs->regs[4]);
|
filename = getname((char __user*)regs->regs[4]);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
return error;
|
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[5],
|
||||||
(const char __user *const __user *)regs->regs[6],
|
(const char __user *const __user *)regs->regs[6],
|
||||||
regs);
|
regs);
|
||||||
|
@ -298,14 +298,14 @@ asmlinkage int sys_execve(const char __user *ufilename,
|
|||||||
{
|
{
|
||||||
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
|
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
|
||||||
int error;
|
int error;
|
||||||
char *filename;
|
struct filename *filename;
|
||||||
|
|
||||||
filename = getname(ufilename);
|
filename = getname(ufilename);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
error = do_execve(filename, uargv, uenvp, regs);
|
error = do_execve(filename->name, uargv, uenvp, regs);
|
||||||
putname(filename);
|
putname(filename);
|
||||||
out:
|
out:
|
||||||
return error;
|
return error;
|
||||||
|
@ -491,14 +491,14 @@ asmlinkage int sys_execve(const char *ufilename, char **uargv,
|
|||||||
struct pt_regs *pregs)
|
struct pt_regs *pregs)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char *filename;
|
struct filename *filename;
|
||||||
|
|
||||||
filename = getname((char __user *)ufilename);
|
filename = getname((char __user *)ufilename);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
error = do_execve(filename,
|
error = do_execve(filename->name,
|
||||||
(const char __user *const __user *)uargv,
|
(const char __user *const __user *)uargv,
|
||||||
(const char __user *const __user *)uenvp,
|
(const char __user *const __user *)uenvp,
|
||||||
pregs);
|
pregs);
|
||||||
|
@ -482,7 +482,7 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
|
|||||||
asmlinkage int sparc_execve(struct pt_regs *regs)
|
asmlinkage int sparc_execve(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int error, base = 0;
|
int error, base = 0;
|
||||||
char *filename;
|
struct filename *filename;
|
||||||
|
|
||||||
/* Check for indirect call. */
|
/* Check for indirect call. */
|
||||||
if(regs->u_regs[UREG_G1] == 0)
|
if(regs->u_regs[UREG_G1] == 0)
|
||||||
@ -492,7 +492,7 @@ asmlinkage int sparc_execve(struct pt_regs *regs)
|
|||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if(IS_ERR(filename))
|
if(IS_ERR(filename))
|
||||||
goto out;
|
goto out;
|
||||||
error = do_execve(filename,
|
error = do_execve(filename->name,
|
||||||
(const char __user *const __user *)
|
(const char __user *const __user *)
|
||||||
regs->u_regs[base + UREG_I1],
|
regs->u_regs[base + UREG_I1],
|
||||||
(const char __user *const __user *)
|
(const char __user *const __user *)
|
||||||
|
@ -722,7 +722,7 @@ EXPORT_SYMBOL(dump_fpu);
|
|||||||
asmlinkage int sparc_execve(struct pt_regs *regs)
|
asmlinkage int sparc_execve(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int error, base = 0;
|
int error, base = 0;
|
||||||
char *filename;
|
struct filename *filename;
|
||||||
|
|
||||||
/* User register window flush is done by entry.S */
|
/* 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);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
goto out;
|
||||||
error = do_execve(filename,
|
error = do_execve(filename->name,
|
||||||
(const char __user *const __user *)
|
(const char __user *const __user *)
|
||||||
regs->u_regs[base + UREG_I1],
|
regs->u_regs[base + UREG_I1],
|
||||||
(const char __user *const __user *)
|
(const char __user *const __user *)
|
||||||
|
@ -403,7 +403,7 @@ asmlinkage long compat_sys_rt_sigaction(int sig,
|
|||||||
asmlinkage long sparc32_execve(struct pt_regs *regs)
|
asmlinkage long sparc32_execve(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int error, base = 0;
|
int error, base = 0;
|
||||||
char *filename;
|
struct filename *filename;
|
||||||
|
|
||||||
/* User register window flush is done by entry.S */
|
/* 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))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
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_I1]),
|
||||||
compat_ptr(regs->u_regs[base + UREG_I2]), regs);
|
compat_ptr(regs->u_regs[base + UREG_I2]), regs);
|
||||||
|
|
||||||
|
@ -594,13 +594,13 @@ SYSCALL_DEFINE4(execve, const char __user *, path,
|
|||||||
struct pt_regs *, regs)
|
struct pt_regs *, regs)
|
||||||
{
|
{
|
||||||
long error;
|
long error;
|
||||||
char *filename;
|
struct filename *filename;
|
||||||
|
|
||||||
filename = getname(path);
|
filename = getname(path);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
goto out;
|
||||||
error = do_execve(filename, argv, envp, regs);
|
error = do_execve(filename->name, argv, envp, regs);
|
||||||
putname(filename);
|
putname(filename);
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
single_step_execve();
|
single_step_execve();
|
||||||
@ -615,13 +615,13 @@ long compat_sys_execve(const char __user *path,
|
|||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
long error;
|
long error;
|
||||||
char *filename;
|
struct filename *filename;
|
||||||
|
|
||||||
filename = getname(path);
|
filename = getname(path);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
goto out;
|
||||||
error = compat_do_execve(filename, argv, envp, regs);
|
error = compat_do_execve(filename->name, argv, envp, regs);
|
||||||
putname(filename);
|
putname(filename);
|
||||||
if (error == 0)
|
if (error == 0)
|
||||||
single_step_execve();
|
single_step_execve();
|
||||||
|
@ -51,13 +51,13 @@ asmlinkage long __sys_execve(const char __user *filename,
|
|||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char *fn;
|
struct filename *fn;
|
||||||
|
|
||||||
fn = getname(filename);
|
fn = getname(filename);
|
||||||
error = PTR_ERR(fn);
|
error = PTR_ERR(fn);
|
||||||
if (IS_ERR(fn))
|
if (IS_ERR(fn))
|
||||||
goto out;
|
goto out;
|
||||||
error = do_execve(fn, argv, envp, regs);
|
error = do_execve(fn->name, argv, envp, regs);
|
||||||
putname(fn);
|
putname(fn);
|
||||||
out:
|
out:
|
||||||
return error;
|
return error;
|
||||||
|
@ -328,13 +328,13 @@ long xtensa_execve(const char __user *name,
|
|||||||
struct pt_regs *regs)
|
struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
long error;
|
long error;
|
||||||
char * filename;
|
struct filename *filename;
|
||||||
|
|
||||||
filename = getname(name);
|
filename = getname(name);
|
||||||
error = PTR_ERR(filename);
|
error = PTR_ERR(filename);
|
||||||
if (IS_ERR(filename))
|
if (IS_ERR(filename))
|
||||||
goto out;
|
goto out;
|
||||||
error = do_execve(filename, argv, envp, regs);
|
error = do_execve(filename->name, argv, envp, regs);
|
||||||
putname(filename);
|
putname(filename);
|
||||||
out:
|
out:
|
||||||
return error;
|
return error;
|
||||||
|
@ -638,7 +638,7 @@ static int btrfs_may_delete(struct inode *dir,struct dentry *victim,int isdir)
|
|||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
BUG_ON(victim->d_parent->d_inode != dir);
|
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);
|
error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
|
||||||
if (error)
|
if (error)
|
||||||
|
12
fs/compat.c
12
fs/compat.c
@ -776,16 +776,16 @@ asmlinkage long compat_sys_mount(const char __user * dev_name,
|
|||||||
char *kernel_type;
|
char *kernel_type;
|
||||||
unsigned long data_page;
|
unsigned long data_page;
|
||||||
char *kernel_dev;
|
char *kernel_dev;
|
||||||
char *dir_page;
|
struct filename *dir;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
retval = copy_mount_string(type, &kernel_type);
|
retval = copy_mount_string(type, &kernel_type);
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
dir_page = getname(dir_name);
|
dir = getname(dir_name);
|
||||||
retval = PTR_ERR(dir_page);
|
retval = PTR_ERR(dir);
|
||||||
if (IS_ERR(dir_page))
|
if (IS_ERR(dir))
|
||||||
goto out1;
|
goto out1;
|
||||||
|
|
||||||
retval = copy_mount_string(dev_name, &kernel_dev);
|
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);
|
flags, (void*)data_page);
|
||||||
|
|
||||||
out4:
|
out4:
|
||||||
@ -815,7 +815,7 @@ asmlinkage long compat_sys_mount(const char __user * dev_name,
|
|||||||
out3:
|
out3:
|
||||||
kfree(kernel_dev);
|
kfree(kernel_dev);
|
||||||
out2:
|
out2:
|
||||||
putname(dir_page);
|
putname(dir);
|
||||||
out1:
|
out1:
|
||||||
kfree(kernel_type);
|
kfree(kernel_type);
|
||||||
out:
|
out:
|
||||||
|
14
fs/exec.c
14
fs/exec.c
@ -105,7 +105,7 @@ static inline void put_binfmt(struct linux_binfmt * fmt)
|
|||||||
SYSCALL_DEFINE1(uselib, const char __user *, library)
|
SYSCALL_DEFINE1(uselib, const char __user *, library)
|
||||||
{
|
{
|
||||||
struct file *file;
|
struct file *file;
|
||||||
char *tmp = getname(library);
|
struct filename *tmp = getname(library);
|
||||||
int error = PTR_ERR(tmp);
|
int error = PTR_ERR(tmp);
|
||||||
static const struct open_flags uselib_flags = {
|
static const struct open_flags uselib_flags = {
|
||||||
.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
|
.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
|
||||||
@ -751,13 +751,14 @@ struct file *open_exec(const char *name)
|
|||||||
{
|
{
|
||||||
struct file *file;
|
struct file *file;
|
||||||
int err;
|
int err;
|
||||||
|
struct filename tmp = { .name = name };
|
||||||
static const struct open_flags open_exec_flags = {
|
static const struct open_flags open_exec_flags = {
|
||||||
.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
|
.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
|
||||||
.acc_mode = MAY_EXEC | MAY_OPEN,
|
.acc_mode = MAY_EXEC | MAY_OPEN,
|
||||||
.intent = LOOKUP_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))
|
if (IS_ERR(file))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -1664,10 +1665,10 @@ SYSCALL_DEFINE3(execve,
|
|||||||
const char __user *const __user *, argv,
|
const char __user *const __user *, argv,
|
||||||
const char __user *const __user *, envp)
|
const char __user *const __user *, envp)
|
||||||
{
|
{
|
||||||
const char *path = getname(filename);
|
struct filename *path = getname(filename);
|
||||||
int error = PTR_ERR(path);
|
int error = PTR_ERR(path);
|
||||||
if (!IS_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);
|
putname(path);
|
||||||
}
|
}
|
||||||
return error;
|
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 * argv,
|
||||||
const compat_uptr_t __user * envp)
|
const compat_uptr_t __user * envp)
|
||||||
{
|
{
|
||||||
const char *path = getname(filename);
|
struct filename *path = getname(filename);
|
||||||
int error = PTR_ERR(path);
|
int error = PTR_ERR(path);
|
||||||
if (!IS_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);
|
putname(path);
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
|
@ -124,7 +124,7 @@ EXPORT_SYMBOL(unregister_filesystem);
|
|||||||
static int fs_index(const char __user * __name)
|
static int fs_index(const char __user * __name)
|
||||||
{
|
{
|
||||||
struct file_system_type * tmp;
|
struct file_system_type * tmp;
|
||||||
char * name;
|
struct filename *name;
|
||||||
int err, index;
|
int err, index;
|
||||||
|
|
||||||
name = getname(__name);
|
name = getname(__name);
|
||||||
@ -135,7 +135,7 @@ static int fs_index(const char __user * __name)
|
|||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
read_lock(&file_systems_lock);
|
read_lock(&file_systems_lock);
|
||||||
for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
|
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;
|
err = index;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -97,8 +97,8 @@ struct open_flags {
|
|||||||
int acc_mode;
|
int acc_mode;
|
||||||
int intent;
|
int intent;
|
||||||
};
|
};
|
||||||
extern struct file *do_filp_open(int dfd, const char *pathname,
|
extern struct file *do_filp_open(int dfd, struct filename *pathname,
|
||||||
const struct open_flags *op, int lookup_flags);
|
const struct open_flags *op, int flags);
|
||||||
extern struct file *do_file_open_root(struct dentry *, struct vfsmount *,
|
extern struct file *do_file_open_root(struct dentry *, struct vfsmount *,
|
||||||
const char *, const struct open_flags *, int lookup_flags);
|
const char *, const struct open_flags *, int lookup_flags);
|
||||||
|
|
||||||
|
219
fs/namei.c
219
fs/namei.c
@ -117,18 +117,70 @@
|
|||||||
* POSIX.1 2.4: an empty pathname is invalid (ENOENT).
|
* POSIX.1 2.4: an empty pathname is invalid (ENOENT).
|
||||||
* PATH_MAX includes the nul terminator --RR.
|
* 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) {
|
||||||
int len;
|
__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))
|
if (unlikely(!result))
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
len = strncpy_from_user(result, filename, PATH_MAX);
|
/*
|
||||||
err = ERR_PTR(len);
|
* First, try to embed the struct filename inside the names_cache
|
||||||
if (unlikely(len < 0))
|
* 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;
|
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. */
|
/* The empty path is special. */
|
||||||
if (unlikely(!len)) {
|
if (unlikely(!len)) {
|
||||||
@ -140,30 +192,32 @@ static char *getname_flags(const char __user *filename, int flags, int *empty)
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = ERR_PTR(-ENAMETOOLONG);
|
err = ERR_PTR(-ENAMETOOLONG);
|
||||||
if (likely(len < PATH_MAX)) {
|
if (unlikely(len >= PATH_MAX))
|
||||||
audit_getname(result);
|
goto error;
|
||||||
return result;
|
|
||||||
}
|
result->uptr = filename;
|
||||||
|
audit_getname(result);
|
||||||
|
return result;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
__putname(result);
|
final_putname(result);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *getname(const char __user * filename)
|
struct filename *
|
||||||
|
getname(const char __user * filename)
|
||||||
{
|
{
|
||||||
return getname_flags(filename, 0, NULL);
|
return getname_flags(filename, 0, NULL);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(getname);
|
||||||
|
|
||||||
#ifdef CONFIG_AUDITSYSCALL
|
#ifdef CONFIG_AUDITSYSCALL
|
||||||
void putname(const char *name)
|
void putname(struct filename *name)
|
||||||
{
|
{
|
||||||
if (unlikely(!audit_dummy_context()))
|
if (unlikely(!audit_dummy_context()))
|
||||||
audit_putname(name);
|
return audit_putname(name);
|
||||||
else
|
final_putname(name);
|
||||||
__putname(name);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(putname);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int check_acl(struct inode *inode, int mask)
|
static int check_acl(struct inode *inode, int mask)
|
||||||
@ -1963,22 +2017,27 @@ static int path_lookupat(int dfd, const char *name,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int filename_lookup(int dfd, struct filename *name,
|
||||||
|
unsigned int flags, struct nameidata *nd)
|
||||||
|
{
|
||||||
|
int retval = path_lookupat(dfd, name->name, flags | LOOKUP_RCU, nd);
|
||||||
|
if (unlikely(retval == -ECHILD))
|
||||||
|
retval = path_lookupat(dfd, name->name, flags, nd);
|
||||||
|
if (unlikely(retval == -ESTALE))
|
||||||
|
retval = path_lookupat(dfd, name->name,
|
||||||
|
flags | LOOKUP_REVAL, nd);
|
||||||
|
|
||||||
|
if (likely(!retval))
|
||||||
|
audit_inode(name, nd->path.dentry, flags & LOOKUP_PARENT);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
static int do_path_lookup(int dfd, const char *name,
|
static int do_path_lookup(int dfd, const char *name,
|
||||||
unsigned int flags, struct nameidata *nd)
|
unsigned int flags, struct nameidata *nd)
|
||||||
{
|
{
|
||||||
int retval = path_lookupat(dfd, name, flags | LOOKUP_RCU, nd);
|
struct filename filename = { .name = name };
|
||||||
if (unlikely(retval == -ECHILD))
|
|
||||||
retval = path_lookupat(dfd, name, flags, nd);
|
|
||||||
if (unlikely(retval == -ESTALE))
|
|
||||||
retval = path_lookupat(dfd, name, flags | LOOKUP_REVAL, nd);
|
|
||||||
|
|
||||||
if (likely(!retval)) {
|
return filename_lookup(dfd, &filename, flags, nd);
|
||||||
if (unlikely(!audit_dummy_context())) {
|
|
||||||
if (nd->path.dentry && nd->inode)
|
|
||||||
audit_inode(name, nd->path.dentry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* does lookup, returns the object with parent locked */
|
/* does lookup, returns the object with parent locked */
|
||||||
@ -2098,13 +2157,13 @@ int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
|
|||||||
struct path *path, int *empty)
|
struct path *path, int *empty)
|
||||||
{
|
{
|
||||||
struct nameidata nd;
|
struct nameidata nd;
|
||||||
char *tmp = getname_flags(name, flags, empty);
|
struct filename *tmp = getname_flags(name, flags, empty);
|
||||||
int err = PTR_ERR(tmp);
|
int err = PTR_ERR(tmp);
|
||||||
if (!IS_ERR(tmp)) {
|
if (!IS_ERR(tmp)) {
|
||||||
|
|
||||||
BUG_ON(flags & LOOKUP_PARENT);
|
BUG_ON(flags & LOOKUP_PARENT);
|
||||||
|
|
||||||
err = do_path_lookup(dfd, tmp, flags, &nd);
|
err = filename_lookup(dfd, tmp, flags, &nd);
|
||||||
putname(tmp);
|
putname(tmp);
|
||||||
if (!err)
|
if (!err)
|
||||||
*path = nd.path;
|
*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);
|
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;
|
int error;
|
||||||
|
|
||||||
if (IS_ERR(s))
|
if (IS_ERR(s))
|
||||||
return PTR_ERR(s);
|
return s;
|
||||||
|
|
||||||
error = do_path_lookup(dfd, s, LOOKUP_PARENT, nd);
|
error = filename_lookup(dfd, s, LOOKUP_PARENT, nd);
|
||||||
if (error)
|
if (error) {
|
||||||
putname(s);
|
putname(s);
|
||||||
else
|
return ERR_PTR(error);
|
||||||
*name = s;
|
}
|
||||||
|
|
||||||
return error;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2180,7 +2245,7 @@ static int may_delete(struct inode *dir,struct dentry *victim,int isdir)
|
|||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
BUG_ON(victim->d_parent->d_inode != dir);
|
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);
|
error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
|
||||||
if (error)
|
if (error)
|
||||||
@ -2625,7 +2690,7 @@ static int lookup_open(struct nameidata *nd, struct path *path,
|
|||||||
*/
|
*/
|
||||||
static int do_last(struct nameidata *nd, struct path *path,
|
static int do_last(struct nameidata *nd, struct path *path,
|
||||||
struct file *file, const struct open_flags *op,
|
struct file *file, const struct open_flags *op,
|
||||||
int *opened, const char *pathname)
|
int *opened, struct filename *name)
|
||||||
{
|
{
|
||||||
struct dentry *dir = nd->path.dentry;
|
struct dentry *dir = nd->path.dentry;
|
||||||
int open_flag = op->open_flag;
|
int open_flag = op->open_flag;
|
||||||
@ -2652,7 +2717,7 @@ static int do_last(struct nameidata *nd, struct path *path,
|
|||||||
error = complete_walk(nd);
|
error = complete_walk(nd);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
audit_inode(pathname, nd->path.dentry);
|
audit_inode(name, nd->path.dentry, 0);
|
||||||
if (open_flag & O_CREAT) {
|
if (open_flag & O_CREAT) {
|
||||||
error = -EISDIR;
|
error = -EISDIR;
|
||||||
goto out;
|
goto out;
|
||||||
@ -2662,7 +2727,7 @@ static int do_last(struct nameidata *nd, struct path *path,
|
|||||||
error = complete_walk(nd);
|
error = complete_walk(nd);
|
||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
audit_inode(pathname, dir);
|
audit_inode(name, dir, 0);
|
||||||
goto finish_open;
|
goto finish_open;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2691,7 +2756,7 @@ static int do_last(struct nameidata *nd, struct path *path,
|
|||||||
if (error)
|
if (error)
|
||||||
return error;
|
return error;
|
||||||
|
|
||||||
audit_inode(pathname, dir);
|
audit_inode(name, dir, 0);
|
||||||
error = -EISDIR;
|
error = -EISDIR;
|
||||||
/* trailing slashes? */
|
/* trailing slashes? */
|
||||||
if (nd->last.name[nd->last.len])
|
if (nd->last.name[nd->last.len])
|
||||||
@ -2721,7 +2786,7 @@ static int do_last(struct nameidata *nd, struct path *path,
|
|||||||
!S_ISREG(file->f_path.dentry->d_inode->i_mode))
|
!S_ISREG(file->f_path.dentry->d_inode->i_mode))
|
||||||
will_truncate = false;
|
will_truncate = false;
|
||||||
|
|
||||||
audit_inode(pathname, file->f_path.dentry);
|
audit_inode(name, file->f_path.dentry, 0);
|
||||||
goto opened;
|
goto opened;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2738,7 +2803,7 @@ static int do_last(struct nameidata *nd, struct path *path,
|
|||||||
* create/update audit record if it already exists.
|
* create/update audit record if it already exists.
|
||||||
*/
|
*/
|
||||||
if (path->dentry->d_inode)
|
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
|
* If atomic_open() acquired write access it is dropped now due to
|
||||||
@ -2803,7 +2868,7 @@ static int do_last(struct nameidata *nd, struct path *path,
|
|||||||
error = -ENOTDIR;
|
error = -ENOTDIR;
|
||||||
if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup)
|
if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup)
|
||||||
goto out;
|
goto out;
|
||||||
audit_inode(pathname, nd->path.dentry);
|
audit_inode(name, nd->path.dentry, 0);
|
||||||
finish_open:
|
finish_open:
|
||||||
if (!S_ISREG(nd->inode->i_mode))
|
if (!S_ISREG(nd->inode->i_mode))
|
||||||
will_truncate = false;
|
will_truncate = false;
|
||||||
@ -2871,7 +2936,7 @@ static int do_last(struct nameidata *nd, struct path *path,
|
|||||||
goto retry_lookup;
|
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 nameidata *nd, const struct open_flags *op, int flags)
|
||||||
{
|
{
|
||||||
struct file *base = NULL;
|
struct file *base = NULL;
|
||||||
@ -2886,12 +2951,12 @@ static struct file *path_openat(int dfd, const char *pathname,
|
|||||||
|
|
||||||
file->f_flags = op->open_flag;
|
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))
|
if (unlikely(error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
current->total_link_count = 0;
|
current->total_link_count = 0;
|
||||||
error = link_path_walk(pathname, nd);
|
error = link_path_walk(pathname->name, nd);
|
||||||
if (unlikely(error))
|
if (unlikely(error))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
@ -2937,7 +3002,7 @@ static struct file *path_openat(int dfd, const char *pathname,
|
|||||||
return file;
|
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)
|
const struct open_flags *op, int flags)
|
||||||
{
|
{
|
||||||
struct nameidata nd;
|
struct nameidata nd;
|
||||||
@ -2956,6 +3021,7 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
|
|||||||
{
|
{
|
||||||
struct nameidata nd;
|
struct nameidata nd;
|
||||||
struct file *file;
|
struct file *file;
|
||||||
|
struct filename filename = { .name = name };
|
||||||
|
|
||||||
nd.root.mnt = mnt;
|
nd.root.mnt = mnt;
|
||||||
nd.root.dentry = dentry;
|
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)
|
if (dentry->d_inode->i_op->follow_link && op->intent & LOOKUP_OPEN)
|
||||||
return ERR_PTR(-ELOOP);
|
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)))
|
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)))
|
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;
|
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)
|
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;
|
struct dentry *res;
|
||||||
if (IS_ERR(tmp))
|
if (IS_ERR(tmp))
|
||||||
return ERR_CAST(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);
|
putname(tmp);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@ -3253,13 +3319,13 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry)
|
|||||||
static long do_rmdir(int dfd, const char __user *pathname)
|
static long do_rmdir(int dfd, const char __user *pathname)
|
||||||
{
|
{
|
||||||
int error = 0;
|
int error = 0;
|
||||||
char * name;
|
struct filename *name;
|
||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
struct nameidata nd;
|
struct nameidata nd;
|
||||||
|
|
||||||
error = user_path_parent(dfd, pathname, &nd, &name);
|
name = user_path_parent(dfd, pathname, &nd);
|
||||||
if (error)
|
if (IS_ERR(name))
|
||||||
return error;
|
return PTR_ERR(name);
|
||||||
|
|
||||||
switch(nd.last_type) {
|
switch(nd.last_type) {
|
||||||
case LAST_DOTDOT:
|
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)
|
static long do_unlinkat(int dfd, const char __user *pathname)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char *name;
|
struct filename *name;
|
||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
struct nameidata nd;
|
struct nameidata nd;
|
||||||
struct inode *inode = NULL;
|
struct inode *inode = NULL;
|
||||||
|
|
||||||
error = user_path_parent(dfd, pathname, &nd, &name);
|
name = user_path_parent(dfd, pathname, &nd);
|
||||||
if (error)
|
if (IS_ERR(name))
|
||||||
return error;
|
return PTR_ERR(name);
|
||||||
|
|
||||||
error = -EISDIR;
|
error = -EISDIR;
|
||||||
if (nd.last_type != LAST_NORM)
|
if (nd.last_type != LAST_NORM)
|
||||||
@ -3439,7 +3505,7 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
|
|||||||
int, newdfd, const char __user *, newname)
|
int, newdfd, const char __user *, newname)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
char *from;
|
struct filename *from;
|
||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
struct path path;
|
struct path path;
|
||||||
|
|
||||||
@ -3452,9 +3518,9 @@ SYSCALL_DEFINE3(symlinkat, const char __user *, oldname,
|
|||||||
if (IS_ERR(dentry))
|
if (IS_ERR(dentry))
|
||||||
goto out_putname;
|
goto out_putname;
|
||||||
|
|
||||||
error = security_path_symlink(&path, dentry, from);
|
error = security_path_symlink(&path, dentry, from->name);
|
||||||
if (!error)
|
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);
|
done_path_create(&path, dentry);
|
||||||
out_putname:
|
out_putname:
|
||||||
putname(from);
|
putname(from);
|
||||||
@ -3734,17 +3800,21 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname,
|
|||||||
struct dentry *old_dentry, *new_dentry;
|
struct dentry *old_dentry, *new_dentry;
|
||||||
struct dentry *trap;
|
struct dentry *trap;
|
||||||
struct nameidata oldnd, newnd;
|
struct nameidata oldnd, newnd;
|
||||||
char *from;
|
struct filename *from;
|
||||||
char *to;
|
struct filename *to;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
error = user_path_parent(olddfd, oldname, &oldnd, &from);
|
from = user_path_parent(olddfd, oldname, &oldnd);
|
||||||
if (error)
|
if (IS_ERR(from)) {
|
||||||
|
error = PTR_ERR(from);
|
||||||
goto exit;
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
error = user_path_parent(newdfd, newname, &newnd, &to);
|
to = user_path_parent(newdfd, newname, &newnd);
|
||||||
if (error)
|
if (IS_ERR(to)) {
|
||||||
|
error = PTR_ERR(to);
|
||||||
goto exit1;
|
goto exit1;
|
||||||
|
}
|
||||||
|
|
||||||
error = -EXDEV;
|
error = -EXDEV;
|
||||||
if (oldnd.path.mnt != newnd.path.mnt)
|
if (oldnd.path.mnt != newnd.path.mnt)
|
||||||
@ -3968,7 +4038,6 @@ EXPORT_SYMBOL(follow_down_one);
|
|||||||
EXPORT_SYMBOL(follow_down);
|
EXPORT_SYMBOL(follow_down);
|
||||||
EXPORT_SYMBOL(follow_up);
|
EXPORT_SYMBOL(follow_up);
|
||||||
EXPORT_SYMBOL(get_write_access); /* nfsd */
|
EXPORT_SYMBOL(get_write_access); /* nfsd */
|
||||||
EXPORT_SYMBOL(getname);
|
|
||||||
EXPORT_SYMBOL(lock_rename);
|
EXPORT_SYMBOL(lock_rename);
|
||||||
EXPORT_SYMBOL(lookup_one_len);
|
EXPORT_SYMBOL(lookup_one_len);
|
||||||
EXPORT_SYMBOL(page_follow_link_light);
|
EXPORT_SYMBOL(page_follow_link_light);
|
||||||
|
@ -2408,7 +2408,7 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
char *kernel_type;
|
char *kernel_type;
|
||||||
char *kernel_dir;
|
struct filename *kernel_dir;
|
||||||
char *kernel_dev;
|
char *kernel_dev;
|
||||||
unsigned long data_page;
|
unsigned long data_page;
|
||||||
|
|
||||||
@ -2430,7 +2430,7 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out_data;
|
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);
|
(void *) data_page);
|
||||||
|
|
||||||
free_page(data_page);
|
free_page(data_page);
|
||||||
|
29
fs/open.c
29
fs/open.c
@ -478,7 +478,7 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode)
|
|||||||
|
|
||||||
file = fget(fd);
|
file = fget(fd);
|
||||||
if (file) {
|
if (file) {
|
||||||
audit_inode(NULL, file->f_path.dentry);
|
audit_inode(NULL, file->f_path.dentry, 0);
|
||||||
err = chmod_common(&file->f_path, mode);
|
err = chmod_common(&file->f_path, mode);
|
||||||
fput(file);
|
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);
|
error = mnt_want_write_file(f.file);
|
||||||
if (error)
|
if (error)
|
||||||
goto out_fput;
|
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);
|
error = chown_common(&f.file->f_path, user, group);
|
||||||
mnt_drop_write_file(f.file);
|
mnt_drop_write_file(f.file);
|
||||||
out_fput:
|
out_fput:
|
||||||
@ -858,6 +858,24 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
|
|||||||
return lookup_flags;
|
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
|
* 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 file *filp_open(const char *filename, int flags, umode_t mode)
|
||||||
{
|
{
|
||||||
struct open_flags op;
|
struct filename name = {.name = filename};
|
||||||
int lookup = build_open_flags(flags, mode, &op);
|
return file_open_name(&name, flags, mode);
|
||||||
return do_filp_open(AT_FDCWD, filename, &op, lookup);
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(filp_open);
|
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;
|
struct open_flags op;
|
||||||
int lookup = build_open_flags(flags, mode, &op);
|
int lookup = build_open_flags(flags, mode, &op);
|
||||||
char *tmp = getname(filename);
|
struct filename *tmp = getname(filename);
|
||||||
int fd = PTR_ERR(tmp);
|
int fd = PTR_ERR(tmp);
|
||||||
|
|
||||||
if (!IS_ERR(tmp)) {
|
if (!IS_ERR(tmp)) {
|
||||||
|
@ -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);
|
pid_t tgid = task_tgid_nr_ns(current, ns);
|
||||||
char *name = ERR_PTR(-ENOENT);
|
char *name = ERR_PTR(-ENOENT);
|
||||||
if (tgid) {
|
if (tgid) {
|
||||||
name = __getname();
|
/* 11 for max length of signed int in decimal + NULL term */
|
||||||
|
name = kmalloc(12, GFP_KERNEL);
|
||||||
if (!name)
|
if (!name)
|
||||||
name = ERR_PTR(-ENOMEM);
|
name = ERR_PTR(-ENOMEM);
|
||||||
else
|
else
|
||||||
@ -2273,7 +2274,7 @@ static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd,
|
|||||||
{
|
{
|
||||||
char *s = nd_get_link(nd);
|
char *s = nd_get_link(nd);
|
||||||
if (!IS_ERR(s))
|
if (!IS_ERR(s))
|
||||||
__putname(s);
|
kfree(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct inode_operations proc_self_inode_operations = {
|
static const struct inode_operations proc_self_inode_operations = {
|
||||||
|
@ -331,11 +331,11 @@ static struct super_block *quotactl_block(const char __user *special, int cmd)
|
|||||||
#ifdef CONFIG_BLOCK
|
#ifdef CONFIG_BLOCK
|
||||||
struct block_device *bdev;
|
struct block_device *bdev;
|
||||||
struct super_block *sb;
|
struct super_block *sb;
|
||||||
char *tmp = getname(special);
|
struct filename *tmp = getname(special);
|
||||||
|
|
||||||
if (IS_ERR(tmp))
|
if (IS_ERR(tmp))
|
||||||
return ERR_CAST(tmp);
|
return ERR_CAST(tmp);
|
||||||
bdev = lookup_bdev(tmp);
|
bdev = lookup_bdev(tmp->name);
|
||||||
putname(tmp);
|
putname(tmp);
|
||||||
if (IS_ERR(bdev))
|
if (IS_ERR(bdev))
|
||||||
return ERR_CAST(bdev);
|
return ERR_CAST(bdev);
|
||||||
|
@ -412,7 +412,7 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
|
|||||||
if (!f.file)
|
if (!f.file)
|
||||||
return error;
|
return error;
|
||||||
dentry = f.file->f_path.dentry;
|
dentry = f.file->f_path.dentry;
|
||||||
audit_inode(NULL, dentry);
|
audit_inode(NULL, dentry, 0);
|
||||||
error = mnt_want_write_file(f.file);
|
error = mnt_want_write_file(f.file);
|
||||||
if (!error) {
|
if (!error) {
|
||||||
error = setxattr(dentry, name, value, size, flags);
|
error = setxattr(dentry, name, value, size, flags);
|
||||||
@ -507,7 +507,7 @@ SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name,
|
|||||||
|
|
||||||
if (!f.file)
|
if (!f.file)
|
||||||
return error;
|
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);
|
error = getxattr(f.file->f_path.dentry, name, value, size);
|
||||||
fdput(f);
|
fdput(f);
|
||||||
return error;
|
return error;
|
||||||
@ -586,7 +586,7 @@ SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size)
|
|||||||
|
|
||||||
if (!f.file)
|
if (!f.file)
|
||||||
return error;
|
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);
|
error = listxattr(f.file->f_path.dentry, list, size);
|
||||||
fdput(f);
|
fdput(f);
|
||||||
return error;
|
return error;
|
||||||
@ -655,7 +655,7 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
|
|||||||
if (!f.file)
|
if (!f.file)
|
||||||
return error;
|
return error;
|
||||||
dentry = f.file->f_path.dentry;
|
dentry = f.file->f_path.dentry;
|
||||||
audit_inode(NULL, dentry);
|
audit_inode(NULL, dentry, 0);
|
||||||
error = mnt_want_write_file(f.file);
|
error = mnt_want_write_file(f.file);
|
||||||
if (!error) {
|
if (!error) {
|
||||||
error = removexattr(dentry, name);
|
error = removexattr(dentry, name);
|
||||||
|
@ -452,6 +452,16 @@ struct audit_field {
|
|||||||
extern int __init audit_register_class(int class, unsigned *list);
|
extern int __init audit_register_class(int class, unsigned *list);
|
||||||
extern int audit_classify_syscall(int abi, unsigned syscall);
|
extern int audit_classify_syscall(int abi, unsigned syscall);
|
||||||
extern int audit_classify_arch(int arch);
|
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
|
#ifdef CONFIG_AUDITSYSCALL
|
||||||
/* These are defined in auditsc.c */
|
/* These are defined in auditsc.c */
|
||||||
/* Public API */
|
/* Public API */
|
||||||
@ -461,11 +471,14 @@ extern void __audit_syscall_entry(int arch,
|
|||||||
int major, unsigned long a0, unsigned long a1,
|
int major, unsigned long a0, unsigned long a1,
|
||||||
unsigned long a2, unsigned long a3);
|
unsigned long a2, unsigned long a3);
|
||||||
extern void __audit_syscall_exit(int ret_success, long ret_value);
|
extern void __audit_syscall_exit(int ret_success, long ret_value);
|
||||||
extern void __audit_getname(const char *name);
|
extern struct filename *__audit_reusename(const __user char *uptr);
|
||||||
extern void audit_putname(const char *name);
|
extern void __audit_getname(struct filename *name);
|
||||||
extern void __audit_inode(const char *name, const struct dentry *dentry);
|
extern void audit_putname(struct filename *name);
|
||||||
extern void __audit_inode_child(const struct dentry *dentry,
|
extern void __audit_inode(struct filename *name, const struct dentry *dentry,
|
||||||
const struct inode *parent);
|
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_seccomp(unsigned long syscall, long signr, int code);
|
||||||
extern void __audit_ptrace(struct task_struct *t);
|
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);
|
__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()))
|
if (unlikely(!audit_dummy_context()))
|
||||||
__audit_getname(name);
|
__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()))
|
if (unlikely(!audit_dummy_context()))
|
||||||
__audit_inode(name, dentry);
|
__audit_inode(name, dentry, parent);
|
||||||
}
|
}
|
||||||
static inline void audit_inode_child(const struct dentry *dentry,
|
static inline void audit_inode_child(const struct inode *parent,
|
||||||
const struct inode *parent) {
|
const struct dentry *dentry,
|
||||||
|
const unsigned char type) {
|
||||||
if (unlikely(!audit_dummy_context()))
|
if (unlikely(!audit_dummy_context()))
|
||||||
__audit_inode_child(dentry, parent);
|
__audit_inode_child(parent, dentry, type);
|
||||||
}
|
}
|
||||||
void audit_core_dumps(long signr);
|
void audit_core_dumps(long signr);
|
||||||
|
|
||||||
@ -651,19 +672,29 @@ static inline int audit_dummy_context(void)
|
|||||||
{
|
{
|
||||||
return 1;
|
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,
|
static inline void __audit_inode_child(const struct inode *parent,
|
||||||
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,
|
static inline void audit_inode_child(const struct inode *parent,
|
||||||
const struct inode *parent)
|
const struct dentry *dentry,
|
||||||
|
const unsigned char type)
|
||||||
{ }
|
{ }
|
||||||
static inline void audit_core_dumps(long signr)
|
static inline void audit_core_dumps(long signr)
|
||||||
{ }
|
{ }
|
||||||
|
@ -2196,6 +2196,13 @@ static inline int break_lease(struct inode *inode, unsigned int mode)
|
|||||||
#endif /* CONFIG_FILE_LOCKING */
|
#endif /* CONFIG_FILE_LOCKING */
|
||||||
|
|
||||||
/* fs/open.c */
|
/* 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,
|
extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
|
||||||
struct file *filp);
|
struct file *filp);
|
||||||
@ -2203,12 +2210,15 @@ extern int do_fallocate(struct file *file, int mode, loff_t offset,
|
|||||||
loff_t len);
|
loff_t len);
|
||||||
extern long do_sys_open(int dfd, const char __user *filename, int flags,
|
extern long do_sys_open(int dfd, const char __user *filename, int flags,
|
||||||
umode_t mode);
|
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 *filp_open(const char *, int, umode_t);
|
||||||
extern struct file *file_open_root(struct dentry *, struct vfsmount *,
|
extern struct file *file_open_root(struct dentry *, struct vfsmount *,
|
||||||
const char *, int);
|
const char *, int);
|
||||||
extern struct file * dentry_open(const struct path *, int, const struct cred *);
|
extern struct file * dentry_open(const struct path *, int, const struct cred *);
|
||||||
extern int filp_close(struct file *, fl_owner_t id);
|
extern int filp_close(struct file *, fl_owner_t id);
|
||||||
extern char * getname(const char __user *);
|
|
||||||
|
extern struct filename *getname(const char __user *);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
FILE_CREATED = 1,
|
FILE_CREATED = 1,
|
||||||
FILE_OPENED = 2
|
FILE_OPENED = 2
|
||||||
@ -2228,13 +2238,14 @@ extern void __init vfs_caches_init(unsigned long);
|
|||||||
|
|
||||||
extern struct kmem_cache *names_cachep;
|
extern struct kmem_cache *names_cachep;
|
||||||
|
|
||||||
#define __getname_gfp(gfp) kmem_cache_alloc(names_cachep, (gfp))
|
extern void final_putname(struct filename *name);
|
||||||
#define __getname() __getname_gfp(GFP_KERNEL)
|
|
||||||
|
#define __getname() kmem_cache_alloc(names_cachep, GFP_KERNEL)
|
||||||
#define __putname(name) kmem_cache_free(names_cachep, (void *)(name))
|
#define __putname(name) kmem_cache_free(names_cachep, (void *)(name))
|
||||||
#ifndef CONFIG_AUDITSYSCALL
|
#ifndef CONFIG_AUDITSYSCALL
|
||||||
#define putname(name) __putname(name)
|
#define putname(name) final_putname(name)
|
||||||
#else
|
#else
|
||||||
extern void putname(const char *name);
|
extern void putname(struct filename *name);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_BLOCK
|
#ifdef CONFIG_BLOCK
|
||||||
|
@ -109,7 +109,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
|
|||||||
|
|
||||||
if (source)
|
if (source)
|
||||||
fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0);
|
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)
|
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);
|
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)
|
static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry)
|
||||||
{
|
{
|
||||||
fsnotify_link_count(inode);
|
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);
|
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);
|
__u32 mask = (FS_CREATE | FS_ISDIR);
|
||||||
struct inode *d_inode = dentry->d_inode;
|
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);
|
fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
|
||||||
}
|
}
|
||||||
|
@ -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)
|
void __init mount_block_root(char *name, int flags)
|
||||||
{
|
{
|
||||||
char *fs_names = __getname_gfp(GFP_KERNEL
|
struct page *page = alloc_page(GFP_KERNEL |
|
||||||
| __GFP_NOTRACK_FALSE_POSITIVE);
|
__GFP_NOTRACK_FALSE_POSITIVE);
|
||||||
|
char *fs_names = page_address(page);
|
||||||
char *p;
|
char *p;
|
||||||
#ifdef CONFIG_BLOCK
|
#ifdef CONFIG_BLOCK
|
||||||
char b[BDEVNAME_SIZE];
|
char b[BDEVNAME_SIZE];
|
||||||
@ -406,7 +407,7 @@ void __init mount_block_root(char *name, int flags)
|
|||||||
#endif
|
#endif
|
||||||
panic("VFS: Unable to mount root fs on %s", b);
|
panic("VFS: Unable to mount root fs on %s", b);
|
||||||
out:
|
out:
|
||||||
putname(fs_names);
|
put_page(page);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_ROOT_NFS
|
#ifdef CONFIG_ROOT_NFS
|
||||||
|
17
ipc/mqueue.c
17
ipc/mqueue.c
@ -772,7 +772,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
|
|||||||
{
|
{
|
||||||
struct path path;
|
struct path path;
|
||||||
struct file *filp;
|
struct file *filp;
|
||||||
char *name;
|
struct filename *name;
|
||||||
struct mq_attr attr;
|
struct mq_attr attr;
|
||||||
int fd, error;
|
int fd, error;
|
||||||
struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
|
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 */
|
ro = mnt_want_write(mnt); /* we'll drop it in any case */
|
||||||
error = 0;
|
error = 0;
|
||||||
mutex_lock(&root->d_inode->i_mutex);
|
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)) {
|
if (IS_ERR(path.dentry)) {
|
||||||
error = PTR_ERR(path.dentry);
|
error = PTR_ERR(path.dentry);
|
||||||
goto out_putfd;
|
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 (oflag & O_CREAT) {
|
||||||
if (path.dentry->d_inode) { /* entry already exists */
|
if (path.dentry->d_inode) { /* entry already exists */
|
||||||
audit_inode(name, path.dentry);
|
audit_inode(name, path.dentry, 0);
|
||||||
if (oflag & O_EXCL) {
|
if (oflag & O_EXCL) {
|
||||||
error = -EEXIST;
|
error = -EEXIST;
|
||||||
goto out;
|
goto out;
|
||||||
@ -824,7 +824,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
|
|||||||
error = -ENOENT;
|
error = -ENOENT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
audit_inode(name, path.dentry);
|
audit_inode(name, path.dentry, 0);
|
||||||
filp = do_open(&path, oflag);
|
filp = do_open(&path, oflag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -849,7 +849,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
|
|||||||
SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
|
SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
char *name;
|
struct filename *name;
|
||||||
struct dentry *dentry;
|
struct dentry *dentry;
|
||||||
struct inode *inode = NULL;
|
struct inode *inode = NULL;
|
||||||
struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
|
struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
|
||||||
@ -863,7 +863,8 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
|
|||||||
if (err)
|
if (err)
|
||||||
goto out_name;
|
goto out_name;
|
||||||
mutex_lock_nested(&mnt->mnt_root->d_inode->i_mutex, I_MUTEX_PARENT);
|
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)) {
|
if (IS_ERR(dentry)) {
|
||||||
err = PTR_ERR(dentry);
|
err = PTR_ERR(dentry);
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
@ -978,7 +979,7 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
|
|||||||
goto out_fput;
|
goto out_fput;
|
||||||
}
|
}
|
||||||
info = MQUEUE_I(inode);
|
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))) {
|
if (unlikely(!(f.file->f_mode & FMODE_WRITE))) {
|
||||||
ret = -EBADF;
|
ret = -EBADF;
|
||||||
@ -1094,7 +1095,7 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
|
|||||||
goto out_fput;
|
goto out_fput;
|
||||||
}
|
}
|
||||||
info = MQUEUE_I(inode);
|
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))) {
|
if (unlikely(!(f.file->f_mode & FMODE_READ))) {
|
||||||
ret = -EBADF;
|
ret = -EBADF;
|
||||||
|
@ -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 file *file;
|
||||||
struct vfsmount *mnt;
|
struct vfsmount *mnt;
|
||||||
@ -201,7 +201,7 @@ static int acct_on(char *name)
|
|||||||
struct bsd_acct_struct *acct = NULL;
|
struct bsd_acct_struct *acct = NULL;
|
||||||
|
|
||||||
/* Difference from BSD - they don't do O_APPEND */
|
/* 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))
|
if (IS_ERR(file))
|
||||||
return PTR_ERR(file);
|
return PTR_ERR(file);
|
||||||
|
|
||||||
@ -260,7 +260,7 @@ SYSCALL_DEFINE1(acct, const char __user *, name)
|
|||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
if (name) {
|
if (name) {
|
||||||
char *tmp = getname(name);
|
struct filename *tmp = getname(name);
|
||||||
if (IS_ERR(tmp))
|
if (IS_ERR(tmp))
|
||||||
return (PTR_ERR(tmp));
|
return (PTR_ERR(tmp));
|
||||||
error = acct_on(tmp);
|
error = acct_on(tmp);
|
||||||
|
@ -74,12 +74,15 @@ static inline int audit_hash_ino(u32 ino)
|
|||||||
return (ino & (AUDIT_INODE_BUCKETS-1));
|
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_match_class(int class, unsigned syscall);
|
||||||
extern int audit_comparator(const u32 left, const u32 op, const u32 right);
|
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_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_gid_comparator(kgid_t left, u32 op, kgid_t right);
|
||||||
extern int audit_compare_dname_path(const char *dname, const char *path,
|
extern int parent_len(const char *path);
|
||||||
int *dirlen);
|
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,
|
extern struct sk_buff * audit_make_reply(int pid, int seq, int type,
|
||||||
int done, int multi,
|
int done, int multi,
|
||||||
const void *payload, int size);
|
const void *payload, int size);
|
||||||
|
@ -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
|
/* Run all of the watches on this parent looking for the one that
|
||||||
* matches the given dname */
|
* matches the given dname */
|
||||||
list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) {
|
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;
|
continue;
|
||||||
|
|
||||||
/* If the update involves invalidating rules, do the inode-based
|
/* If the update involves invalidating rules, do the inode-based
|
||||||
|
@ -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. */
|
* parent_len - find the length of the parent portion of a pathname
|
||||||
int audit_compare_dname_path(const char *dname, const char *path,
|
* @path: pathname of which to determine length
|
||||||
int *dirlen)
|
*/
|
||||||
|
int parent_len(const char *path)
|
||||||
{
|
{
|
||||||
int dlen, plen;
|
int plen;
|
||||||
const char *p;
|
const char *p;
|
||||||
|
|
||||||
if (!dname || !path)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
dlen = strlen(dname);
|
|
||||||
plen = strlen(path);
|
plen = strlen(path);
|
||||||
if (plen < dlen)
|
|
||||||
return 1;
|
if (plen == 0)
|
||||||
|
return plen;
|
||||||
|
|
||||||
/* disregard trailing slashes */
|
/* disregard trailing slashes */
|
||||||
p = path + plen - 1;
|
p = path + plen - 1;
|
||||||
while ((*p == '/') && (p > path))
|
while ((*p == '/') && (p > path))
|
||||||
p--;
|
p--;
|
||||||
|
|
||||||
/* find last path component */
|
/* walk backward until we find the next slash or hit beginning */
|
||||||
p = p - dlen + 1;
|
while ((*p != '/') && (p > path))
|
||||||
if (p < path)
|
p--;
|
||||||
return 1;
|
|
||||||
else if (p > path) {
|
/* did we find a slash? Then increment to include it in path */
|
||||||
if (*--p != '/')
|
if (*p == '/')
|
||||||
return 1;
|
p++;
|
||||||
else
|
|
||||||
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;
|
||||||
|
|
||||||
|
parentlen = parentlen == AUDIT_NAME_FULL ? parent_len(path) : parentlen;
|
||||||
|
if (pathlen - parentlen != dlen)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
p = path + parentlen;
|
||||||
|
|
||||||
/* return length of path's directory component */
|
|
||||||
if (dirlen)
|
|
||||||
*dirlen = p - path;
|
|
||||||
return strncmp(p, dname, dlen);
|
return strncmp(p, dname, dlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
219
kernel/auditsc.c
219
kernel/auditsc.c
@ -81,9 +81,6 @@
|
|||||||
* a name dynamically and also add those to the list anchored by names_list. */
|
* a name dynamically and also add those to the list anchored by names_list. */
|
||||||
#define AUDIT_NAMES 5
|
#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) */
|
/* no execve audit message should be longer than this (userspace limits) */
|
||||||
#define MAX_EXECVE_AUDIT_LEN 7500
|
#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
|
* we don't let putname() free it (instead we free all of the saved
|
||||||
* pointers at syscall exit time).
|
* 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 audit_names {
|
||||||
struct list_head list; /* audit_context->names_list */
|
struct list_head list; /* audit_context->names_list */
|
||||||
const char *name;
|
struct filename *name;
|
||||||
unsigned long ino;
|
unsigned long ino;
|
||||||
dev_t dev;
|
dev_t dev;
|
||||||
umode_t mode;
|
umode_t mode;
|
||||||
kuid_t uid;
|
kuid_t uid;
|
||||||
kgid_t gid;
|
kgid_t gid;
|
||||||
dev_t rdev;
|
dev_t rdev;
|
||||||
u32 osid;
|
u32 osid;
|
||||||
struct audit_cap_data fcap;
|
struct audit_cap_data fcap;
|
||||||
unsigned int fcap_ver;
|
unsigned int fcap_ver;
|
||||||
int name_len; /* number of name's characters to log */
|
int name_len; /* number of name's characters to log */
|
||||||
bool name_put; /* call __putname() for this name */
|
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
|
* This was an allocated audit_names and not from the array of
|
||||||
* names allocated in the task audit context. Thus this name
|
* names allocated in the task audit context. Thus this name
|
||||||
* should be freed on syscall exit
|
* should be freed on syscall exit
|
||||||
*/
|
*/
|
||||||
bool should_free;
|
bool should_free;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct audit_aux_data {
|
struct audit_aux_data {
|
||||||
@ -998,7 +997,7 @@ static inline void audit_free_names(struct audit_context *context)
|
|||||||
context->ino_count);
|
context->ino_count);
|
||||||
list_for_each_entry(n, &context->names_list, list) {
|
list_for_each_entry(n, &context->names_list, list) {
|
||||||
printk(KERN_ERR "names[%d] = %p = %s\n", i,
|
printk(KERN_ERR "names[%d] = %p = %s\n", i,
|
||||||
n->name, n->name ?: "(null)");
|
n->name, n->name->name ?: "(null)");
|
||||||
}
|
}
|
||||||
dump_stack();
|
dump_stack();
|
||||||
return;
|
return;
|
||||||
@ -1555,7 +1554,7 @@ static void audit_log_name(struct audit_context *context, struct audit_names *n,
|
|||||||
case AUDIT_NAME_FULL:
|
case AUDIT_NAME_FULL:
|
||||||
/* log the full path */
|
/* log the full path */
|
||||||
audit_log_format(ab, " name=");
|
audit_log_format(ab, " name=");
|
||||||
audit_log_untrustedstring(ab, n->name);
|
audit_log_untrustedstring(ab, n->name->name);
|
||||||
break;
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
/* name was specified as a relative path and the
|
/* 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:
|
default:
|
||||||
/* log the name's directory component */
|
/* log the name's directory component */
|
||||||
audit_log_format(ab, " name=");
|
audit_log_format(ab, " name=");
|
||||||
audit_log_n_untrustedstring(ab, n->name,
|
audit_log_n_untrustedstring(ab, n->name->name,
|
||||||
n->name_len);
|
n->name_len);
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
@ -1995,7 +1994,8 @@ static void handle_path(const struct dentry *dentry)
|
|||||||
#endif
|
#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;
|
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->ino = (unsigned long)-1;
|
||||||
|
aname->type = type;
|
||||||
list_add_tail(&aname->list, &context->names_list);
|
list_add_tail(&aname->list, &context->names_list);
|
||||||
|
|
||||||
context->name_count++;
|
context->name_count++;
|
||||||
@ -2019,6 +2020,29 @@ static struct audit_names *audit_alloc_name(struct audit_context *context)
|
|||||||
return aname;
|
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
|
* audit_getname - add a name to the list
|
||||||
* @name: name to add
|
* @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.
|
* Add a name to the list of audit names for this context.
|
||||||
* Called from fs/namei.c:getname().
|
* 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_context *context = current->audit_context;
|
||||||
struct audit_names *n;
|
struct audit_names *n;
|
||||||
@ -2040,13 +2064,19 @@ void __audit_getname(const char *name)
|
|||||||
return;
|
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)
|
if (!n)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
n->name = name;
|
n->name = name;
|
||||||
n->name_len = AUDIT_NAME_FULL;
|
n->name_len = AUDIT_NAME_FULL;
|
||||||
n->name_put = true;
|
n->name_put = true;
|
||||||
|
name->aname = n;
|
||||||
|
|
||||||
if (!context->pwd.dentry)
|
if (!context->pwd.dentry)
|
||||||
get_fs_pwd(current->fs, &context->pwd);
|
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.
|
* then we delay the putname until syscall exit.
|
||||||
* Called from include/linux/fs.h:putname().
|
* 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;
|
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)
|
list_for_each_entry(n, &context->names_list, list)
|
||||||
printk(KERN_ERR "name[%d] = %p = %s\n", i,
|
printk(KERN_ERR "name[%d] = %p = %s\n", i,
|
||||||
n->name, n->name ?: "(null)");
|
n->name, n->name->name ?: "(null)");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
__putname(name);
|
__putname(name);
|
||||||
@ -2088,8 +2118,8 @@ void audit_putname(const char *name)
|
|||||||
" put_count=%d\n",
|
" put_count=%d\n",
|
||||||
__FILE__, __LINE__,
|
__FILE__, __LINE__,
|
||||||
context->serial, context->major,
|
context->serial, context->major,
|
||||||
context->in_syscall, name, context->name_count,
|
context->in_syscall, name->name,
|
||||||
context->put_count);
|
context->name_count, context->put_count);
|
||||||
dump_stack();
|
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
|
* @name: name being audited
|
||||||
* @dentry: dentry being audited
|
* @dentry: dentry being audited
|
||||||
*
|
* @parent: does this dentry represent the parent?
|
||||||
* Called from fs/namei.c:path_lookup().
|
|
||||||
*/
|
*/
|
||||||
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;
|
struct audit_context *context = current->audit_context;
|
||||||
const struct inode *inode = dentry->d_inode;
|
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)
|
if (!context->in_syscall)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
list_for_each_entry_reverse(n, &context->names_list, list) {
|
if (!name)
|
||||||
if (n->name && (n->name == name))
|
goto out_alloc;
|
||||||
goto out;
|
|
||||||
|
#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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unable to find the name from a previous getname() */
|
list_for_each_entry_reverse(n, &context->names_list, list) {
|
||||||
n = audit_alloc_name(context);
|
/* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
if (!n)
|
||||||
return;
|
return;
|
||||||
out:
|
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);
|
handle_path(dentry);
|
||||||
audit_copy_inode(n, dentry, inode);
|
audit_copy_inode(n, dentry, inode);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* audit_inode_child - collect inode info for created/removed objects
|
* __audit_inode_child - collect inode info for created/removed objects
|
||||||
* @dentry: dentry being audited
|
|
||||||
* @parent: inode of dentry parent
|
* @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
|
* For syscalls that create or remove filesystem objects, audit_inode
|
||||||
* can only collect information for the filesystem object's parent.
|
* can only collect information for the filesystem object's parent.
|
||||||
@ -2174,15 +2249,14 @@ void __audit_inode(const char *name, const struct dentry *dentry)
|
|||||||
* must be hooked prior, in order to capture the target inode during
|
* must be hooked prior, in order to capture the target inode during
|
||||||
* unsuccessful attempts.
|
* unsuccessful attempts.
|
||||||
*/
|
*/
|
||||||
void __audit_inode_child(const struct dentry *dentry,
|
void __audit_inode_child(const struct inode *parent,
|
||||||
const struct inode *parent)
|
const struct dentry *dentry,
|
||||||
|
const unsigned char type)
|
||||||
{
|
{
|
||||||
struct audit_context *context = current->audit_context;
|
struct audit_context *context = current->audit_context;
|
||||||
const char *found_parent = NULL, *found_child = NULL;
|
|
||||||
const struct inode *inode = dentry->d_inode;
|
const struct inode *inode = dentry->d_inode;
|
||||||
const char *dname = dentry->d_name.name;
|
const char *dname = dentry->d_name.name;
|
||||||
struct audit_names *n;
|
struct audit_names *n, *found_parent = NULL, *found_child = NULL;
|
||||||
int dirlen = 0;
|
|
||||||
|
|
||||||
if (!context->in_syscall)
|
if (!context->in_syscall)
|
||||||
return;
|
return;
|
||||||
@ -2190,62 +2264,65 @@ void __audit_inode_child(const struct dentry *dentry,
|
|||||||
if (inode)
|
if (inode)
|
||||||
handle_one(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) {
|
list_for_each_entry(n, &context->names_list, list) {
|
||||||
if (!n->name)
|
if (!n->name || n->type != AUDIT_TYPE_PARENT)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (n->ino == parent->i_ino &&
|
if (n->ino == parent->i_ino &&
|
||||||
!audit_compare_dname_path(dname, n->name, &dirlen)) {
|
!audit_compare_dname_path(dname, n->name->name, n->name_len)) {
|
||||||
n->name_len = dirlen; /* update parent data in place */
|
found_parent = n;
|
||||||
found_parent = n->name;
|
break;
|
||||||
goto add_names;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* no matching parent, look for matching child */
|
/* is there a matching child entry? */
|
||||||
list_for_each_entry(n, &context->names_list, list) {
|
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;
|
continue;
|
||||||
|
|
||||||
/* strcmp() is the more likely scenario */
|
/* if we found a parent, make sure this one is a child of it */
|
||||||
if (!strcmp(dname, n->name) ||
|
if (found_parent && (n->name != found_parent->name))
|
||||||
!audit_compare_dname_path(dname, n->name, &dirlen)) {
|
continue;
|
||||||
if (inode)
|
|
||||||
audit_copy_inode(n, NULL, inode);
|
if (!strcmp(dname, n->name->name) ||
|
||||||
else
|
!audit_compare_dname_path(dname, n->name->name,
|
||||||
n->ino = (unsigned long)-1;
|
found_parent ?
|
||||||
found_child = n->name;
|
found_parent->name_len :
|
||||||
goto add_names;
|
AUDIT_NAME_FULL)) {
|
||||||
|
found_child = n;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
add_names:
|
|
||||||
if (!found_parent) {
|
if (!found_parent) {
|
||||||
n = audit_alloc_name(context);
|
/* create a new, "anonymous" parent record */
|
||||||
|
n = audit_alloc_name(context, AUDIT_TYPE_PARENT);
|
||||||
if (!n)
|
if (!n)
|
||||||
return;
|
return;
|
||||||
audit_copy_inode(n, NULL, parent);
|
audit_copy_inode(n, NULL, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found_child) {
|
if (!found_child) {
|
||||||
n = audit_alloc_name(context);
|
found_child = audit_alloc_name(context, type);
|
||||||
if (!n)
|
if (!found_child)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* Re-use the name belonging to the slot for a matching parent
|
/* Re-use the name belonging to the slot for a matching parent
|
||||||
* directory. All names for this context are relinquished in
|
* directory. All names for this context are relinquished in
|
||||||
* audit_free_names() */
|
* audit_free_names() */
|
||||||
if (found_parent) {
|
if (found_parent) {
|
||||||
n->name = found_parent;
|
found_child->name = found_parent->name;
|
||||||
n->name_len = AUDIT_NAME_FULL;
|
found_child->name_len = AUDIT_NAME_FULL;
|
||||||
/* don't call __putname() */
|
/* 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);
|
EXPORT_SYMBOL_GPL(__audit_inode_child);
|
||||||
|
|
||||||
|
@ -1483,7 +1483,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
|
|||||||
struct file *swap_file, *victim;
|
struct file *swap_file, *victim;
|
||||||
struct address_space *mapping;
|
struct address_space *mapping;
|
||||||
struct inode *inode;
|
struct inode *inode;
|
||||||
char *pathname;
|
struct filename *pathname;
|
||||||
int oom_score_adj;
|
int oom_score_adj;
|
||||||
int i, type, prev;
|
int i, type, prev;
|
||||||
int err;
|
int err;
|
||||||
@ -1498,8 +1498,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
|
|||||||
if (IS_ERR(pathname))
|
if (IS_ERR(pathname))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
victim = filp_open(pathname, O_RDWR|O_LARGEFILE, 0);
|
victim = file_open_name(pathname, O_RDWR|O_LARGEFILE, 0);
|
||||||
putname(pathname);
|
|
||||||
err = PTR_ERR(victim);
|
err = PTR_ERR(victim);
|
||||||
if (IS_ERR(victim))
|
if (IS_ERR(victim))
|
||||||
goto out;
|
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)
|
SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
|
||||||
{
|
{
|
||||||
struct swap_info_struct *p;
|
struct swap_info_struct *p;
|
||||||
char *name;
|
struct filename *name;
|
||||||
struct file *swap_file = NULL;
|
struct file *swap_file = NULL;
|
||||||
struct address_space *mapping;
|
struct address_space *mapping;
|
||||||
int i;
|
int i;
|
||||||
@ -1967,7 +1966,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
|
|||||||
name = NULL;
|
name = NULL;
|
||||||
goto bad_swap;
|
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)) {
|
if (IS_ERR(swap_file)) {
|
||||||
error = PTR_ERR(swap_file);
|
error = PTR_ERR(swap_file);
|
||||||
swap_file = NULL;
|
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. "
|
printk(KERN_INFO "Adding %uk swap on %s. "
|
||||||
"Priority:%d extents:%d across:%lluk %s%s%s\n",
|
"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),
|
nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10),
|
||||||
(p->flags & SWP_SOLIDSTATE) ? "SS" : "",
|
(p->flags & SWP_SOLIDSTATE) ? "SS" : "",
|
||||||
(p->flags & SWP_DISCARDABLE) ? "D" : "",
|
(p->flags & SWP_DISCARDABLE) ? "D" : "",
|
||||||
|
Loading…
Reference in New Issue
Block a user