Whamcloud - gitweb
LU-8299 llite: ll_fault should fail for insane file offsets 42/34242/5
authorAlexander Zarochentsev <c17826@cray.com>
Tue, 12 Feb 2019 15:28:37 +0000 (18:28 +0300)
committerOleg Drokin <green@whamcloud.com>
Wed, 27 Feb 2019 02:03:19 +0000 (02:03 +0000)
A page fault for a mmapped lustre file at offset large than
2^63 cause Lustre client to hang due to wrong page index
calculations from signed loff_t.
There is no need to do such calclulations but perform
page offset sanity checks in ll_fault().

Cray-bug-id: LUS-1392
Signed-off-by: Alexander Zarochentsev <c17826@cray.com>
Change-Id: Ia492083ee4bdc23edfcbf88cb6d7e9726b2ca80c
Reviewed-on: https://review.whamcloud.com/34242
Reviewed-by: Andrew Perepechko <c17827@cray.com>
Tested-by: Jenkins
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Patrick Farrell <pfarrell@whamcloud.com>
Reviewed-by: James Simmons <uja.ornl@yahoo.com>
lustre/llite/llite_mmap.c
lustre/tests/mmap_sanity.c

index 9dc934a..fe8710a 100644 (file)
@@ -363,6 +363,9 @@ static int ll_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
        ll_stats_ops_tally(ll_i2sbi(file_inode(vma->vm_file)),
                           LPROC_LL_FAULT, 1);
 
        ll_stats_ops_tally(ll_i2sbi(file_inode(vma->vm_file)),
                           LPROC_LL_FAULT, 1);
 
+       /* make sure offset is not a negative number */
+       if (vmf->pgoff > (MAX_LFS_FILESIZE >> PAGE_SHIFT))
+               return VM_FAULT_SIGBUS;
 restart:
        result = ll_fault0(vma, vmf);
        if (!(result & (VM_FAULT_RETRY | VM_FAULT_ERROR | VM_FAULT_LOCKED))) {
 restart:
        result = ll_fault0(vma, vmf);
        if (!(result & (VM_FAULT_RETRY | VM_FAULT_ERROR | VM_FAULT_LOCKED))) {
index b432435..90a2edb 100644 (file)
@@ -748,6 +748,56 @@ out:
         return rc;
 }
 
         return rc;
 }
 
+static int mmap_tst9(char *mnt)
+{
+        char  fname[256];
+        char *buf = MAP_FAILED;
+        int fd = -1;
+        int rc = 0;
+
+       if (snprintf(fname, 256, "%s/mmap_tst9", mnt) >= 256) {
+               fprintf(stderr, "dir name too long\n");
+               rc = -ENAMETOOLONG;
+               goto out;
+       }
+       if (unlink(fname) == -1 && errno != ENOENT) {
+               perror("unlink");
+               rc = -errno;
+               goto out;
+       }
+       fd = open(fname, O_RDWR | O_CREAT, 0644);
+       if (fd == -1) {
+               perror("open");
+               rc = -errno;
+               goto out;
+        }
+       buf = mmap(NULL, page_size * 2,
+                  PROT_READ , MAP_PRIVATE, fd, (loff_t)(-10 * page_size));
+       if (buf == MAP_FAILED) {
+               perror("mmap");
+               rc = -errno;
+               goto out;
+       }
+       rc = write(STDOUT_FILENO, buf, 2 * page_size);
+       if (rc != -1) {
+               fprintf(stderr, "write succeded with %d instead of failing\n", rc);
+               rc = -EINVAL;
+               goto out;
+       } else if (errno != EFAULT) {
+               fprintf(stderr, "write failed with %d instead of EFAULT(%d)\n",
+                       errno, EFAULT);
+               rc = -errno;
+               goto out;
+       }
+       rc = 0;
+out:
+       if (buf != MAP_FAILED)
+               munmap(buf, page_size * 2);
+       if (fd != -1)
+               close(fd);
+       return rc;
+}
+
 static int remote_tst(int tc, char *mnt)
 {
         int rc = 0;
 static int remote_tst(int tc, char *mnt)
 {
         int rc = 0;
@@ -829,6 +879,12 @@ struct test_case tests[] = {
                .node_cnt       = 1
        },
        {
                .node_cnt       = 1
        },
        {
+               .tc             = 9,
+               .desc           = "mmap test9: SIGBUS for negative file offset",
+               .test_fn        = mmap_tst9,
+               .node_cnt       = 1
+       },
+       {
                .tc             = 0
        }
 };
                .tc             = 0
        }
 };