Loading...
Note: File does not exist in v3.15.
1// SPDX-License-Identifier: GPL-2.0
2#define _GNU_SOURCE
3#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 somestr
75 */
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 binary
93 */
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}