diff options
Diffstat (limited to 'mm')
| -rw-r--r-- | mm/cleancache.c | 6 | ||||
| -rw-r--r-- | mm/filemap.c | 69 | ||||
| -rw-r--r-- | mm/filemap_xip.c | 4 | ||||
| -rw-r--r-- | mm/internal.h | 4 | ||||
| -rw-r--r-- | mm/mmap.c | 54 | ||||
| -rw-r--r-- | mm/mremap.c | 26 | ||||
| -rw-r--r-- | mm/nommu.c | 35 | ||||
| -rw-r--r-- | mm/shmem.c | 6 | ||||
| -rw-r--r-- | mm/util.c | 30 | 
9 files changed, 58 insertions, 176 deletions
diff --git a/mm/cleancache.c b/mm/cleancache.c index 5646c740f61..32e6f4136fa 100644 --- a/mm/cleancache.c +++ b/mm/cleancache.c @@ -80,7 +80,7 @@ EXPORT_SYMBOL(__cleancache_init_shared_fs);  static int cleancache_get_key(struct inode *inode,  			      struct cleancache_filekey *key)  { -	int (*fhfn)(struct dentry *, __u32 *fh, int *, int); +	int (*fhfn)(struct inode *, __u32 *fh, int *, struct inode *);  	int len = 0, maxlen = CLEANCACHE_KEY_MAX;  	struct super_block *sb = inode->i_sb; @@ -88,9 +88,7 @@ static int cleancache_get_key(struct inode *inode,  	if (sb->s_export_op != NULL) {  		fhfn = sb->s_export_op->encode_fh;  		if  (fhfn) { -			struct dentry d; -			d.d_inode = inode; -			len = (*fhfn)(&d, &key->u.fh[0], &maxlen, 0); +			len = (*fhfn)(inode, &key->u.fh[0], &maxlen, NULL);  			if (len <= 0 || len == 255)  				return -1;  			if (maxlen > CLEANCACHE_KEY_MAX) diff --git a/mm/filemap.c b/mm/filemap.c index 64b48f934b8..a4a5260b027 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1899,71 +1899,6 @@ struct page *read_cache_page(struct address_space *mapping,  }  EXPORT_SYMBOL(read_cache_page); -/* - * The logic we want is - * - *	if suid or (sgid and xgrp) - *		remove privs - */ -int should_remove_suid(struct dentry *dentry) -{ -	umode_t mode = dentry->d_inode->i_mode; -	int kill = 0; - -	/* suid always must be killed */ -	if (unlikely(mode & S_ISUID)) -		kill = ATTR_KILL_SUID; - -	/* -	 * sgid without any exec bits is just a mandatory locking mark; leave -	 * it alone.  If some exec bits are set, it's a real sgid; kill it. -	 */ -	if (unlikely((mode & S_ISGID) && (mode & S_IXGRP))) -		kill |= ATTR_KILL_SGID; - -	if (unlikely(kill && !capable(CAP_FSETID) && S_ISREG(mode))) -		return kill; - -	return 0; -} -EXPORT_SYMBOL(should_remove_suid); - -static int __remove_suid(struct dentry *dentry, int kill) -{ -	struct iattr newattrs; - -	newattrs.ia_valid = ATTR_FORCE | kill; -	return notify_change(dentry, &newattrs); -} - -int file_remove_suid(struct file *file) -{ -	struct dentry *dentry = file->f_path.dentry; -	struct inode *inode = dentry->d_inode; -	int killsuid; -	int killpriv; -	int error = 0; - -	/* Fast path for nothing security related */ -	if (IS_NOSEC(inode)) -		return 0; - -	killsuid = should_remove_suid(dentry); -	killpriv = security_inode_need_killpriv(dentry); - -	if (killpriv < 0) -		return killpriv; -	if (killpriv) -		error = security_inode_killpriv(dentry); -	if (!error && killsuid) -		error = __remove_suid(dentry, killsuid); -	if (!error && (inode->i_sb->s_flags & MS_NOSEC)) -		inode->i_flags |= S_NOSEC; - -	return error; -} -EXPORT_SYMBOL(file_remove_suid); -  static size_t __iovec_copy_from_user_inatomic(char *vaddr,  			const struct iovec *iov, size_t base, size_t bytes)  { @@ -2489,7 +2424,9 @@ ssize_t __generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,  	if (err)  		goto out; -	file_update_time(file); +	err = file_update_time(file); +	if (err) +		goto out;  	/* coalesce the iovecs and go direct-to-BIO for O_DIRECT */  	if (unlikely(file->f_flags & O_DIRECT)) { diff --git a/mm/filemap_xip.c b/mm/filemap_xip.c index a4eb3113222..213ca1f5340 100644 --- a/mm/filemap_xip.c +++ b/mm/filemap_xip.c @@ -426,7 +426,9 @@ xip_file_write(struct file *filp, const char __user *buf, size_t len,  	if (ret)  		goto out_backing; -	file_update_time(filp); +	ret = file_update_time(filp); +	if (ret) +		goto out_backing;  	ret = __xip_file_write (filp, buf, count, pos, ppos); diff --git a/mm/internal.h b/mm/internal.h index 4194ab9dc19..5cbb7819004 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -350,3 +350,7 @@ extern u64 hwpoison_filter_flags_mask;  extern u64 hwpoison_filter_flags_value;  extern u64 hwpoison_filter_memcg;  extern u32 hwpoison_filter_enable; + +extern unsigned long vm_mmap_pgoff(struct file *, unsigned long, +        unsigned long, unsigned long, +        unsigned long, unsigned long); diff --git a/mm/mmap.c b/mm/mmap.c index 4a9c2a391e2..3edfcdfa42d 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -971,15 +971,13 @@ static inline unsigned long round_hint_to_min(unsigned long hint)   * The caller must hold down_write(¤t->mm->mmap_sem).   */ -static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, +unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,  			unsigned long len, unsigned long prot,  			unsigned long flags, unsigned long pgoff)  {  	struct mm_struct * mm = current->mm;  	struct inode *inode;  	vm_flags_t vm_flags; -	int error; -	unsigned long reqprot = prot;  	/*  	 * Does the application expect PROT_READ to imply PROT_EXEC? @@ -1101,39 +1099,9 @@ static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,  		}  	} -	error = security_file_mmap(file, reqprot, prot, flags, addr, 0); -	if (error) -		return error; -  	return mmap_region(file, addr, len, flags, vm_flags, pgoff);  } -unsigned long do_mmap(struct file *file, unsigned long addr, -	unsigned long len, unsigned long prot, -	unsigned long flag, unsigned long offset) -{ -	if (unlikely(offset + PAGE_ALIGN(len) < offset)) -		return -EINVAL; -	if (unlikely(offset & ~PAGE_MASK)) -		return -EINVAL; -	return do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); -} -EXPORT_SYMBOL(do_mmap); - -unsigned long vm_mmap(struct file *file, unsigned long addr, -	unsigned long len, unsigned long prot, -	unsigned long flag, unsigned long offset) -{ -	unsigned long ret; -	struct mm_struct *mm = current->mm; - -	down_write(&mm->mmap_sem); -	ret = do_mmap(file, addr, len, prot, flag, offset); -	up_write(&mm->mmap_sem); -	return ret; -} -EXPORT_SYMBOL(vm_mmap); -  SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,  		unsigned long, prot, unsigned long, flags,  		unsigned long, fd, unsigned long, pgoff) @@ -1165,10 +1133,7 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,  	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); -	down_write(¤t->mm->mmap_sem); -	retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); -	up_write(¤t->mm->mmap_sem); - +	retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);  	if (file)  		fput(file);  out: @@ -1629,7 +1594,9 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,  	if (addr & ~PAGE_MASK)  		return -EINVAL; -	return arch_rebalance_pgtables(addr, len); +	addr = arch_rebalance_pgtables(addr, len); +	error = security_mmap_addr(addr); +	return error ? error : addr;  }  EXPORT_SYMBOL(get_unmapped_area); @@ -1819,7 +1786,7 @@ int expand_downwards(struct vm_area_struct *vma,  		return -ENOMEM;  	address &= PAGE_MASK; -	error = security_file_mmap(NULL, 0, 0, 0, address, 1); +	error = security_mmap_addr(address);  	if (error)  		return error; @@ -2159,7 +2126,6 @@ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)  	return 0;  } -EXPORT_SYMBOL(do_munmap);  int vm_munmap(unsigned long start, size_t len)  { @@ -2207,10 +2173,6 @@ static unsigned long do_brk(unsigned long addr, unsigned long len)  	if (!len)  		return addr; -	error = security_file_mmap(NULL, 0, 0, 0, addr, 1); -	if (error) -		return error; -  	flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;  	error = get_unmapped_area(NULL, addr, len, 0, MAP_FIXED); @@ -2563,10 +2525,6 @@ int install_special_mapping(struct mm_struct *mm,  	vma->vm_ops = &special_mapping_vmops;  	vma->vm_private_data = pages; -	ret = security_file_mmap(NULL, 0, 0, 0, vma->vm_start, 1); -	if (ret) -		goto out; -  	ret = insert_vm_struct(mm, vma);  	if (ret)  		goto out; diff --git a/mm/mremap.c b/mm/mremap.c index db8d983b5a7..21fed202dda 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -371,10 +371,6 @@ static unsigned long mremap_to(unsigned long addr,  	if ((addr <= new_addr) && (addr+old_len) > new_addr)  		goto out; -	ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1); -	if (ret) -		goto out; -  	ret = do_munmap(mm, new_addr, new_len);  	if (ret)  		goto out; @@ -432,15 +428,17 @@ static int vma_expandable(struct vm_area_struct *vma, unsigned long delta)   * MREMAP_FIXED option added 5-Dec-1999 by Benjamin LaHaise   * This option implies MREMAP_MAYMOVE.   */ -unsigned long do_mremap(unsigned long addr, -	unsigned long old_len, unsigned long new_len, -	unsigned long flags, unsigned long new_addr) +SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len, +		unsigned long, new_len, unsigned long, flags, +		unsigned long, new_addr)  {  	struct mm_struct *mm = current->mm;  	struct vm_area_struct *vma;  	unsigned long ret = -EINVAL;  	unsigned long charged = 0; +	down_write(¤t->mm->mmap_sem); +  	if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE))  		goto out; @@ -530,25 +528,11 @@ unsigned long do_mremap(unsigned long addr,  			goto out;  		} -		ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1); -		if (ret) -			goto out;  		ret = move_vma(vma, addr, old_len, new_len, new_addr);  	}  out:  	if (ret & ~PAGE_MASK)  		vm_unacct_memory(charged); -	return ret; -} - -SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len, -		unsigned long, new_len, unsigned long, flags, -		unsigned long, new_addr) -{ -	unsigned long ret; - -	down_write(¤t->mm->mmap_sem); -	ret = do_mremap(addr, old_len, new_len, flags, new_addr);  	up_write(¤t->mm->mmap_sem);  	return ret;  } diff --git a/mm/nommu.c b/mm/nommu.c index bb8f4f004a8..c4acfbc0997 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -889,7 +889,6 @@ static int validate_mmap_request(struct file *file,  				 unsigned long *_capabilities)  {  	unsigned long capabilities, rlen; -	unsigned long reqprot = prot;  	int ret;  	/* do the simple checks first */ @@ -1047,7 +1046,7 @@ static int validate_mmap_request(struct file *file,  	}  	/* allow the security API to have its say */ -	ret = security_file_mmap(file, reqprot, prot, flags, addr, 0); +	ret = security_mmap_addr(addr);  	if (ret < 0)  		return ret; @@ -1233,7 +1232,7 @@ enomem:  /*   * handle mapping creation for uClinux   */ -static unsigned long do_mmap_pgoff(struct file *file, +unsigned long do_mmap_pgoff(struct file *file,  			    unsigned long addr,  			    unsigned long len,  			    unsigned long prot, @@ -1471,32 +1470,6 @@ error_getting_region:  	return -ENOMEM;  } -unsigned long do_mmap(struct file *file, unsigned long addr, -	unsigned long len, unsigned long prot, -	unsigned long flag, unsigned long offset) -{ -	if (unlikely(offset + PAGE_ALIGN(len) < offset)) -		return -EINVAL; -	if (unlikely(offset & ~PAGE_MASK)) -		return -EINVAL; -	return do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); -} -EXPORT_SYMBOL(do_mmap); - -unsigned long vm_mmap(struct file *file, unsigned long addr, -	unsigned long len, unsigned long prot, -	unsigned long flag, unsigned long offset) -{ -	unsigned long ret; -	struct mm_struct *mm = current->mm; - -	down_write(&mm->mmap_sem); -	ret = do_mmap(file, addr, len, prot, flag, offset); -	up_write(&mm->mmap_sem); -	return ret; -} -EXPORT_SYMBOL(vm_mmap); -  SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,  		unsigned long, prot, unsigned long, flags,  		unsigned long, fd, unsigned long, pgoff) @@ -1513,9 +1486,7 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,  	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); -	down_write(¤t->mm->mmap_sem); -	retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); -	up_write(¤t->mm->mmap_sem); +	ret = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);  	if (file)  		fput(file); diff --git a/mm/shmem.c b/mm/shmem.c index d576b84d913..585bd220a21 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -2439,11 +2439,9 @@ static struct dentry *shmem_fh_to_dentry(struct super_block *sb,  	return dentry;  } -static int shmem_encode_fh(struct dentry *dentry, __u32 *fh, int *len, -				int connectable) +static int shmem_encode_fh(struct inode *inode, __u32 *fh, int *len, +				struct inode *parent)  { -	struct inode *inode = dentry->d_inode; -  	if (*len < 3) {  		*len = 3;  		return 255; diff --git a/mm/util.c b/mm/util.c index ae962b31de8..8c7265afa29 100644 --- a/mm/util.c +++ b/mm/util.c @@ -4,6 +4,7 @@  #include <linux/export.h>  #include <linux/err.h>  #include <linux/sched.h> +#include <linux/security.h>  #include <asm/uaccess.h>  #include "internal.h" @@ -341,6 +342,35 @@ int __attribute__((weak)) get_user_pages_fast(unsigned long start,  }  EXPORT_SYMBOL_GPL(get_user_pages_fast); +unsigned long vm_mmap_pgoff(struct file *file, unsigned long addr, +	unsigned long len, unsigned long prot, +	unsigned long flag, unsigned long pgoff) +{ +	unsigned long ret; +	struct mm_struct *mm = current->mm; + +	ret = security_mmap_file(file, prot, flag); +	if (!ret) { +		down_write(&mm->mmap_sem); +		ret = do_mmap_pgoff(file, addr, len, prot, flag, pgoff); +		up_write(&mm->mmap_sem); +	} +	return ret; +} + +unsigned long vm_mmap(struct file *file, unsigned long addr, +	unsigned long len, unsigned long prot, +	unsigned long flag, unsigned long offset) +{ +	if (unlikely(offset + PAGE_ALIGN(len) < offset)) +		return -EINVAL; +	if (unlikely(offset & ~PAGE_MASK)) +		return -EINVAL; + +	return vm_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); +} +EXPORT_SYMBOL(vm_mmap); +  /* Tracepoints definitions. */  EXPORT_TRACEPOINT_SYMBOL(kmalloc);  EXPORT_TRACEPOINT_SYMBOL(kmem_cache_alloc);  |