138 lines · c
1// SPDX-License-Identifier: GPL-2.02#define _GNU_SOURCE3#include <sys/mman.h>4#include <stdint.h>5#include <asm-generic/unistd.h>6#include <string.h>7#include <sys/time.h>8#include <sys/resource.h>9#include <stdbool.h>10#include "../kselftest.h"11#include <syscall.h>12#include <errno.h>13#include <stdio.h>14#include <stdlib.h>15#include <fcntl.h>16#include <sys/ioctl.h>17#include <sys/vfs.h>18#include <sys/stat.h>19#include "mseal_helpers.h"20 21/*22 * define sys_xyx to call syscall directly.23 */24static int sys_mseal(void *start, size_t len)25{26 int sret;27 28 errno = 0;29 sret = syscall(__NR_mseal, start, len, 0);30 return sret;31}32 33static inline int sys_mprotect(void *ptr, size_t size, unsigned long prot)34{35 int sret;36 37 errno = 0;38 sret = syscall(__NR_mprotect, ptr, size, prot);39 return sret;40}41 42static bool seal_support(void)43{44 int ret;45 void *ptr;46 unsigned long page_size = getpagesize();47 48 ptr = mmap(NULL, page_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);49 if (ptr == (void *) -1)50 return false;51 52 ret = sys_mseal(ptr, page_size);53 if (ret < 0)54 return false;55 56 return true;57}58 59const char somestr[4096] = {"READONLY"};60 61static void test_seal_elf(void)62{63 int ret;64 FILE *maps;65 char line[512];66 uintptr_t addr_start, addr_end;67 char prot[5];68 char filename[256];69 unsigned long page_size = getpagesize();70 unsigned long long ptr = (unsigned long long) somestr;71 char *somestr2 = (char *)somestr;72 73 /*74 * Modify the protection of readonly somestr75 */76 if (((unsigned long long)ptr % page_size) != 0)77 ptr = (unsigned long long)ptr & ~(page_size - 1);78 79 ksft_print_msg("somestr = %s\n", somestr);80 ksft_print_msg("change protection to rw\n");81 ret = sys_mprotect((void *)ptr, page_size, PROT_READ|PROT_WRITE);82 FAIL_TEST_IF_FALSE(!ret);83 *somestr2 = 'A';84 ksft_print_msg("somestr is modified to: %s\n", somestr);85 ret = sys_mprotect((void *)ptr, page_size, PROT_READ);86 FAIL_TEST_IF_FALSE(!ret);87 88 maps = fopen("/proc/self/maps", "r");89 FAIL_TEST_IF_FALSE(maps);90 91 /*92 * apply sealing to elf binary93 */94 while (fgets(line, sizeof(line), maps)) {95 if (sscanf(line, "%lx-%lx %4s %*x %*x:%*x %*u %255[^\n]",96 &addr_start, &addr_end, prot, filename) == 4) {97 if (strlen(filename)) {98 /*99 * seal the mapping if read only.100 */101 if (strstr(prot, "r-")) {102 ret = sys_mseal((void *)addr_start, addr_end - addr_start);103 FAIL_TEST_IF_FALSE(!ret);104 ksft_print_msg("sealed: %lx-%lx %s %s\n",105 addr_start, addr_end, prot, filename);106 if ((uintptr_t) somestr >= addr_start &&107 (uintptr_t) somestr <= addr_end)108 ksft_print_msg("mapping for somestr found\n");109 }110 }111 }112 }113 fclose(maps);114 115 ret = sys_mprotect((void *)ptr, page_size, PROT_READ | PROT_WRITE);116 FAIL_TEST_IF_FALSE(ret < 0);117 ksft_print_msg("somestr is sealed, mprotect is rejected\n");118 119 REPORT_TEST_PASS();120}121 122int main(int argc, char **argv)123{124 bool test_seal = seal_support();125 126 ksft_print_header();127 ksft_print_msg("pid=%d\n", getpid());128 129 if (!test_seal)130 ksft_exit_skip("sealing not supported, check CONFIG_64BIT\n");131 132 ksft_set_plan(1);133 134 test_seal_elf();135 136 ksft_finished();137}138