~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/um/os-Linux/mem.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  4  */
  5 
  6 #include <stdio.h>
  7 #include <stddef.h>
  8 #include <stdlib.h>
  9 #include <unistd.h>
 10 #include <errno.h>
 11 #include <fcntl.h>
 12 #include <string.h>
 13 #include <sys/stat.h>
 14 #include <sys/mman.h>
 15 #include <sys/vfs.h>
 16 #include <linux/magic.h>
 17 #include <init.h>
 18 #include <kern_util.h>
 19 #include <os.h>
 20 #include "internal.h"
 21 
 22 /*
 23  * kasan_map_memory - maps memory from @start with a size of @len.
 24  * The allocated memory is filled with zeroes upon success.
 25  * @start: the start address of the memory to be mapped
 26  * @len: the length of the memory to be mapped
 27  *
 28  * This function is used to map shadow memory for KASAN in uml
 29  */
 30 void kasan_map_memory(void *start, size_t len)
 31 {
 32         if (mmap(start,
 33                  len,
 34                  PROT_READ|PROT_WRITE,
 35                  MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE,
 36                  -1,
 37                  0) == MAP_FAILED) {
 38                 os_info("Couldn't allocate shadow memory: %s\n.",
 39                         strerror(errno));
 40                 exit(1);
 41         }
 42 }
 43 
 44 /* Set by make_tempfile() during early boot. */
 45 static char *tempdir = NULL;
 46 
 47 /* Check if dir is on tmpfs. Return 0 if yes, -1 if no or error. */
 48 static int __init check_tmpfs(const char *dir)
 49 {
 50         struct statfs st;
 51 
 52         os_info("Checking if %s is on tmpfs...", dir);
 53         if (statfs(dir, &st) < 0) {
 54                 os_info("%s\n", strerror(errno));
 55         } else if (st.f_type != TMPFS_MAGIC) {
 56                 os_info("no\n");
 57         } else {
 58                 os_info("OK\n");
 59                 return 0;
 60         }
 61         return -1;
 62 }
 63 
 64 /*
 65  * Choose the tempdir to use. We want something on tmpfs so that our memory is
 66  * not subject to the host's vm.dirty_ratio. If a tempdir is specified in the
 67  * environment, we use that even if it's not on tmpfs, but we warn the user.
 68  * Otherwise, we try common tmpfs locations, and if no tmpfs directory is found
 69  * then we fall back to /tmp.
 70  */
 71 static char * __init choose_tempdir(void)
 72 {
 73         static const char * const vars[] = {
 74                 "TMPDIR",
 75                 "TMP",
 76                 "TEMP",
 77                 NULL
 78         };
 79         static const char fallback_dir[] = "/tmp";
 80         static const char * const tmpfs_dirs[] = {
 81                 "/dev/shm",
 82                 fallback_dir,
 83                 NULL
 84         };
 85         int i;
 86         const char *dir;
 87 
 88         os_info("Checking environment variables for a tempdir...");
 89         for (i = 0; vars[i]; i++) {
 90                 dir = getenv(vars[i]);
 91                 if ((dir != NULL) && (*dir != '\0')) {
 92                         os_info("%s\n", dir);
 93                         if (check_tmpfs(dir) >= 0)
 94                                 goto done;
 95                         else
 96                                 goto warn;
 97                 }
 98         }
 99         os_info("none found\n");
100 
101         for (i = 0; tmpfs_dirs[i]; i++) {
102                 dir = tmpfs_dirs[i];
103                 if (check_tmpfs(dir) >= 0)
104                         goto done;
105         }
106 
107         dir = fallback_dir;
108 warn:
109         os_warn("Warning: tempdir %s is not on tmpfs\n", dir);
110 done:
111         /* Make a copy since getenv results may not remain valid forever. */
112         return strdup(dir);
113 }
114 
115 /*
116  * Create an unlinked tempfile in a suitable tempdir. template must be the
117  * basename part of the template with a leading '/'.
118  */
119 static int __init make_tempfile(const char *template)
120 {
121         char *tempname;
122         int fd;
123 
124         if (tempdir == NULL) {
125                 tempdir = choose_tempdir();
126                 if (tempdir == NULL) {
127                         os_warn("Failed to choose tempdir: %s\n",
128                                 strerror(errno));
129                         return -1;
130                 }
131         }
132 
133 #ifdef O_TMPFILE
134         fd = open(tempdir, O_CLOEXEC | O_RDWR | O_EXCL | O_TMPFILE, 0700);
135         /*
136          * If the running system does not support O_TMPFILE flag then retry
137          * without it.
138          */
139         if (fd != -1 || (errno != EINVAL && errno != EISDIR &&
140                         errno != EOPNOTSUPP))
141                 return fd;
142 #endif
143 
144         tempname = malloc(strlen(tempdir) + strlen(template) + 1);
145         if (tempname == NULL)
146                 return -1;
147 
148         strcpy(tempname, tempdir);
149         strcat(tempname, template);
150         fd = mkstemp(tempname);
151         if (fd < 0) {
152                 os_warn("open - cannot create %s: %s\n", tempname,
153                         strerror(errno));
154                 goto out;
155         }
156         if (unlink(tempname) < 0) {
157                 perror("unlink");
158                 goto close;
159         }
160         free(tempname);
161         return fd;
162 close:
163         close(fd);
164 out:
165         free(tempname);
166         return -1;
167 }
168 
169 #define TEMPNAME_TEMPLATE "/vm_file-XXXXXX"
170 
171 static int __init create_tmp_file(unsigned long long len)
172 {
173         int fd, err;
174         char zero;
175 
176         fd = make_tempfile(TEMPNAME_TEMPLATE);
177         if (fd < 0)
178                 exit(1);
179 
180         /*
181          * Seek to len - 1 because writing a character there will
182          * increase the file size by one byte, to the desired length.
183          */
184         if (lseek64(fd, len - 1, SEEK_SET) < 0) {
185                 perror("lseek64");
186                 exit(1);
187         }
188 
189         zero = 0;
190 
191         err = write(fd, &zero, 1);
192         if (err != 1) {
193                 perror("write");
194                 exit(1);
195         }
196 
197         return fd;
198 }
199 
200 int __init create_mem_file(unsigned long long len)
201 {
202         int err, fd;
203 
204         fd = create_tmp_file(len);
205 
206         err = os_set_exec_close(fd);
207         if (err < 0) {
208                 errno = -err;
209                 perror("exec_close");
210         }
211         return fd;
212 }
213 
214 void __init check_tmpexec(void)
215 {
216         void *addr;
217         int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
218 
219         addr = mmap(NULL, UM_KERN_PAGE_SIZE,
220                     PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
221         os_info("Checking PROT_EXEC mmap in %s...", tempdir);
222         if (addr == MAP_FAILED) {
223                 err = errno;
224                 os_warn("%s\n", strerror(err));
225                 close(fd);
226                 if (err == EPERM)
227                         os_warn("%s must be not mounted noexec\n", tempdir);
228                 exit(1);
229         }
230         os_info("OK\n");
231         munmap(addr, UM_KERN_PAGE_SIZE);
232 
233         close(fd);
234 }
235 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php