From ada3b33b52cdc6420e3b186c0aba4dd0b0337d8c Mon Sep 17 00:00:00 2001 From: Alexander Zarochentsev Date: Tue, 12 Feb 2019 18:28:37 +0300 Subject: [PATCH] LU-8299 llite: ll_fault should fail for insane file offsets 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 Change-Id: Ia492083ee4bdc23edfcbf88cb6d7e9726b2ca80c Reviewed-on: https://review.whamcloud.com/34242 Reviewed-by: Andrew Perepechko Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Patrick Farrell Reviewed-by: James Simmons --- lustre/llite/llite_mmap.c | 3 +++ lustre/tests/mmap_sanity.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/lustre/llite/llite_mmap.c b/lustre/llite/llite_mmap.c index 9dc934a..fe8710a 100644 --- a/lustre/llite/llite_mmap.c +++ b/lustre/llite/llite_mmap.c @@ -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); + /* 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))) { diff --git a/lustre/tests/mmap_sanity.c b/lustre/tests/mmap_sanity.c index b432435..90a2edb 100644 --- a/lustre/tests/mmap_sanity.c +++ b/lustre/tests/mmap_sanity.c @@ -748,6 +748,56 @@ out: 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; @@ -829,6 +879,12 @@ struct test_case tests[] = { .node_cnt = 1 }, { + .tc = 9, + .desc = "mmap test9: SIGBUS for negative file offset", + .test_fn = mmap_tst9, + .node_cnt = 1 + }, + { .tc = 0 } }; -- 1.8.3.1