1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * Copyright (C) 2012 Red Hat, Inc. 3f08c3bdfSopenharmony_ci * 4f08c3bdfSopenharmony_ci * This program is free software; you can redistribute it and/or 5f08c3bdfSopenharmony_ci * modify it under the terms of version 2 of the GNU General Public 6f08c3bdfSopenharmony_ci * License as published by the Free Software Foundation. 7f08c3bdfSopenharmony_ci * 8f08c3bdfSopenharmony_ci * This program is distributed in the hope that it would be useful, 9f08c3bdfSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 10f08c3bdfSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 11f08c3bdfSopenharmony_ci * 12f08c3bdfSopenharmony_ci * Further, this software is distributed without any warranty that it 13f08c3bdfSopenharmony_ci * is free of the rightful claim of any third person regarding 14f08c3bdfSopenharmony_ci * infringement or the like. Any license provided herein, whether 15f08c3bdfSopenharmony_ci * implied or otherwise, applies only to this software file. Patent 16f08c3bdfSopenharmony_ci * licenses, if any, provided herein do not apply to combinations of 17f08c3bdfSopenharmony_ci * this program with other software, or any other product whatsoever. 18f08c3bdfSopenharmony_ci * 19f08c3bdfSopenharmony_ci * You should have received a copy of the GNU General Public License 20f08c3bdfSopenharmony_ci * along with this program; if not, write the Free Software 21f08c3bdfSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 22f08c3bdfSopenharmony_ci * 02110-1301, USA. 23f08c3bdfSopenharmony_ci */ 24f08c3bdfSopenharmony_ci/* 25f08c3bdfSopenharmony_ci * This is a reproducer for CVE-2011-2496. 26f08c3bdfSopenharmony_ci * 27f08c3bdfSopenharmony_ci * The normal mmap paths all avoid creating a mapping where the pgoff 28f08c3bdfSopenharmony_ci * inside the mapping could wrap around due to overflow. However, an 29f08c3bdfSopenharmony_ci * expanding mremap() can take such a non-wrapping mapping and make it 30f08c3bdfSopenharmony_ci * bigger and cause a wrapping condition. There is also another case 31f08c3bdfSopenharmony_ci * where we expand mappings hiding in plain sight: the automatic stack 32f08c3bdfSopenharmony_ci * expansion. 33f08c3bdfSopenharmony_ci * 34f08c3bdfSopenharmony_ci * This program tries to remap a mapping with a new size that would 35f08c3bdfSopenharmony_ci * wrap pgoff. Notice that it only works on 32-bit arch for now. 36f08c3bdfSopenharmony_ci */ 37f08c3bdfSopenharmony_ci 38f08c3bdfSopenharmony_ci#define _GNU_SOURCE 39f08c3bdfSopenharmony_ci#include "config.h" 40f08c3bdfSopenharmony_ci#include <sys/types.h> 41f08c3bdfSopenharmony_ci#include <sys/mman.h> 42f08c3bdfSopenharmony_ci#include <sys/stat.h> 43f08c3bdfSopenharmony_ci#include <sys/syscall.h> 44f08c3bdfSopenharmony_ci#include <errno.h> 45f08c3bdfSopenharmony_ci#include <fcntl.h> 46f08c3bdfSopenharmony_ci#include <limits.h> 47f08c3bdfSopenharmony_ci#include <stdio.h> 48f08c3bdfSopenharmony_ci#include <stdlib.h> 49f08c3bdfSopenharmony_ci#include <unistd.h> 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_ci#include "test.h" 52f08c3bdfSopenharmony_ci#include "safe_macros.h" 53f08c3bdfSopenharmony_ci#include "tst_kernel.h" 54f08c3bdfSopenharmony_ci#include "lapi/abisize.h" 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_cichar *TCID = "vma03"; 57f08c3bdfSopenharmony_ciint TST_TOTAL = 1; 58f08c3bdfSopenharmony_ci 59f08c3bdfSopenharmony_ci#ifdef __NR_mmap2 60f08c3bdfSopenharmony_ci#define TESTFILE "testfile" 61f08c3bdfSopenharmony_ci 62f08c3bdfSopenharmony_cistatic size_t pgsz; 63f08c3bdfSopenharmony_cistatic int fd; 64f08c3bdfSopenharmony_ci 65f08c3bdfSopenharmony_cistatic void *mmap2(void *addr, size_t length, int prot, 66f08c3bdfSopenharmony_ci int flags, int fd, off_t pgoffset); 67f08c3bdfSopenharmony_cistatic void setup(void); 68f08c3bdfSopenharmony_cistatic void cleanup(void); 69f08c3bdfSopenharmony_ci 70f08c3bdfSopenharmony_ciint main(int argc, char *argv[]) 71f08c3bdfSopenharmony_ci{ 72f08c3bdfSopenharmony_ci int lc; 73f08c3bdfSopenharmony_ci void *map, *remap; 74f08c3bdfSopenharmony_ci off_t pgoff; 75f08c3bdfSopenharmony_ci 76f08c3bdfSopenharmony_ci if (TST_ABI != 32 || tst_kernel_bits() != 32) { 77f08c3bdfSopenharmony_ci tst_brkm(TCONF, NULL, 78f08c3bdfSopenharmony_ci "test is designed for 32-bit system only."); 79f08c3bdfSopenharmony_ci } 80f08c3bdfSopenharmony_ci 81f08c3bdfSopenharmony_ci tst_parse_opts(argc, argv, NULL, NULL); 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_ci pgsz = sysconf(_SC_PAGE_SIZE); 84f08c3bdfSopenharmony_ci setup(); 85f08c3bdfSopenharmony_ci 86f08c3bdfSopenharmony_ci for (lc = 0; TEST_LOOPING(lc); lc++) { 87f08c3bdfSopenharmony_ci tst_count = 0; 88f08c3bdfSopenharmony_ci 89f08c3bdfSopenharmony_ci fd = SAFE_OPEN(NULL, TESTFILE, O_RDWR); 90f08c3bdfSopenharmony_ci 91f08c3bdfSopenharmony_ci /* 92f08c3bdfSopenharmony_ci * The pgoff is counted in 4K units and must be page-aligned, 93f08c3bdfSopenharmony_ci * hence we must align it down to page_size/4096 in a case that 94f08c3bdfSopenharmony_ci * the system has page_size > 4K. 95f08c3bdfSopenharmony_ci */ 96f08c3bdfSopenharmony_ci pgoff = (ULONG_MAX - 1)&(~((pgsz-1)>>12)); 97f08c3bdfSopenharmony_ci map = mmap2(NULL, pgsz, PROT_READ | PROT_WRITE, MAP_PRIVATE, 98f08c3bdfSopenharmony_ci fd, pgoff); 99f08c3bdfSopenharmony_ci if (map == MAP_FAILED) 100f08c3bdfSopenharmony_ci tst_brkm(TBROK | TERRNO, cleanup, "mmap2"); 101f08c3bdfSopenharmony_ci 102f08c3bdfSopenharmony_ci remap = mremap(map, pgsz, 2 * pgsz, 0); 103f08c3bdfSopenharmony_ci if (remap == MAP_FAILED) { 104f08c3bdfSopenharmony_ci if (errno == EINVAL) 105f08c3bdfSopenharmony_ci tst_resm(TPASS, "mremap failed as expected."); 106f08c3bdfSopenharmony_ci else 107f08c3bdfSopenharmony_ci tst_resm(TFAIL | TERRNO, "mremap"); 108f08c3bdfSopenharmony_ci munmap(map, pgsz); 109f08c3bdfSopenharmony_ci } else { 110f08c3bdfSopenharmony_ci tst_resm(TFAIL, "mremap succeeded unexpectedly."); 111f08c3bdfSopenharmony_ci munmap(remap, 2 * pgsz); 112f08c3bdfSopenharmony_ci } 113f08c3bdfSopenharmony_ci 114f08c3bdfSopenharmony_ci close(fd); 115f08c3bdfSopenharmony_ci } 116f08c3bdfSopenharmony_ci 117f08c3bdfSopenharmony_ci cleanup(); 118f08c3bdfSopenharmony_ci tst_exit(); 119f08c3bdfSopenharmony_ci} 120f08c3bdfSopenharmony_ci 121f08c3bdfSopenharmony_cistatic void *mmap2(void *addr, size_t length, int prot, 122f08c3bdfSopenharmony_ci int flags, int fd, off_t pgoffset) 123f08c3bdfSopenharmony_ci{ 124f08c3bdfSopenharmony_ci return (void *)syscall(SYS_mmap2, addr, length, prot, 125f08c3bdfSopenharmony_ci flags, fd, pgoffset); 126f08c3bdfSopenharmony_ci} 127f08c3bdfSopenharmony_ci 128f08c3bdfSopenharmony_cistatic void setup(void) 129f08c3bdfSopenharmony_ci{ 130f08c3bdfSopenharmony_ci tst_sig(FORK, DEF_HANDLER, cleanup); 131f08c3bdfSopenharmony_ci 132f08c3bdfSopenharmony_ci tst_tmpdir(); 133f08c3bdfSopenharmony_ci 134f08c3bdfSopenharmony_ci fd = SAFE_CREAT(NULL, TESTFILE, 0644); 135f08c3bdfSopenharmony_ci close(fd); 136f08c3bdfSopenharmony_ci 137f08c3bdfSopenharmony_ci TEST_PAUSE; 138f08c3bdfSopenharmony_ci} 139f08c3bdfSopenharmony_ci 140f08c3bdfSopenharmony_cistatic void cleanup(void) 141f08c3bdfSopenharmony_ci{ 142f08c3bdfSopenharmony_ci tst_rmdir(); 143f08c3bdfSopenharmony_ci} 144f08c3bdfSopenharmony_ci#else /* __NR_mmap2 */ 145f08c3bdfSopenharmony_ciint main(int argc, char *argv[]) 146f08c3bdfSopenharmony_ci{ 147f08c3bdfSopenharmony_ci tst_brkm(TCONF, NULL, "__NR_mmap2 is not defined on your system"); 148f08c3bdfSopenharmony_ci} 149f08c3bdfSopenharmony_ci#endif 150