]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - ipc/shm.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
[mirror_ubuntu-artful-kernel.git] / ipc / shm.c
index 258aff2e03bbc61773a1e7f5a2d8ea4230574910..481d2a9c298ab14916543a040d4f45b9b69764e0 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -374,12 +374,12 @@ void exit_shm(struct task_struct *task)
        up_write(&shm_ids(ns).rwsem);
 }
 
-static int shm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
+static int shm_fault(struct vm_fault *vmf)
 {
-       struct file *file = vma->vm_file;
+       struct file *file = vmf->vma->vm_file;
        struct shm_file_data *sfd = shm_file_data(file);
 
-       return sfd->vm_ops->fault(vma, vmf);
+       return sfd->vm_ops->fault(vmf);
 }
 
 #ifdef CONFIG_NUMA
@@ -1091,8 +1091,8 @@ out_unlock1:
  * "raddr" thing points to kernel space, and there has to be a wrapper around
  * this.
  */
-long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
-             unsigned long shmlba)
+long do_shmat(int shmid, char __user *shmaddr, int shmflg,
+             ulong *raddr, unsigned long shmlba)
 {
        struct shmid_kernel *shp;
        unsigned long addr;
@@ -1113,8 +1113,13 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
                goto out;
        else if ((addr = (ulong)shmaddr)) {
                if (addr & (shmlba - 1)) {
-                       if (shmflg & SHM_RND)
-                               addr &= ~(shmlba - 1);     /* round down */
+                       /*
+                        * Round down to the nearest multiple of shmlba.
+                        * For sane do_mmap_pgoff() parameters, avoid
+                        * round downs that trigger nil-page and MAP_FIXED.
+                        */
+                       if ((shmflg & SHM_RND) && addr >= shmlba)
+                               addr &= ~(shmlba - 1);
                        else
 #ifndef __ARCH_FORCE_SHMLBA
                                if (addr & ~PAGE_MASK)
@@ -1222,7 +1227,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr,
                        goto invalid;
        }
 
-       addr = do_mmap_pgoff(file, addr, size, prot, flags, 0, &populate);
+       addr = do_mmap_pgoff(file, addr, size, prot, flags, 0, &populate, NULL);
        *raddr = addr;
        err = 0;
        if (IS_ERR_VALUE(addr))
@@ -1329,7 +1334,7 @@ SYSCALL_DEFINE1(shmdt, char __user *, shmaddr)
                         */
                        file = vma->vm_file;
                        size = i_size_read(file_inode(vma->vm_file));
-                       do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start);
+                       do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start, NULL);
                        /*
                         * We discovered the size of the shm segment, so
                         * break out of here and fall through to the next
@@ -1356,7 +1361,7 @@ SYSCALL_DEFINE1(shmdt, char __user *, shmaddr)
                if ((vma->vm_ops == &shm_vm_ops) &&
                    ((vma->vm_start - addr)/PAGE_SIZE == vma->vm_pgoff) &&
                    (vma->vm_file == file))
-                       do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start);
+                       do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start, NULL);
                vma = next;
        }
 
@@ -1365,7 +1370,7 @@ SYSCALL_DEFINE1(shmdt, char __user *, shmaddr)
         * given
         */
        if (vma && vma->vm_start == addr && vma->vm_ops == &shm_vm_ops) {
-               do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start);
+               do_munmap(mm, vma->vm_start, vma->vm_end - vma->vm_start, NULL);
                retval = 0;
        }