Commit 8418263e authored by Linus Torvalds's avatar Linus Torvalds

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
parents ccff9b1d f81700bd
......@@ -449,7 +449,7 @@ osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
{
int retval;
struct cdfs_args tmp;
char *devname;
struct filename *devname;
retval = -EFAULT;
if (copy_from_user(&tmp, args, sizeof(tmp)))
......@@ -458,7 +458,7 @@ osf_ufs_mount(char *dirname, struct ufs_args __user *args, int flags)
retval = PTR_ERR(devname);
if (IS_ERR(devname))
goto out;
retval = do_mount(devname, dirname, "ext2", flags, NULL);
retval = do_mount(devname->name, dirname, "ext2", flags, NULL);
putname(devname);
out:
return retval;
......@@ -469,7 +469,7 @@ osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
{
int retval;
struct cdfs_args tmp;
char *devname;
struct filename *devname;
retval = -EFAULT;
if (copy_from_user(&tmp, args, sizeof(tmp)))
......@@ -478,7 +478,7 @@ osf_cdfs_mount(char *dirname, struct cdfs_args __user *args, int flags)
retval = PTR_ERR(devname);
if (IS_ERR(devname))
goto out;
retval = do_mount(devname, dirname, "iso9660", flags, NULL);
retval = do_mount(devname->name, dirname, "iso9660", flags, NULL);
putname(devname);
out:
return retval;
......@@ -499,7 +499,7 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, const char __user *, path,
int, flag, void __user *, data)
{
int retval;
char *name;
struct filename *name;
name = getname(path);
retval = PTR_ERR(name);
......@@ -507,13 +507,13 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, const char __user *, path,
goto out;
switch (typenr) {
case 1:
retval = osf_ufs_mount(name, data, flag);
retval = osf_ufs_mount(name->name, data, flag);
break;
case 6:
retval = osf_cdfs_mount(name, data, flag);
retval = osf_cdfs_mount(name->name, data, flag);
break;
case 9:
retval = osf_procfs_mount(name, data, flag);
retval = osf_procfs_mount(name->name, data, flag);
break;
default:
retval = -EINVAL;
......
......@@ -50,13 +50,13 @@ asmlinkage long sys_execve(const char __user *filenamei,
struct pt_regs *regs)
{
long error;
char * filename;
struct filename *filename;
filename = getname(filenamei);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename, argv, envp, regs);
error = do_execve(filename->name, argv, envp, regs);
putname(filename);
out:
return error;
......
......@@ -56,14 +56,14 @@ asmlinkage int compat_sys_execve(const char __user *filenamei,
struct pt_regs *regs)
{
int error;
char * filename;
struct filename *filename;
filename = getname(filenamei);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = compat_do_execve(filename, compat_ptr(argv), compat_ptr(envp),
regs);
error = compat_do_execve(filename->name, compat_ptr(argv),
compat_ptr(envp), regs);
putname(filename);
out:
return error;
......
......@@ -388,14 +388,14 @@ asmlinkage int sys_execve(const char __user *ufilename,
struct pt_regs *regs)
{
int error;
char *filename;
struct filename *filename;
filename = getname(ufilename);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename, uargv, uenvp, regs);
error = do_execve(filename->name, uargv, uenvp, regs);
putname(filename);
out:
......
......@@ -213,14 +213,14 @@ asmlinkage int sys_execve(const char __user *name,
const char __user *const __user *envp)
{
int error;
char *filename;
struct filename *filename;
struct pt_regs *regs = (struct pt_regs *)((&name) + 6);
filename = getname(name);
error = PTR_ERR(filename);
if (IS_ERR(filename))
return error;
error = do_execve(filename, argv, envp, regs);
error = do_execve(filename->name, argv, envp, regs);
putname(filename);
return error;
}
......
......@@ -212,14 +212,14 @@ asmlinkage int sys_execve(const char *fname,
struct pt_regs *regs)
{
int error;
char *filename;
struct filename *filename;
filename = getname(fname);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename, argv, envp, regs);
error = do_execve(filename->name, argv, envp, regs);
putname(filename);
out:
return error;
......
......@@ -224,7 +224,7 @@ sys_execve(const char *fname,
struct pt_regs *regs)
{
int error;
char *filename;
struct filename *filename;
filename = getname(fname);
error = PTR_ERR(filename);
......@@ -232,7 +232,7 @@ sys_execve(const char *fname,
if (IS_ERR(filename))
goto out;
error = do_execve(filename, argv, envp, regs);
error = do_execve(filename->name, argv, envp, regs);
putname(filename);
out:
return error;
......
......@@ -217,14 +217,14 @@ asmlinkage int sys_execve(const char *name,
int dummy, ...)
{
int error;
char * filename;
struct filename *filename;
struct pt_regs *regs = (struct pt_regs *) ((unsigned char *)&dummy-4);
filename = getname(name);
error = PTR_ERR(filename);
if (IS_ERR(filename))
return error;
error = do_execve(filename, argv, envp, regs);
error = do_execve(filename->name, argv, envp, regs);
putname(filename);
return error;
}
......
......@@ -40,7 +40,7 @@ asmlinkage int sys_execve(char __user *ufilename,
const char __user *const __user *envp)
{
struct pt_regs *pregs = current_thread_info()->regs;
char *filename;
struct filename *filename;
int retval;
filename = getname(ufilename);
......@@ -48,7 +48,7 @@ asmlinkage int sys_execve(char __user *ufilename,
if (IS_ERR(filename))
return retval;
retval = do_execve(filename, argv, envp, pregs);
retval = do_execve(filename->name, argv, envp, pregs);
putname(filename);
return retval;
......
......@@ -614,14 +614,14 @@ sys_execve (const char __user *filename,
const char __user *const __user *envp,
struct pt_regs *regs)
{
char *fname;
struct filename *fname;
int error;
fname = getname(filename);
error = PTR_ERR(fname);
if (IS_ERR(fname))
goto out;
error = do_execve(fname, argv, envp, regs);
error = do_execve(fname->name, argv, envp, regs);
putname(fname);
out:
return error;
......
......@@ -296,14 +296,14 @@ asmlinkage int sys_execve(const char __user *ufilename,
unsigned long r6, struct pt_regs regs)
{
int error;
char *filename;
struct filename *filename;
filename = getname(ufilename);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename, uargv, uenvp, &regs);
error = do_execve(filename->name, uargv, uenvp, &regs);
putname(filename);
out:
return error;
......
......@@ -54,13 +54,13 @@ asmlinkage long microblaze_execve(const char __user *filenamei,
struct pt_regs *regs)
{
int error;
char *filename;
struct filename *filename;
filename = getname(filenamei);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename, argv, envp, regs);
error = do_execve(filename->name, argv, envp, regs);
putname(filename);
out:
return error;
......
......@@ -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)
{
int error;
char * filename;
struct filename *filename;
filename = getname(compat_ptr(regs.regs[4]));
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = compat_do_execve(filename, compat_ptr(regs.regs[5]),
error = compat_do_execve(filename->name, compat_ptr(regs.regs[5]),
compat_ptr(regs.regs[6]), &regs);
putname(filename);
......
......@@ -133,13 +133,13 @@ _sys_clone(nabi_no_regargs struct pt_regs regs)
asmlinkage int sys_execve(nabi_no_regargs struct pt_regs regs)
{
int error;
char * filename;
struct filename *filename;
filename = getname((const char __user *) (long)regs.regs[4]);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename,
error = do_execve(filename->name,
(const char __user *const __user *) (long)regs.regs[5],
(const char __user *const __user *) (long)regs.regs[6],
&regs);
......
......@@ -271,7 +271,7 @@ asmlinkage long _sys_execve(const char __user *name,
struct pt_regs *regs)
{
int error;
char *filename;
struct filename *filename;
filename = getname(name);
error = PTR_ERR(filename);
......@@ -279,7 +279,7 @@ asmlinkage long _sys_execve(const char __user *name,
if (IS_ERR(filename))
goto out;
error = do_execve(filename, argv, envp, regs);
error = do_execve(filename->name, argv, envp, regs);
putname(filename);
out:
......
......@@ -34,14 +34,14 @@
int hpux_execve(struct pt_regs *regs)
{
int error;
char *filename;
struct filename *filename;
filename = getname((const char __user *) regs->gr[26]);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename,
error = do_execve(filename->name,
(const char __user *const __user *) regs->gr[25],
(const char __user *const __user *) regs->gr[24],
regs);
......
......@@ -342,13 +342,13 @@ unsigned long thread_saved_pc(struct task_struct *t)
asmlinkage int sys_execve(struct pt_regs *regs)
{
int error;
char *filename;
struct filename *filename;
filename = getname((const char __user *) regs->gr[26]);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename,
error = do_execve(filename->name,
(const char __user *const __user *) regs->gr[25],
(const char __user *const __user *) regs->gr[24],
regs);
......
......@@ -60,14 +60,14 @@
asmlinkage int sys32_execve(struct pt_regs *regs)
{
int error;
char *filename;
struct filename *filename;
DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26]));
filename = getname((const char __user *) regs->gr[26]);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = compat_do_execve(filename, compat_ptr(regs->gr[25]),
error = compat_do_execve(filename->name, compat_ptr(regs->gr[25]),
compat_ptr(regs->gr[24]), regs);
putname(filename);
out:
......
......@@ -92,14 +92,14 @@ asmlinkage long
score_execve(struct pt_regs *regs)
{
int error;
char *filename;
struct filename *filename;
filename = getname((char __user*)regs->regs[4]);
error = PTR_ERR(filename);
if (IS_ERR(filename))
return error;
error = do_execve(filename,
error = do_execve(filename->name,
(const char __user *const __user *)regs->regs[5],
(const char __user *const __user *)regs->regs[6],
regs);
......
......@@ -298,14 +298,14 @@ asmlinkage int sys_execve(const char __user *ufilename,
{
struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
int error;
char *filename;
struct filename *filename;
filename = getname(ufilename);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename, uargv, uenvp, regs);
error = do_execve(filename->name, uargv, uenvp, regs);
putname(filename);
out:
return error;
......
......@@ -491,14 +491,14 @@ asmlinkage int sys_execve(const char *ufilename, char **uargv,
struct pt_regs *pregs)
{
int error;
char *filename;
struct filename *filename;
filename = getname((char __user *)ufilename);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename,
error = do_execve(filename->name,
(const char __user *const __user *)uargv,
(const char __user *const __user *)uenvp,
pregs);
......
......@@ -482,7 +482,7 @@ int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs)
asmlinkage int sparc_execve(struct pt_regs *regs)
{
int error, base = 0;
char *filename;
struct filename *filename;
/* Check for indirect call. */
if(regs->u_regs[UREG_G1] == 0)
......@@ -492,7 +492,7 @@ asmlinkage int sparc_execve(struct pt_regs *regs)
error = PTR_ERR(filename);
if(IS_ERR(filename))
goto out;
error = do_execve(filename,
error = do_execve(filename->name,
(const char __user *const __user *)
regs->u_regs[base + UREG_I1],
(const char __user *const __user *)
......
......@@ -722,7 +722,7 @@ EXPORT_SYMBOL(dump_fpu);
asmlinkage int sparc_execve(struct pt_regs *regs)
{
int error, base = 0;
char *filename;
struct filename *filename;
/* User register window flush is done by entry.S */
......@@ -734,7 +734,7 @@ asmlinkage int sparc_execve(struct pt_regs *regs)
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename,
error = do_execve(filename->name,
(const char __user *const __user *)
regs->u_regs[base + UREG_I1],
(const char __user *const __user *)
......
......@@ -403,7 +403,7 @@ asmlinkage long compat_sys_rt_sigaction(int sig,
asmlinkage long sparc32_execve(struct pt_regs *regs)
{
int error, base = 0;
char *filename;
struct filename *filename;
/* User register window flush is done by entry.S */
......@@ -416,7 +416,7 @@ asmlinkage long sparc32_execve(struct pt_regs *regs)
if (IS_ERR(filename))
goto out;
error = compat_do_execve(filename,
error = compat_do_execve(filename->name,
compat_ptr(regs->u_regs[base + UREG_I1]),
compat_ptr(regs->u_regs[base + UREG_I2]), regs);
......
......@@ -594,13 +594,13 @@ SYSCALL_DEFINE4(execve, const char __user *, path,
struct pt_regs *, regs)
{
long error;
char *filename;
struct filename *filename;
filename = getname(path);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename, argv, envp, regs);
error = do_execve(filename->name, argv, envp, regs);
putname(filename);
if (error == 0)
single_step_execve();
......@@ -615,13 +615,13 @@ long compat_sys_execve(const char __user *path,
struct pt_regs *regs)
{
long error;
char *filename;
struct filename *filename;
filename = getname(path);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = compat_do_execve(filename, argv, envp, regs);
error = compat_do_execve(filename->name, argv, envp, regs);
putname(filename);
if (error == 0)
single_step_execve();
......
......@@ -51,13 +51,13 @@ asmlinkage long __sys_execve(const char __user *filename,
struct pt_regs *regs)
{
int error;
char *fn;
struct filename *fn;
fn = getname(filename);
error = PTR_ERR(fn);
if (IS_ERR(fn))
goto out;
error = do_execve(fn, argv, envp, regs);
error = do_execve(fn->name, argv, envp, regs);
putname(fn);
out:
return error;
......
......@@ -328,13 +328,13 @@ long xtensa_execve(const char __user *name,
struct pt_regs *regs)
{
long error;
char * filename;
struct filename *filename;
filename = getname(name);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename, argv, envp, regs);
error = do_execve(filename->name, argv, envp, regs);
putname(filename);
out:
return error;
......
......@@ -638,7 +638,7 @@ static int btrfs_may_delete(struct inode *dir,struct dentry *victim,int isdir)
return -ENOENT;
BUG_ON(victim->d_parent->d_inode != dir);
audit_inode_child(victim, dir);
audit_inode_child(dir, victim, AUDIT_TYPE_CHILD_DELETE);
error = inode_permission(dir, MAY_WRITE | MAY_EXEC);
if (error)
......
......@@ -776,16 +776,16 @@ asmlinkage long compat_sys_mount(const char __user * dev_name,
char *kernel_type;
unsigned long data_page;
char *kernel_dev;
char *dir_page;
struct filename *dir;
int retval;
retval = copy_mount_string(type, &kernel_type);
if (retval < 0)
goto out;
dir_page = getname(dir_name);
retval = PTR_ERR(dir_page);
if (IS_ERR(dir_page))
dir = getname(dir_name);
retval = PTR_ERR(dir);
if (IS_ERR(dir))
goto out1;
retval = copy_mount_string(dev_name, &kernel_dev);
......@@ -807,7 +807,7 @@ asmlinkage long compat_sys_mount(const char __user * dev_name,
}
}
retval = do_mount(kernel_dev, dir_page, kernel_type,
retval = do_mount(kernel_dev, dir->name, kernel_type,
flags, (void*)data_page);
out4:
......@@ -815,7 +815,7 @@ asmlinkage long compat_sys_mount(const char __user * dev_name,
out3:
kfree(kernel_dev);
out2:
putname(dir_page);
putname(dir);
out1:
kfree(kernel_type);
out:
......
......@@ -105,7 +105,7 @@ static inline void put_binfmt(struct linux_binfmt * fmt)
SYSCALL_DEFINE1(uselib, const char __user *, library)
{
struct file *file;
char *tmp = getname(library);
struct filename *tmp = getname(library);
int error = PTR_ERR(tmp);
static const struct open_flags uselib_flags = {
.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
......@@ -751,13 +751,14 @@ struct file *open_exec(const char *name)
{
struct file *file;
int err;
struct filename tmp = { .name = name };
static const struct open_flags open_exec_flags = {
.open_flag = O_LARGEFILE | O_RDONLY | __FMODE_EXEC,
.acc_mode = MAY_EXEC | MAY_OPEN,
.intent = LOOKUP_OPEN
};
file = do_filp_open(AT_FDCWD, name, &open_exec_flags, LOOKUP_FOLLOW);
file = do_filp_open(AT_FDCWD, &tmp, &open_exec_flags, LOOKUP_FOLLOW);
if (IS_ERR(file))
goto out;
......@@ -1664,10 +1665,10 @@ SYSCALL_DEFINE3(execve,
const char __user *const __user *, argv,
const char __user *const __user *, envp)
{
const char *path = getname(filename);
struct filename *path = getname(filename);
int error = PTR_ERR(path);
if (!IS_ERR(path)) {
error = do_execve(path, argv, envp, current_pt_regs());
error = do_execve(path->name, argv, envp, current_pt_regs());
putname(path);
}
return error;
......@@ -1677,10 +1678,11 @@ asmlinkage long compat_sys_execve(const char __user * filename,
const compat_uptr_t __user * argv,
const compat_uptr_t __user * envp)
{
const char *path = getname(filename);
struct filename *path = getname(filename);
int error = PTR_ERR(path);
if (!IS_ERR(path)) {
error = compat_do_execve(path, argv, envp, current_pt_regs());
error = compat_do_execve(path->name, argv, envp,
current_pt_regs());
putname(path);
}
return error;
......
......@@ -124,7 +124,7 @@ EXPORT_SYMBOL(unregister_filesystem);
static int fs_index(const char __user * __name)
{
struct file_system_type * tmp;
char * name;
struct filename *name;
int err, index;
name = getname(__name);
......@@ -135,7 +135,7 @@ static int fs_index(const char __user * __name)
err = -EINVAL;
read_lock(&file_systems_lock);
for (tmp=file_systems, index=0 ; tmp ; tmp=tmp->next, index++) {
if (strcmp(tmp->name,name) == 0) {
if (strcmp(tmp->name, name->name) == 0) {
err = index;
break;
}
......
......@@ -97,8 +97,8 @@ struct open_flags {
int acc_mode;
int intent;
};
extern struct file *do_filp_open(int dfd, const char *pathname,
const struct open_flags *op, int lookup_flags);
extern struct file *do_filp_open(int dfd, struct filename *pathname,
const struct open_flags *op, int flags);
extern struct file *do_file_open_root(struct dentry *, struct vfsmount *,
const char *, const struct open_flags *, int lookup_flags);
......
This diff is collapsed.
......@@ -2408,7 +2408,7 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
{
int ret;
char *kernel_type;
char *kernel_dir;
struct filename *kernel_dir;
char *kernel_dev;
unsigned long data_page;
......@@ -2430,7 +2430,7 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name,
if (ret < 0)
goto out_data;
ret = do_mount(kernel_dev, kernel_dir, kernel_type, flags,
ret = do_mount(kernel_dev, kernel_dir->name, kernel_type, flags,
(void *) data_page);
free_page(data_page);
......
......@@ -478,7 +478,7 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd, umode_t, mode)
file = fget(fd);
if (file) {
audit_inode(NULL, file->f_path.dentry);
audit_inode(NULL, file->f_path.dentry, 0);
err = chmod_common(&file->f_path, mode);
fput(file);
}
......@@ -588,7 +588,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
error = mnt_want_write_file(f.file);
if (error)
goto out_fput;
audit_inode(NULL, f.file->f_path.dentry);
audit_inode(NULL, f.file->f_path.dentry, 0);
error = chown_common(&f.file->f_path, user, group);
mnt_drop_write_file(f.file);
out_fput:
......@@ -858,6 +858,24 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
return lookup_flags;
}
/**
* file_open_name - open file and return file pointer
*
* @name: struct filename containing path to open
* @flags: open flags as per the open(2) second argument
* @mode: mode for the new file if O_CREAT is set, else ignored
*
* This is the helper to open a file from kernelspace if you really
* have to. But in generally you should not do this, so please move
* along, nothing to see here..
*/
struct file *file_open_name(struct filename *name, int flags, umode_t mode)
{
struct open_flags op;
int lookup = build_open_flags(flags, mode, &op);
return do_filp_open(AT_FDCWD, name, &op, lookup);
}
/**
* filp_open - open file and return file pointer
*
......@@ -871,9 +889,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
*/
struct file *filp_open(const char *filename, int flags, umode_t mode)
{
struct open_flags op;
int lookup = build_open_flags(flags, mode, &op);
return do_filp_open(AT_FDCWD, filename, &op, lookup);
struct filename name = {.name = filename};
return file_open_name(&name, flags, mode);
}
EXPORT_SYMBOL(filp_open);
......@@ -895,7 +912,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
{
struct open_flags op;
int lookup = build_open_flags(flags, mode, &op);
char *tmp = getname(filename);
struct filename *tmp = getname(filename);
int fd = PTR_ERR(tmp);
if (!IS_ERR(tmp)) {
......
......@@ -2258,7 +2258,8 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
pid_t tgid = task_tgid_nr_ns(current, ns);
char *name = ERR_PTR(-ENOENT);
if (tgid) {
name = __getname();
/* 11 for max length of signed int in decimal + NULL term */
name = kmalloc(12, GFP_KERNEL);
if (!name)
name = ERR_PTR(-ENOMEM);
else
......@@ -2273,7 +2274,7 @@ static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd,
{
char *s = nd_get_link(nd);
if (!IS_ERR(s))
__putname(s);
kfree(s);
}
static const struct inode_operations proc_self_inode_operations = {
......
......@@ -331,11 +331,11 @@ static struct super_block *quotactl_block(const char __user *special, int cmd)
#ifdef CONFIG_BLOCK
struct block_device *bdev;
struct super_block *sb;
char *tmp = getname(special);
struct filename *tmp = getname(special);
if (IS_ERR(tmp))
return ERR_CAST(tmp);
bdev = lookup_bdev(tmp);
bdev = lookup_bdev(tmp->name);
putname(tmp);
if (IS_ERR(bdev))
return ERR_CAST(bdev);
......
......@@ -412,7 +412,7 @@ SYSCALL_DEFINE5(fsetxattr, int, fd, const char __user *, name,
if (!f.file)
return error;
dentry = f.file->f_path.dentry;
audit_inode(NULL, dentry);
audit_inode(NULL, dentry, 0);
error = mnt_want_write_file(f.file);
if (!error) {
error = setxattr(dentry, name, value, size, flags);
......@@ -507,7 +507,7 @@ SYSCALL_DEFINE4(fgetxattr, int, fd, const char __user *, name,
if (!f.file)
return error;
audit_inode(NULL, f.file->f_path.dentry);
audit_inode(NULL, f.file->f_path.dentry, 0);
error = getxattr(f.file->f_path.dentry, name, value, size);
fdput(f);
return error;
......@@ -586,7 +586,7 @@ SYSCALL_DEFINE3(flistxattr, int, fd, char __user *, list, size_t, size)
if (!f.file)
return error;
audit_inode(NULL, f.file->f_path.dentry);
audit_inode(NULL, f.file->f_path.dentry, 0);
error = listxattr(f.file->f_path.dentry, list, size);
fdput(f);
return error;
......@@ -655,7 +655,7 @@ SYSCALL_DEFINE2(fremovexattr, int, fd, const char __user *, name)
if (!f.file)
return error;
dentry = f.file->f_path.dentry;
audit_inode(NULL, dentry);
audit_inode(NULL, dentry, 0);
error = mnt_want_write_file(f.file);
if (!error) {
error = removexattr(dentry, name);
......
......@@ -452,6 +452,16 @@ struct audit_field {
extern int __init audit_register_class(int class, unsigned *list);
extern int audit_classify_syscall(int abi, unsigned syscall);
extern int audit_classify_arch(int arch);
/* audit_names->type values */
#define AUDIT_TYPE_UNKNOWN 0 /* we don't know yet */
#define AUDIT_TYPE_NORMAL 1 /* a "normal" audit record */
#define AUDIT_TYPE_PARENT 2 /* a parent audit record */
#define AUDIT_TYPE_CHILD_DELETE 3 /* a child being deleted */
#define AUDIT_TYPE_CHILD_CREATE 4 /* a child being created */
struct filename;
#ifdef CONFIG_AUDITSYSCALL
/* These are defined in auditsc.c */
/* Public API */
......@@ -461,11 +471,14 @@ extern void __audit_syscall_entry(int arch,
int major, unsigned long a0, unsigned long a1,
unsigned long a2, unsigned long a3);
extern void __audit_syscall_exit(int ret_success, long ret_value);
extern void __audit_getname(const char *name);
extern void audit_putname(const char *name);
extern void __audit_inode(const char *name, const struct dentry *dentry);
extern void __audit_inode_child(const struct dentry *dentry,
const struct inode *parent);
extern struct filename *__audit_reusename(const __user char *uptr);
extern void __audit_getname(struct filename *name);
extern void audit_putname(struct filename *name);
extern void __audit_inode(struct filename *name, const struct dentry *dentry,
unsigned int parent);
extern void __audit_inode_child(const struct inode *parent,
const struct dentry *dentry,
const unsigned char type);
extern void __audit_seccomp(unsigned long syscall, long signr, int code);
extern void __audit_ptrace(struct task_struct *t);
......@@ -495,19 +508,27 @@ static inline void audit_syscall_exit(void *pt_regs)
__audit_syscall_exit(success, return_code);
}
}
static inline void audit_getname(const char *name)
static inline struct filename *audit_reusename(const __user char *name)
{
if (unlikely(!audit_dummy_context()))
return __audit_reusename(name);
return NULL;
}
static inline void audit_getname(struct filename *name)
{
if (unlikely(!audit_dummy_context()))
__audit_getname(name);
}
static inline void audit_inode(const char *name, const struct dentry *dentry) {
static inline void audit_inode(struct filename *name, const struct dentry *dentry,
unsigned int parent) {
if (unlikely(!audit_dummy_context()))
__audit_inode(name, dentry);
__audit_inode(name, dentry, parent);
}
static inline void audit_inode_child(const struct dentry *dentry,
const struct inode *parent) {
static inline void audit_inode_child(const struct inode *parent,
const struct dentry *dentry,
const unsigned char type) {
if (unlikely(!audit_dummy_context()))
__audit_inode_child(dentry, parent);
__audit_inode_child(parent, dentry, type);
}
void audit_core_dumps(long signr);
......@@ -651,19 +672,29 @@ static inline int audit_dummy_context(void)
{
return 1;
}
static inline void audit_getname(const char *name)
static inline struct filename *audit_reusename(const __user char *name)
{
return NULL;
}
static inline void audit_getname(struct filename *name)
{ }
static inline void audit_putname(const char *name)
static inline void audit_putname(struct filename *name)
{ }
static inline void __audit_inode(const char *name, const struct dentry *dentry)
static inline void __audit_inode(struct filename *name,
const struct dentry *dentry,
unsigned int parent)
{ }
static inline void __audit_inode_child(const struct dentry *dentry,
const struct inode *parent)
static inline void __audit_inode_child(const struct inode *parent,
const struct dentry *dentry,
const unsigned char type)
{ }
static inline void audit_inode(const char *name, const struct dentry *dentry)
static inline void audit_inode(struct filename *name,
const struct dentry *dentry,
unsigned int parent)
{ }
static inline void audit_inode_child(const struct dentry *dentry,
const struct inode *parent)
static inline void audit_inode_child(const struct inode *parent,
const struct dentry *dentry,
const unsigned char type)
{ }
static inline void audit_core_dumps(long signr)
{ }
......
......@@ -2196,6 +2196,13 @@ static inline int break_lease(struct inode *inode, unsigned int mode)
#endif /* CONFIG_FILE_LOCKING */
/* fs/open.c */
struct audit_names;
struct filename {
const char *name; /* pointer to actual string */
const __user char *uptr; /* original userland pointer */
struct audit_names *aname;
bool separate; /* should "name" be freed? */
};
extern int do_truncate(struct dentry *, loff_t start, unsigned int time_attrs,
struct file *filp);
......@@ -2203,12 +2210,15 @@ extern int do_fallocate(struct file *file, int mode, loff_t offset,
loff_t len);
extern long do_sys_open(int dfd, const char __user *filename, int flags,
umode_t mode);
extern struct file *file_open_name(struct filename *, int, umode_t);
extern struct file *filp_open(const char *, int, umode_t);
extern struct file *file_open_root(struct dentry *, struct vfsmount *,
const char *, int);
extern struct file * dentry_open(const struct path *, int, const struct cred *);
extern int filp_close(struct file *, fl_owner_t id);
extern char * getname(const char __user *);
extern struct filename *getname(const char __user *);
enum {
FILE_CREATED = 1,
FILE_OPENED = 2
......@@ -2228,13 +2238,14 @@ extern void __init vfs_caches_init(unsigned long);
extern struct kmem_cache *names_cachep;
#define __getname_gfp(gfp) kmem_cache_alloc(names_cachep, (gfp))
#define __getname() __getname_gfp(GFP_KERNEL)
extern void final_putname(struct filename *name);
#define __getname() kmem_cache_alloc(names_cachep, GFP_KERNEL)
#define __putname(name) kmem_cache_free(names_cachep, (void *)(name))
#ifndef CONFIG_AUDITSYSCALL
#define putname(name) __putname(name)
#define putname(name) final_putname(name)
#else
extern void putname(const char *name);
extern void putname(struct filename *name);
#endif
#ifdef CONFIG_BLOCK
......
......@@ -109,7 +109,7 @@ static inline void fsnotify_move(struct inode *old_dir, struct inode *new_dir,
if (source)
fsnotify(source, FS_MOVE_SELF, moved->d_inode, FSNOTIFY_EVENT_INODE, NULL, 0);
audit_inode_child(moved, new_dir);
audit_inode_child(new_dir, moved, AUDIT_TYPE_CHILD_CREATE);
}
/*
......@@ -155,7 +155,7 @@ static inline void fsnotify_inoderemove(struct inode *inode)
*/
static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
{
audit_inode_child(dentry, inode);
audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
fsnotify(inode, FS_CREATE, dentry->d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
}
......@@ -168,7 +168,7 @@ static inline void fsnotify_create(struct inode *inode, struct dentry *dentry)
static inline void fsnotify_link(struct inode *dir, struct inode *inode, struct dentry *new_dentry)
{
fsnotify_link_count(inode);
audit_inode_child(new_dentry, dir);
audit_inode_child(dir, new_dentry, AUDIT_TYPE_CHILD_CREATE);
fsnotify(dir, FS_CREATE, inode, FSNOTIFY_EVENT_INODE, new_dentry->d_name.name, 0);
}
......@@ -181,7 +181,7 @@ static inline void fsnotify_mkdir(struct inode *inode, struct dentry *dentry)
__u32 mask = (FS_CREATE | FS_ISDIR);
struct inode *d_inode = dentry->d_inode;
audit_inode_child(dentry, inode);
audit_inode_child(inode, dentry, AUDIT_TYPE_CHILD_CREATE);
fsnotify(inode, mask, d_inode, FSNOTIFY_EVENT_INODE, dentry->d_name.name, 0);
}
......
......@@ -353,8 +353,9 @@ static int __init do_mount_root(char *name, char *fs, int flags, void *data)
void __init mount_block_root(char *name, int flags)
{
char *fs_names = __getname_gfp(GFP_KERNEL
| __GFP_NOTRACK_FALSE_POSITIVE);
struct page *page = alloc_page(GFP_KERNEL |
__GFP_NOTRACK_FALSE_POSITIVE);
char *fs_names = page_address(page);
char *p;
#ifdef CONFIG_BLOCK
char b[BDEVNAME_SIZE];
......@@ -406,7 +407,7 @@ void __init mount_block_root(char *name, int flags)
#endif
panic("VFS: Unable to mount root fs on %s", b);
out:
putname(fs_names);
put_page(page);
}
#ifdef CONFIG_ROOT_NFS
......
......@@ -772,7 +772,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
{
struct path path;
struct file *filp;
char *name;
struct filename *name;
struct mq_attr attr;
int fd, error;
struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
......@@ -795,7 +795,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
ro = mnt_want_write(mnt); /* we'll drop it in any case */
error = 0;
mutex_lock(&root->d_inode->i_mutex);
path.dentry = lookup_one_len(name, root, strlen(name));
path.dentry = lookup_one_len(name->name, root, strlen(name->name));
if (IS_ERR(path.dentry)) {
error = PTR_ERR(path.dentry);
goto out_putfd;
......@@ -804,7 +804,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
if (oflag & O_CREAT) {
if (path.dentry->d_inode) { /* entry already exists */
audit_inode(name, path.dentry);
audit_inode(name, path.dentry, 0);
if (oflag & O_EXCL) {
error = -EEXIST;
goto out;
......@@ -824,7 +824,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
error = -ENOENT;
goto out;
}
audit_inode(name, path.dentry);
audit_inode(name, path.dentry, 0);
filp = do_open(&path, oflag);
}
......@@ -849,7 +849,7 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
{
int err;
char *name;
struct filename *name;
struct dentry *dentry;
struct inode *inode = NULL;
struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
......@@ -863,7 +863,8 @@ SYSCALL_DEFINE1(mq_unlink, const char __user *, u_name)
if (err)
goto out_name;
mutex_lock_nested(&mnt->mnt_root->d_inode->i_mutex, I_MUTEX_PARENT);
dentry = lookup_one_len(name, mnt->mnt_root, strlen(name));
dentry = lookup_one_len(name->name, mnt->mnt_root,
strlen(name->name));
if (IS_ERR(dentry)) {
err = PTR_ERR(dentry);
goto out_unlock;
......@@ -978,7 +979,7 @@ SYSCALL_DEFINE5(mq_timedsend, mqd_t, mqdes, const char __user *, u_msg_ptr,
goto out_fput;
}
info = MQUEUE_I(inode);
audit_inode(NULL, f.file->f_path.dentry);
audit_inode(NULL, f.file->f_path.dentry, 0);
if (unlikely(!(f.file->f_mode & FMODE_WRITE))) {
ret = -EBADF;
......@@ -1094,7 +1095,7 @@ SYSCALL_DEFINE5(mq_timedreceive, mqd_t, mqdes, char __user *, u_msg_ptr,
goto out_fput;
}
info = MQUEUE_I(inode);
audit_inode(NULL, f.file->f_path.dentry);
audit_inode(NULL, f.file->f_path.dentry, 0);
if (unlikely(!(f.file->f_mode & FMODE_READ))) {
ret = -EBADF;
......
......@@ -193,7 +193,7 @@ static void acct_file_reopen(struct bsd_acct_struct *acct, struct file *file,
}
}
static int acct_on(char *name)
static int acct_on(struct filename *pathname)
{
struct file *file;
struct vfsmount *mnt;
......@@ -201,7 +201,7 @@ static int acct_on(char *name)
struct bsd_acct_struct *acct = NULL;
/* Difference from BSD - they don't do O_APPEND */
file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0);
file = file_open_name(pathname, O_WRONLY|O_APPEND|O_LARGEFILE, 0);
if (IS_ERR(file))
return PTR_ERR(file);
......@@ -260,7 +260,7 @@ SYSCALL_DEFINE1(acct, const char __user *, name)
return -EPERM;
if (name) {
char *tmp = getname(name);
struct filename *tmp = getname(name);
if (IS_ERR(tmp))
return (PTR_ERR(tmp));
error = acct_on(tmp);
......
......@@ -74,12 +74,15 @@ static inline int audit_hash_ino(u32 ino)
return (ino & (AUDIT_INODE_BUCKETS-1));
}
/* Indicates that audit should log the full pathname. */
#define AUDIT_NAME_FULL -1
extern int audit_match_class(int class, unsigned syscall);
extern int audit_comparator(const u32 left, const u32 op, const u32 right);
extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right);
extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right);
extern int audit_compare_dname_path(const char *dname, const char *path,
int *dirlen);
extern int parent_len(const char *path);
extern int audit_compare_dname_path(const char *dname, const char *path, int plen);
extern struct sk_buff * audit_make_reply(int pid, int seq, int type,
int done, int multi,
const void *payload, int size);
......
......@@ -265,7 +265,8 @@ static void audit_update_watch(struct audit_parent *parent,
/* Run all of the watches on this parent looking for the one that
* matches the given dname */
list_for_each_entry_safe(owatch, nextw, &parent->watches, wlist) {
if (audit_compare_dname_path(dname, owatch->path, NULL))
if (audit_compare_dname_path(dname, owatch->path,
AUDIT_NAME_FULL))
continue;
/* If the update involves invalidating rules, do the inode-based
......
......@@ -1298,41 +1298,60 @@ int audit_gid_comparator(kgid_t left, u32 op, kgid_t right)
}
}
/* Compare given dentry name with last component in given path,
* return of 0 indicates a match. */
int audit_compare_dname_path(const char *dname, const char *path,
int *dirlen)
/**
* parent_len - find the length of the parent portion of a pathname
* @path: pathname of which to determine length
*/
int parent_len(const char *path)
{
int dlen, plen;
int plen;
const char *p;
if (!dname || !path)
return 1;
dlen = strlen(dname);
plen = strlen(path);
if (plen < dlen)
return 1;
if (plen == 0)
return plen;
/* disregard trailing slashes */
p = path + plen - 1;
while ((*p == '/') && (p > path))
p--;
/* find last path component */
p = p - dlen + 1;
if (p < path)
/* walk backward until we find the next slash or hit beginning */
while ((*p != '/') && (p > path))
p--;
/* did we find a slash? Then increment to include it in path */
if (*p == '/')
p++;
return p - path;
}
/**
* audit_compare_dname_path - compare given dentry name with last component in
* given path. Return of 0 indicates a match.
* @dname: dentry name that we're comparing
* @path: full pathname that we're comparing
* @parentlen: length of the parent if known. Passing in AUDIT_NAME_FULL
* here indicates that we must compute this value.
*/
int audit_compare_dname_path(const char *dname, const char *path, int parentlen)
{
int dlen, pathlen;
const char *p;
dlen = strlen(dname);
pathlen = strlen(path);
if (pathlen < dlen)
return 1;
else if (p > path) {
if (*--p != '/')
return 1;
else
p++;
}
/* return length of path's directory component */
if (dirlen)
*dirlen = p - path;
parentlen = parentlen == AUDIT_NAME_FULL ? parent_len(path) : parentlen;
if (pathlen - parentlen != dlen)
return 1;
p = path + parentlen;
return strncmp(p, dname, dlen);
}
......
This diff is collapsed.
......@@ -1483,7 +1483,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
struct file *swap_file, *victim;
struct address_space *mapping;
struct inode *inode;
char *pathname;
struct filename *pathname;
int oom_score_adj;
int i, type, prev;
int err;
......@@ -1498,8 +1498,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
if (IS_ERR(pathname))
goto out;
victim = filp_open(pathname, O_RDWR|O_LARGEFILE, 0);
putname(pathname);
victim = file_open_name(pathname, O_RDWR|O_LARGEFILE, 0);
err = PTR_ERR(victim);
if (IS_ERR(victim))
goto out;
......@@ -1936,7 +1935,7 @@ static int setup_swap_map_and_extents(struct swap_info_struct *p,
SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
{
struct swap_info_struct *p;
char *name;
struct filename *name;
struct file *swap_file = NULL;
struct address_space *mapping;
int i;
......@@ -1967,7 +1966,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
name = NULL;
goto bad_swap;
}
swap_file = filp_open(name, O_RDWR|O_LARGEFILE, 0);
swap_file = file_open_name(name, O_RDWR|O_LARGEFILE, 0);
if (IS_ERR(swap_file)) {
error = PTR_ERR(swap_file);
swap_file = NULL;
......@@ -2053,7 +2052,7 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
printk(KERN_INFO "Adding %uk swap on %s. "
"Priority:%d extents:%d across:%lluk %s%s%s\n",
p->pages<<(PAGE_SHIFT-10), name, p->prio,
p->pages<<(PAGE_SHIFT-10), name->name, p->prio,
nr_extents, (unsigned long long)span<<(PAGE_SHIFT-10),
(p->flags & SWP_SOLIDSTATE) ? "SS" : "",
(p->flags & SWP_DISCARDABLE) ? "D" : "",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment