VM: add "vm_mmap()" helper function
This continues the theme started with vm_brk() and vm_munmap(): vm_mmap() does the same thing as do_mmap(), but additionally does the required VM locking. This uninlines (and rewrites it to be clearer) do_mmap(), which sadly duplicates it in mm/mmap.c and mm/nommu.c. But that way we don't have to export our internal do_mmap_pgoff() function. Some day we hopefully don't have to export do_mmap() either, if all modular users can become the simpler vm_mmap() instead. We're actually very close to that already, with the notable exception of the (broken) use in i810, and a couple of stragglers in binfmt_elf. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
					parent
					
						
							
								a46ef99d80
							
						
					
				
			
			
				commit
				
					
						6be5ceb02e
					
				
			
		
					 15 changed files with 87 additions and 97 deletions
				
			
		| 
						 | 
					@ -346,12 +346,10 @@ void single_step_once(struct pt_regs *regs)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* allocate a cache line of writable, executable memory */
 | 
							/* allocate a cache line of writable, executable memory */
 | 
				
			||||||
		down_write(¤t->mm->mmap_sem);
 | 
							buffer = (void __user *) vm_mmap(NULL, 0, 64,
 | 
				
			||||||
		buffer = (void __user *) do_mmap(NULL, 0, 64,
 | 
					 | 
				
			||||||
					  PROT_EXEC | PROT_READ | PROT_WRITE,
 | 
										  PROT_EXEC | PROT_READ | PROT_WRITE,
 | 
				
			||||||
					  MAP_PRIVATE | MAP_ANONYMOUS,
 | 
										  MAP_PRIVATE | MAP_ANONYMOUS,
 | 
				
			||||||
					  0);
 | 
										  0);
 | 
				
			||||||
		up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (IS_ERR((void __force *)buffer)) {
 | 
							if (IS_ERR((void __force *)buffer)) {
 | 
				
			||||||
			kfree(state);
 | 
								kfree(state);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -379,26 +379,22 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 | 
				
			||||||
			goto beyond_if;
 | 
								goto beyond_if;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		down_write(¤t->mm->mmap_sem);
 | 
							error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
 | 
				
			||||||
		error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
 | 
					 | 
				
			||||||
				PROT_READ | PROT_EXEC,
 | 
									PROT_READ | PROT_EXEC,
 | 
				
			||||||
				MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
 | 
									MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
 | 
				
			||||||
				MAP_EXECUTABLE | MAP_32BIT,
 | 
									MAP_EXECUTABLE | MAP_32BIT,
 | 
				
			||||||
				fd_offset);
 | 
									fd_offset);
 | 
				
			||||||
		up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (error != N_TXTADDR(ex)) {
 | 
							if (error != N_TXTADDR(ex)) {
 | 
				
			||||||
			send_sig(SIGKILL, current, 0);
 | 
								send_sig(SIGKILL, current, 0);
 | 
				
			||||||
			return error;
 | 
								return error;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		down_write(¤t->mm->mmap_sem);
 | 
							error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
 | 
				
			||||||
		error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
 | 
					 | 
				
			||||||
				PROT_READ | PROT_WRITE | PROT_EXEC,
 | 
									PROT_READ | PROT_WRITE | PROT_EXEC,
 | 
				
			||||||
				MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
 | 
									MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
 | 
				
			||||||
				MAP_EXECUTABLE | MAP_32BIT,
 | 
									MAP_EXECUTABLE | MAP_32BIT,
 | 
				
			||||||
				fd_offset + ex.a_text);
 | 
									fd_offset + ex.a_text);
 | 
				
			||||||
		up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
		if (error != N_DATADDR(ex)) {
 | 
							if (error != N_DATADDR(ex)) {
 | 
				
			||||||
			send_sig(SIGKILL, current, 0);
 | 
								send_sig(SIGKILL, current, 0);
 | 
				
			||||||
			return error;
 | 
								return error;
 | 
				
			||||||
| 
						 | 
					@ -482,12 +478,10 @@ static int load_aout_library(struct file *file)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Now use mmap to map the library into memory. */
 | 
						/* Now use mmap to map the library into memory. */
 | 
				
			||||||
	down_write(¤t->mm->mmap_sem);
 | 
						error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
 | 
				
			||||||
	error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
 | 
					 | 
				
			||||||
			PROT_READ | PROT_WRITE | PROT_EXEC,
 | 
								PROT_READ | PROT_WRITE | PROT_EXEC,
 | 
				
			||||||
			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_32BIT,
 | 
								MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_32BIT,
 | 
				
			||||||
			N_TXTOFF(ex));
 | 
								N_TXTOFF(ex));
 | 
				
			||||||
	up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
	retval = error;
 | 
						retval = error;
 | 
				
			||||||
	if (error != start_addr)
 | 
						if (error != start_addr)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6336,13 +6336,11 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
 | 
				
			||||||
		if (npages && !old.rmap) {
 | 
							if (npages && !old.rmap) {
 | 
				
			||||||
			unsigned long userspace_addr;
 | 
								unsigned long userspace_addr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			down_write(¤t->mm->mmap_sem);
 | 
								userspace_addr = vm_mmap(NULL, 0,
 | 
				
			||||||
			userspace_addr = do_mmap(NULL, 0,
 | 
					 | 
				
			||||||
						 npages * PAGE_SIZE,
 | 
											 npages * PAGE_SIZE,
 | 
				
			||||||
						 PROT_READ | PROT_WRITE,
 | 
											 PROT_READ | PROT_WRITE,
 | 
				
			||||||
						 map_flags,
 | 
											 map_flags,
 | 
				
			||||||
						 0);
 | 
											 0);
 | 
				
			||||||
			up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (IS_ERR((void *)userspace_addr))
 | 
								if (IS_ERR((void *)userspace_addr))
 | 
				
			||||||
				return PTR_ERR((void *)userspace_addr);
 | 
									return PTR_ERR((void *)userspace_addr);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1510,8 +1510,8 @@ int drm_freebufs(struct drm_device *dev, void *data,
 | 
				
			||||||
 * \param arg pointer to a drm_buf_map structure.
 | 
					 * \param arg pointer to a drm_buf_map structure.
 | 
				
			||||||
 * \return zero on success or a negative number on failure.
 | 
					 * \return zero on success or a negative number on failure.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Maps the AGP, SG or PCI buffer region with do_mmap(), and copies information
 | 
					 * Maps the AGP, SG or PCI buffer region with vm_mmap(), and copies information
 | 
				
			||||||
 * about each buffer into user space. For PCI buffers, it calls do_mmap() with
 | 
					 * about each buffer into user space. For PCI buffers, it calls vm_mmap() with
 | 
				
			||||||
 * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
 | 
					 * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
 | 
				
			||||||
 * drm_mmap_dma().
 | 
					 * drm_mmap_dma().
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -1553,18 +1553,14 @@ int drm_mapbufs(struct drm_device *dev, void *data,
 | 
				
			||||||
				retcode = -EINVAL;
 | 
									retcode = -EINVAL;
 | 
				
			||||||
				goto done;
 | 
									goto done;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			down_write(¤t->mm->mmap_sem);
 | 
								virtual = vm_mmap(file_priv->filp, 0, map->size,
 | 
				
			||||||
			virtual = do_mmap(file_priv->filp, 0, map->size,
 | 
					 | 
				
			||||||
					  PROT_READ | PROT_WRITE,
 | 
										  PROT_READ | PROT_WRITE,
 | 
				
			||||||
					  MAP_SHARED,
 | 
										  MAP_SHARED,
 | 
				
			||||||
					  token);
 | 
										  token);
 | 
				
			||||||
			up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			down_write(¤t->mm->mmap_sem);
 | 
								virtual = vm_mmap(file_priv->filp, 0, dma->byte_count,
 | 
				
			||||||
			virtual = do_mmap(file_priv->filp, 0, dma->byte_count,
 | 
					 | 
				
			||||||
					  PROT_READ | PROT_WRITE,
 | 
										  PROT_READ | PROT_WRITE,
 | 
				
			||||||
					  MAP_SHARED, 0);
 | 
										  MAP_SHARED, 0);
 | 
				
			||||||
			up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (virtual > -1024UL) {
 | 
							if (virtual > -1024UL) {
 | 
				
			||||||
			/* Real error */
 | 
								/* Real error */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -581,10 +581,8 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
 | 
				
			||||||
	obj->filp->f_op = &exynos_drm_gem_fops;
 | 
						obj->filp->f_op = &exynos_drm_gem_fops;
 | 
				
			||||||
	obj->filp->private_data = obj;
 | 
						obj->filp->private_data = obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	down_write(¤t->mm->mmap_sem);
 | 
						addr = vm_mmap(obj->filp, 0, args->size,
 | 
				
			||||||
	addr = do_mmap(obj->filp, 0, args->size,
 | 
					 | 
				
			||||||
			PROT_READ | PROT_WRITE, MAP_SHARED, 0);
 | 
								PROT_READ | PROT_WRITE, MAP_SHARED, 0);
 | 
				
			||||||
	up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	drm_gem_object_unreference_unlocked(obj);
 | 
						drm_gem_object_unreference_unlocked(obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -129,6 +129,7 @@ static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
 | 
				
			||||||
	if (buf_priv->currently_mapped == I810_BUF_MAPPED)
 | 
						if (buf_priv->currently_mapped == I810_BUF_MAPPED)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* This is all entirely broken */
 | 
				
			||||||
	down_write(¤t->mm->mmap_sem);
 | 
						down_write(¤t->mm->mmap_sem);
 | 
				
			||||||
	old_fops = file_priv->filp->f_op;
 | 
						old_fops = file_priv->filp->f_op;
 | 
				
			||||||
	file_priv->filp->f_op = &i810_buffer_fops;
 | 
						file_priv->filp->f_op = &i810_buffer_fops;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1087,11 +1087,9 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
 | 
				
			||||||
	if (obj == NULL)
 | 
						if (obj == NULL)
 | 
				
			||||||
		return -ENOENT;
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	down_write(¤t->mm->mmap_sem);
 | 
						addr = vm_mmap(obj->filp, 0, args->size,
 | 
				
			||||||
	addr = do_mmap(obj->filp, 0, args->size,
 | 
					 | 
				
			||||||
		       PROT_READ | PROT_WRITE, MAP_SHARED,
 | 
							       PROT_READ | PROT_WRITE, MAP_SHARED,
 | 
				
			||||||
		       args->offset);
 | 
							       args->offset);
 | 
				
			||||||
	up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
	drm_gem_object_unreference_unlocked(obj);
 | 
						drm_gem_object_unreference_unlocked(obj);
 | 
				
			||||||
	if (IS_ERR((void *)addr))
 | 
						if (IS_ERR((void *)addr))
 | 
				
			||||||
		return addr;
 | 
							return addr;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -319,24 +319,20 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 | 
				
			||||||
			goto beyond_if;
 | 
								goto beyond_if;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		down_write(¤t->mm->mmap_sem);
 | 
							error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
 | 
				
			||||||
		error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
 | 
					 | 
				
			||||||
			PROT_READ | PROT_EXEC,
 | 
								PROT_READ | PROT_EXEC,
 | 
				
			||||||
			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
 | 
								MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
 | 
				
			||||||
			fd_offset);
 | 
								fd_offset);
 | 
				
			||||||
		up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (error != N_TXTADDR(ex)) {
 | 
							if (error != N_TXTADDR(ex)) {
 | 
				
			||||||
			send_sig(SIGKILL, current, 0);
 | 
								send_sig(SIGKILL, current, 0);
 | 
				
			||||||
			return error;
 | 
								return error;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		down_write(¤t->mm->mmap_sem);
 | 
							error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
 | 
				
			||||||
 		error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
 | 
					 | 
				
			||||||
				PROT_READ | PROT_WRITE | PROT_EXEC,
 | 
									PROT_READ | PROT_WRITE | PROT_EXEC,
 | 
				
			||||||
				MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
 | 
									MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
 | 
				
			||||||
				fd_offset + ex.a_text);
 | 
									fd_offset + ex.a_text);
 | 
				
			||||||
		up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
		if (error != N_DATADDR(ex)) {
 | 
							if (error != N_DATADDR(ex)) {
 | 
				
			||||||
			send_sig(SIGKILL, current, 0);
 | 
								send_sig(SIGKILL, current, 0);
 | 
				
			||||||
			return error;
 | 
								return error;
 | 
				
			||||||
| 
						 | 
					@ -417,12 +413,10 @@ static int load_aout_library(struct file *file)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Now use mmap to map the library into memory. */
 | 
						/* Now use mmap to map the library into memory. */
 | 
				
			||||||
	down_write(¤t->mm->mmap_sem);
 | 
						error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
 | 
				
			||||||
	error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
 | 
					 | 
				
			||||||
			PROT_READ | PROT_WRITE | PROT_EXEC,
 | 
								PROT_READ | PROT_WRITE | PROT_EXEC,
 | 
				
			||||||
			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
 | 
								MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
 | 
				
			||||||
			N_TXTOFF(ex));
 | 
								N_TXTOFF(ex));
 | 
				
			||||||
	up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
	retval = error;
 | 
						retval = error;
 | 
				
			||||||
	if (error != start_addr)
 | 
						if (error != start_addr)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -958,10 +958,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
 | 
				
			||||||
		   and some applications "depend" upon this behavior.
 | 
							   and some applications "depend" upon this behavior.
 | 
				
			||||||
		   Since we do not have the power to recompile these, we
 | 
							   Since we do not have the power to recompile these, we
 | 
				
			||||||
		   emulate the SVr4 behavior. Sigh. */
 | 
							   emulate the SVr4 behavior. Sigh. */
 | 
				
			||||||
		down_write(¤t->mm->mmap_sem);
 | 
							error = vm_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
 | 
				
			||||||
		error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
 | 
					 | 
				
			||||||
				MAP_FIXED | MAP_PRIVATE, 0);
 | 
									MAP_FIXED | MAP_PRIVATE, 0);
 | 
				
			||||||
		up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef ELF_PLAT_INIT
 | 
					#ifdef ELF_PLAT_INIT
 | 
				
			||||||
| 
						 | 
					@ -1046,8 +1044,7 @@ static int load_elf_library(struct file *file)
 | 
				
			||||||
		eppnt++;
 | 
							eppnt++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Now use mmap to map the library into memory. */
 | 
						/* Now use mmap to map the library into memory. */
 | 
				
			||||||
	down_write(¤t->mm->mmap_sem);
 | 
						error = vm_mmap(file,
 | 
				
			||||||
	error = do_mmap(file,
 | 
					 | 
				
			||||||
			ELF_PAGESTART(eppnt->p_vaddr),
 | 
								ELF_PAGESTART(eppnt->p_vaddr),
 | 
				
			||||||
			(eppnt->p_filesz +
 | 
								(eppnt->p_filesz +
 | 
				
			||||||
			 ELF_PAGEOFFSET(eppnt->p_vaddr)),
 | 
								 ELF_PAGEOFFSET(eppnt->p_vaddr)),
 | 
				
			||||||
| 
						 | 
					@ -1055,7 +1052,6 @@ static int load_elf_library(struct file *file)
 | 
				
			||||||
			MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
 | 
								MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
 | 
				
			||||||
			(eppnt->p_offset -
 | 
								(eppnt->p_offset -
 | 
				
			||||||
			 ELF_PAGEOFFSET(eppnt->p_vaddr)));
 | 
								 ELF_PAGEOFFSET(eppnt->p_vaddr)));
 | 
				
			||||||
	up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
	if (error != ELF_PAGESTART(eppnt->p_vaddr))
 | 
						if (error != ELF_PAGESTART(eppnt->p_vaddr))
 | 
				
			||||||
		goto out_free_ph;
 | 
							goto out_free_ph;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -390,21 +390,17 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
 | 
				
			||||||
	    (executable_stack == EXSTACK_DEFAULT && VM_STACK_FLAGS & VM_EXEC))
 | 
						    (executable_stack == EXSTACK_DEFAULT && VM_STACK_FLAGS & VM_EXEC))
 | 
				
			||||||
		stack_prot |= PROT_EXEC;
 | 
							stack_prot |= PROT_EXEC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	down_write(¤t->mm->mmap_sem);
 | 
						current->mm->start_brk = vm_mmap(NULL, 0, stack_size, stack_prot,
 | 
				
			||||||
	current->mm->start_brk = do_mmap(NULL, 0, stack_size, stack_prot,
 | 
					 | 
				
			||||||
					 MAP_PRIVATE | MAP_ANONYMOUS |
 | 
										 MAP_PRIVATE | MAP_ANONYMOUS |
 | 
				
			||||||
					 MAP_UNINITIALIZED | MAP_GROWSDOWN,
 | 
										 MAP_UNINITIALIZED | MAP_GROWSDOWN,
 | 
				
			||||||
					 0);
 | 
										 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (IS_ERR_VALUE(current->mm->start_brk)) {
 | 
						if (IS_ERR_VALUE(current->mm->start_brk)) {
 | 
				
			||||||
		up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
		retval = current->mm->start_brk;
 | 
							retval = current->mm->start_brk;
 | 
				
			||||||
		current->mm->start_brk = 0;
 | 
							current->mm->start_brk = 0;
 | 
				
			||||||
		goto error_kill;
 | 
							goto error_kill;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	current->mm->brk = current->mm->start_brk;
 | 
						current->mm->brk = current->mm->start_brk;
 | 
				
			||||||
	current->mm->context.end_brk = current->mm->start_brk;
 | 
						current->mm->context.end_brk = current->mm->start_brk;
 | 
				
			||||||
	current->mm->context.end_brk +=
 | 
						current->mm->context.end_brk +=
 | 
				
			||||||
| 
						 | 
					@ -955,10 +951,8 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(
 | 
				
			||||||
	if (params->flags & ELF_FDPIC_FLAG_EXECUTABLE)
 | 
						if (params->flags & ELF_FDPIC_FLAG_EXECUTABLE)
 | 
				
			||||||
		mflags |= MAP_EXECUTABLE;
 | 
							mflags |= MAP_EXECUTABLE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	down_write(&mm->mmap_sem);
 | 
						maddr = vm_mmap(NULL, load_addr, top - base,
 | 
				
			||||||
	maddr = do_mmap(NULL, load_addr, top - base,
 | 
					 | 
				
			||||||
			PROT_READ | PROT_WRITE | PROT_EXEC, mflags, 0);
 | 
								PROT_READ | PROT_WRITE | PROT_EXEC, mflags, 0);
 | 
				
			||||||
	up_write(&mm->mmap_sem);
 | 
					 | 
				
			||||||
	if (IS_ERR_VALUE(maddr))
 | 
						if (IS_ERR_VALUE(maddr))
 | 
				
			||||||
		return (int) maddr;
 | 
							return (int) maddr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1096,10 +1090,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* create the mapping */
 | 
							/* create the mapping */
 | 
				
			||||||
		disp = phdr->p_vaddr & ~PAGE_MASK;
 | 
							disp = phdr->p_vaddr & ~PAGE_MASK;
 | 
				
			||||||
		down_write(&mm->mmap_sem);
 | 
							maddr = vm_mmap(file, maddr, phdr->p_memsz + disp, prot, flags,
 | 
				
			||||||
		maddr = do_mmap(file, maddr, phdr->p_memsz + disp, prot, flags,
 | 
					 | 
				
			||||||
				phdr->p_offset - disp);
 | 
									phdr->p_offset - disp);
 | 
				
			||||||
		up_write(&mm->mmap_sem);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		kdebug("mmap[%d] <file> sz=%lx pr=%x fl=%x of=%lx --> %08lx",
 | 
							kdebug("mmap[%d] <file> sz=%lx pr=%x fl=%x of=%lx --> %08lx",
 | 
				
			||||||
		       loop, phdr->p_memsz + disp, prot, flags,
 | 
							       loop, phdr->p_memsz + disp, prot, flags,
 | 
				
			||||||
| 
						 | 
					@ -1143,10 +1135,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
 | 
				
			||||||
			unsigned long xmaddr;
 | 
								unsigned long xmaddr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			flags |= MAP_FIXED | MAP_ANONYMOUS;
 | 
								flags |= MAP_FIXED | MAP_ANONYMOUS;
 | 
				
			||||||
			down_write(&mm->mmap_sem);
 | 
								xmaddr = vm_mmap(NULL, xaddr, excess - excess1,
 | 
				
			||||||
			xmaddr = do_mmap(NULL, xaddr, excess - excess1,
 | 
					 | 
				
			||||||
					 prot, flags, 0);
 | 
										 prot, flags, 0);
 | 
				
			||||||
			up_write(&mm->mmap_sem);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			kdebug("mmap[%d] <anon>"
 | 
								kdebug("mmap[%d] <anon>"
 | 
				
			||||||
			       " ad=%lx sz=%lx pr=%x fl=%x of=0 --> %08lx",
 | 
								       " ad=%lx sz=%lx pr=%x fl=%x of=0 --> %08lx",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -542,10 +542,8 @@ static int load_flat_file(struct linux_binprm * bprm,
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
 | 
							DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		down_write(¤t->mm->mmap_sem);
 | 
							textpos = vm_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC,
 | 
				
			||||||
		textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC,
 | 
					 | 
				
			||||||
				  MAP_PRIVATE|MAP_EXECUTABLE, 0);
 | 
									  MAP_PRIVATE|MAP_EXECUTABLE, 0);
 | 
				
			||||||
		up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
		if (!textpos || IS_ERR_VALUE(textpos)) {
 | 
							if (!textpos || IS_ERR_VALUE(textpos)) {
 | 
				
			||||||
			if (!textpos)
 | 
								if (!textpos)
 | 
				
			||||||
				textpos = (unsigned long) -ENOMEM;
 | 
									textpos = (unsigned long) -ENOMEM;
 | 
				
			||||||
| 
						 | 
					@ -556,10 +554,8 @@ static int load_flat_file(struct linux_binprm * bprm,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
 | 
							len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
 | 
				
			||||||
		len = PAGE_ALIGN(len);
 | 
							len = PAGE_ALIGN(len);
 | 
				
			||||||
		down_write(¤t->mm->mmap_sem);
 | 
							realdatastart = vm_mmap(0, 0, len,
 | 
				
			||||||
		realdatastart = do_mmap(0, 0, len,
 | 
					 | 
				
			||||||
			PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
 | 
								PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
 | 
				
			||||||
		up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (realdatastart == 0 || IS_ERR_VALUE(realdatastart)) {
 | 
							if (realdatastart == 0 || IS_ERR_VALUE(realdatastart)) {
 | 
				
			||||||
			if (!realdatastart)
 | 
								if (!realdatastart)
 | 
				
			||||||
| 
						 | 
					@ -603,10 +599,8 @@ static int load_flat_file(struct linux_binprm * bprm,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
 | 
							len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
 | 
				
			||||||
		len = PAGE_ALIGN(len);
 | 
							len = PAGE_ALIGN(len);
 | 
				
			||||||
		down_write(¤t->mm->mmap_sem);
 | 
							textpos = vm_mmap(0, 0, len,
 | 
				
			||||||
		textpos = do_mmap(0, 0, len,
 | 
					 | 
				
			||||||
			PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
 | 
								PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
 | 
				
			||||||
		up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!textpos || IS_ERR_VALUE(textpos)) {
 | 
							if (!textpos || IS_ERR_VALUE(textpos)) {
 | 
				
			||||||
			if (!textpos)
 | 
								if (!textpos)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -147,10 +147,8 @@ static int map_som_binary(struct file *file,
 | 
				
			||||||
	code_size = SOM_PAGEALIGN(hpuxhdr->exec_tsize);
 | 
						code_size = SOM_PAGEALIGN(hpuxhdr->exec_tsize);
 | 
				
			||||||
	current->mm->start_code = code_start;
 | 
						current->mm->start_code = code_start;
 | 
				
			||||||
	current->mm->end_code = code_start + code_size;
 | 
						current->mm->end_code = code_start + code_size;
 | 
				
			||||||
	down_write(¤t->mm->mmap_sem);
 | 
						retval = vm_mmap(file, code_start, code_size, prot,
 | 
				
			||||||
	retval = do_mmap(file, code_start, code_size, prot,
 | 
					 | 
				
			||||||
			flags, SOM_PAGESTART(hpuxhdr->exec_tfile));
 | 
								flags, SOM_PAGESTART(hpuxhdr->exec_tfile));
 | 
				
			||||||
	up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
	if (retval < 0 && retval > -1024)
 | 
						if (retval < 0 && retval > -1024)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -158,20 +156,16 @@ static int map_som_binary(struct file *file,
 | 
				
			||||||
	data_size = SOM_PAGEALIGN(hpuxhdr->exec_dsize);
 | 
						data_size = SOM_PAGEALIGN(hpuxhdr->exec_dsize);
 | 
				
			||||||
	current->mm->start_data = data_start;
 | 
						current->mm->start_data = data_start;
 | 
				
			||||||
	current->mm->end_data = bss_start = data_start + data_size;
 | 
						current->mm->end_data = bss_start = data_start + data_size;
 | 
				
			||||||
	down_write(¤t->mm->mmap_sem);
 | 
						retval = vm_mmap(file, data_start, data_size,
 | 
				
			||||||
	retval = do_mmap(file, data_start, data_size,
 | 
					 | 
				
			||||||
			prot | PROT_WRITE, flags,
 | 
								prot | PROT_WRITE, flags,
 | 
				
			||||||
			SOM_PAGESTART(hpuxhdr->exec_dfile));
 | 
								SOM_PAGESTART(hpuxhdr->exec_dfile));
 | 
				
			||||||
	up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
	if (retval < 0 && retval > -1024)
 | 
						if (retval < 0 && retval > -1024)
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	som_brk = bss_start + SOM_PAGEALIGN(hpuxhdr->exec_bsize);
 | 
						som_brk = bss_start + SOM_PAGEALIGN(hpuxhdr->exec_bsize);
 | 
				
			||||||
	current->mm->start_brk = current->mm->brk = som_brk;
 | 
						current->mm->start_brk = current->mm->brk = som_brk;
 | 
				
			||||||
	down_write(¤t->mm->mmap_sem);
 | 
						retval = vm_mmap(NULL, bss_start, som_brk - bss_start,
 | 
				
			||||||
	retval = do_mmap(NULL, bss_start, som_brk - bss_start,
 | 
					 | 
				
			||||||
			prot | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, 0);
 | 
								prot | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, 0);
 | 
				
			||||||
	up_write(¤t->mm->mmap_sem);
 | 
					 | 
				
			||||||
	if (retval > 0 || retval < -1024)
 | 
						if (retval > 0 || retval < -1024)
 | 
				
			||||||
		retval = 0;
 | 
							retval = 0;
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1393,31 +1393,20 @@ extern int install_special_mapping(struct mm_struct *mm,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 | 
					extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
 | 
					 | 
				
			||||||
	unsigned long len, unsigned long prot,
 | 
					 | 
				
			||||||
	unsigned long flag, unsigned long pgoff);
 | 
					 | 
				
			||||||
extern unsigned long mmap_region(struct file *file, unsigned long addr,
 | 
					extern unsigned long mmap_region(struct file *file, unsigned long addr,
 | 
				
			||||||
	unsigned long len, unsigned long flags,
 | 
						unsigned long len, unsigned long flags,
 | 
				
			||||||
	vm_flags_t vm_flags, unsigned long pgoff);
 | 
						vm_flags_t vm_flags, unsigned long pgoff);
 | 
				
			||||||
 | 
					extern unsigned long do_mmap(struct file *, unsigned long,
 | 
				
			||||||
static inline unsigned long do_mmap(struct file *file, unsigned long addr,
 | 
					        unsigned long, unsigned long,
 | 
				
			||||||
	unsigned long len, unsigned long prot,
 | 
					        unsigned long, unsigned long);
 | 
				
			||||||
	unsigned long flag, unsigned long offset)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	unsigned long ret = -EINVAL;
 | 
					 | 
				
			||||||
	if ((offset + PAGE_ALIGN(len)) < offset)
 | 
					 | 
				
			||||||
		goto out;
 | 
					 | 
				
			||||||
	if (!(offset & ~PAGE_MASK))
 | 
					 | 
				
			||||||
		ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
 | 
					 | 
				
			||||||
out:
 | 
					 | 
				
			||||||
	return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extern int do_munmap(struct mm_struct *, unsigned long, size_t);
 | 
					extern int do_munmap(struct mm_struct *, unsigned long, size_t);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* These take the mm semaphore themselves */
 | 
					/* These take the mm semaphore themselves */
 | 
				
			||||||
extern unsigned long vm_brk(unsigned long, unsigned long);
 | 
					extern unsigned long vm_brk(unsigned long, unsigned long);
 | 
				
			||||||
extern int vm_munmap(struct mm_struct *, unsigned long, size_t);
 | 
					extern int vm_munmap(struct mm_struct *, unsigned long, size_t);
 | 
				
			||||||
 | 
					extern unsigned long vm_mmap(struct file *, unsigned long,
 | 
				
			||||||
 | 
					        unsigned long, unsigned long,
 | 
				
			||||||
 | 
					        unsigned long, unsigned long);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* truncate.c */
 | 
					/* truncate.c */
 | 
				
			||||||
extern void truncate_inode_pages(struct address_space *, loff_t);
 | 
					extern void truncate_inode_pages(struct address_space *, loff_t);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										29
									
								
								mm/mmap.c
									
										
									
									
									
								
							
							
						
						
									
										29
									
								
								mm/mmap.c
									
										
									
									
									
								
							| 
						 | 
					@ -953,7 +953,7 @@ static inline unsigned long round_hint_to_min(unsigned long hint)
 | 
				
			||||||
 * The caller must hold down_write(¤t->mm->mmap_sem).
 | 
					 * The caller must hold down_write(¤t->mm->mmap_sem).
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
 | 
					static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
 | 
				
			||||||
			unsigned long len, unsigned long prot,
 | 
								unsigned long len, unsigned long prot,
 | 
				
			||||||
			unsigned long flags, unsigned long pgoff)
 | 
								unsigned long flags, unsigned long pgoff)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1089,7 +1089,32 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return mmap_region(file, addr, len, flags, vm_flags, pgoff);
 | 
						return mmap_region(file, addr, len, flags, vm_flags, pgoff);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(do_mmap_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,
 | 
					SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
 | 
				
			||||||
		unsigned long, prot, unsigned long, flags,
 | 
							unsigned long, prot, unsigned long, flags,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										29
									
								
								mm/nommu.c
									
										
									
									
									
								
							
							
						
						
									
										29
									
								
								mm/nommu.c
									
										
									
									
									
								
							| 
						 | 
					@ -1233,7 +1233,7 @@ enomem:
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * handle mapping creation for uClinux
 | 
					 * handle mapping creation for uClinux
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
unsigned long do_mmap_pgoff(struct file *file,
 | 
					static unsigned long do_mmap_pgoff(struct file *file,
 | 
				
			||||||
			    unsigned long addr,
 | 
								    unsigned long addr,
 | 
				
			||||||
			    unsigned long len,
 | 
								    unsigned long len,
 | 
				
			||||||
			    unsigned long prot,
 | 
								    unsigned long prot,
 | 
				
			||||||
| 
						 | 
					@ -1470,7 +1470,32 @@ error_getting_region:
 | 
				
			||||||
	show_free_areas(0);
 | 
						show_free_areas(0);
 | 
				
			||||||
	return -ENOMEM;
 | 
						return -ENOMEM;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL(do_mmap_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,
 | 
					SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
 | 
				
			||||||
		unsigned long, prot, unsigned long, flags,
 | 
							unsigned long, prot, unsigned long, flags,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue