// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2023 Huawei Technologies Duesseldorf GmbH * * Tool to test IMA MMAP_CHECK and MMAP_CHECK_REQPROT hooks. */ #include #include #include #include #include #include #include #include /* * Convention: return 1 for errors that should not occur, as they are * setup-related, return 2 for errors that might occur due to testing * conditions. */ #define ERR_SETUP 1 #define ERR_TEST 2 int main(int argc, char *argv[]) { struct stat st; void *ptr, *ptr_write = NULL; int ret, fd, fd_write, prot = PROT_READ; if (!argv[1]) { printf("Missing file parameter\n"); return ERR_SETUP; } if (argv[2] && !strcmp(argv[2], "read_implies_exec")) { ret = personality(READ_IMPLIES_EXEC); if (ret == -1) { printf("Failed to set personality, err: %d (%s)\n", -errno, strerror(errno)); return ERR_SETUP; } } if (stat(argv[1], &st) == -1) { printf("Failed to access %s, err: %d (%s)\n", argv[1], -errno, strerror(errno)); return ERR_SETUP; } if (argv[2] && !strcmp(argv[2], "exec_on_writable")) { fd_write = open(argv[1], O_RDWR); if (fd_write == -1) { printf("Failed to open %s in r/w, err: %d (%s)\n", argv[1], -errno, strerror(errno)); return ERR_SETUP; } ptr_write = mmap(0, st.st_size, PROT_WRITE, MAP_SHARED, fd_write, 0); close(fd_write); if (ptr_write == MAP_FAILED) { printf("Failed mmap() with PROT_WRITE on %s, err: %d (%s)\n", argv[1], -errno, strerror(errno)); return ERR_SETUP; } } fd = open(argv[1], O_RDONLY); if (fd == -1) { printf("Failed to open %s in ro, err: %d (%s)\n", argv[1], -errno, strerror(errno)); if (ptr_write && munmap(ptr_write, st.st_size) == -1) printf("Failed munmap() of writable mapping on %s, err: %d (%s)\n", argv[1], -errno, strerror(errno)); return ERR_SETUP; } if (argv[2] && !strncmp(argv[2], "exec", 4)) prot |= PROT_EXEC; ptr = mmap(0, st.st_size, prot, MAP_PRIVATE, fd, 0); close(fd); if (ptr_write && munmap(ptr_write, st.st_size) == -1) { printf("Failed munmap() of writable mapping on %s, err: %d (%s)\n", argv[1], -errno, strerror(errno)); return ERR_SETUP; } if (ptr == MAP_FAILED) { ret = ERR_SETUP; if (argv[2] && !strcmp(argv[2], "exec_on_writable") && errno == EACCES) ret = ERR_TEST; else printf("Failed mmap() with PROT_READ%s on %s, err: %d (%s)\n", (prot & PROT_EXEC) ? " | PROT_EXEC" : "", argv[1], -errno, strerror(errno)); return ret; } ret = 0; if (argv[2] && !strcmp(argv[2], "mprotect")) { ret = mprotect(ptr, st.st_size, PROT_EXEC); if (ret == -1) { ret = ERR_SETUP; if (errno == EPERM) ret = ERR_TEST; else printf("Unexpected mprotect() error on %s, err: %d (%s)\n", argv[1], -errno, strerror(errno)); } } if (munmap(ptr, st.st_size) == -1) { printf("Failed munmap() of mapping on %s, err: %d (%s)\n", argv[1], -errno, strerror(errno)); return ERR_SETUP; } return ret; }