take security_mmap_file() outside of ->mmap_sem
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
		
							parent
							
								
									e5467859f7
								
							
						
					
					
						commit
						8b3ec6814c
					
				| @ -1745,8 +1745,8 @@ int security_file_permission(struct file *file, int mask); | ||||
| int security_file_alloc(struct file *file); | ||||
| void security_file_free(struct file *file); | ||||
| int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg); | ||||
| int security_mmap_file(struct file *file, unsigned long reqprot, | ||||
| 			unsigned long prot, unsigned long flags); | ||||
| int security_mmap_file(struct file *file, unsigned long prot, | ||||
| 			unsigned long flags); | ||||
| int security_mmap_addr(unsigned long addr); | ||||
| int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, | ||||
| 			   unsigned long prot); | ||||
| @ -2183,8 +2183,7 @@ static inline int security_file_ioctl(struct file *file, unsigned int cmd, | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static inline int security_mmap_file(struct file *file, unsigned long reqprot, | ||||
| 				     unsigned long prot, | ||||
| static inline int security_mmap_file(struct file *file, unsigned long prot, | ||||
| 				     unsigned long flags) | ||||
| { | ||||
| 	return 0; | ||||
|  | ||||
| @ -1036,6 +1036,10 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) | ||||
| 	sfd->file = shp->shm_file; | ||||
| 	sfd->vm_ops = NULL; | ||||
| 
 | ||||
| 	err = security_mmap_file(file, prot, flags); | ||||
| 	if (err) | ||||
| 		goto out_fput; | ||||
| 
 | ||||
| 	down_write(¤t->mm->mmap_sem); | ||||
| 	if (addr && !(shmflg & SHM_REMAP)) { | ||||
| 		err = -EINVAL; | ||||
| @ -1058,6 +1062,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) | ||||
| invalid: | ||||
| 	up_write(¤t->mm->mmap_sem); | ||||
| 
 | ||||
| out_fput: | ||||
| 	fput(file); | ||||
| 
 | ||||
| out_nattch: | ||||
|  | ||||
							
								
								
									
										23
									
								
								mm/mmap.c
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								mm/mmap.c
									
									
									
									
									
								
							| @ -979,7 +979,6 @@ static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, | ||||
| 	struct inode *inode; | ||||
| 	vm_flags_t vm_flags; | ||||
| 	int error; | ||||
| 	unsigned long reqprot = prot; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Does the application expect PROT_READ to imply PROT_EXEC? | ||||
| @ -1105,10 +1104,6 @@ static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, | ||||
| 	if (error) | ||||
| 		return error; | ||||
| 
 | ||||
| 	error = security_mmap_file(file, reqprot, prot, flags); | ||||
| 	if (error) | ||||
| 		return error; | ||||
| 
 | ||||
| 	return mmap_region(file, addr, len, flags, vm_flags, pgoff); | ||||
| } | ||||
| 
 | ||||
| @ -1130,9 +1125,12 @@ unsigned long vm_mmap(struct file *file, unsigned long addr, | ||||
| 	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); | ||||
| 	ret = security_mmap_file(file, prot, flag); | ||||
| 	if (!ret) { | ||||
| 		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); | ||||
| @ -1168,9 +1166,12 @@ 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 = security_mmap_file(file, prot, flags); | ||||
| 	if (!retval) { | ||||
| 		down_write(¤t->mm->mmap_sem); | ||||
| 		retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||||
| 		up_write(¤t->mm->mmap_sem); | ||||
| 	} | ||||
| 
 | ||||
| 	if (file) | ||||
| 		fput(file); | ||||
|  | ||||
							
								
								
									
										22
									
								
								mm/nommu.c
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								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 */ | ||||
| @ -1048,9 +1047,6 @@ static int validate_mmap_request(struct file *file, | ||||
| 
 | ||||
| 	/* allow the security API to have its say */ | ||||
| 	ret = security_mmap_addr(addr); | ||||
| 	if (ret < 0) | ||||
| 		return ret; | ||||
| 	ret = security_mmap_file(file, reqprot, prot, flags); | ||||
| 	if (ret < 0) | ||||
| 		return ret; | ||||
| 
 | ||||
| @ -1492,9 +1488,12 @@ unsigned long vm_mmap(struct file *file, unsigned long addr, | ||||
| 	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); | ||||
| 	ret = security_mmap_file(file, prot, flag); | ||||
| 	if (!ret) { | ||||
| 		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); | ||||
| @ -1515,9 +1514,12 @@ 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 = security_mmap_file(file, prot, flags); | ||||
| 	if (!ret) { | ||||
| 		down_write(¤t->mm->mmap_sem); | ||||
| 		retval = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); | ||||
| 		up_write(¤t->mm->mmap_sem); | ||||
| 	} | ||||
| 
 | ||||
| 	if (file) | ||||
| 		fput(file); | ||||
|  | ||||
| @ -20,6 +20,9 @@ | ||||
| #include <linux/ima.h> | ||||
| #include <linux/evm.h> | ||||
| #include <linux/fsnotify.h> | ||||
| #include <linux/mman.h> | ||||
| #include <linux/mount.h> | ||||
| #include <linux/personality.h> | ||||
| #include <net/flow.h> | ||||
| 
 | ||||
| #define MAX_LSM_EVM_XATTR	2 | ||||
| @ -657,11 +660,35 @@ int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||||
| 	return security_ops->file_ioctl(file, cmd, arg); | ||||
| } | ||||
| 
 | ||||
| int security_mmap_file(struct file *file, unsigned long reqprot, | ||||
| 			unsigned long prot, unsigned long flags) | ||||
| int security_mmap_file(struct file *file, unsigned long prot, | ||||
| 			unsigned long flags) | ||||
| { | ||||
| 	unsigned long reqprot = prot; | ||||
| 	int ret; | ||||
| 
 | ||||
| 	/*
 | ||||
| 	 * Does the application expect PROT_READ to imply PROT_EXEC? | ||||
| 	 * | ||||
| 	 * (the exception is when the underlying filesystem is noexec | ||||
| 	 *  mounted, in which case we dont add PROT_EXEC.) | ||||
| 	 */ | ||||
| 	if (!(reqprot & PROT_READ)) | ||||
| 		goto out; | ||||
| 	if (!(current->personality & READ_IMPLIES_EXEC)) | ||||
| 		goto out; | ||||
| 	if (!file) { | ||||
| 		prot |= PROT_EXEC; | ||||
| 	} else if (!(file->f_path.mnt->mnt_flags & MNT_NOEXEC)) { | ||||
| #ifndef CONFIG_MMU | ||||
| 		unsigned long caps = 0; | ||||
| 		struct address_space *mapping = file->f_mapping; | ||||
| 		if (mapping && mapping->backing_dev_info) | ||||
| 			caps = mapping->backing_dev_info->capabilities; | ||||
| 		if (!(caps & BDI_CAP_EXEC_MAP)) | ||||
| 			goto out; | ||||
| #endif | ||||
| 		prot |= PROT_EXEC; | ||||
| 	} | ||||
| out: | ||||
| 	ret = security_ops->mmap_file(file, reqprot, prot, flags); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user