0001
0002
0003
0004
0005
0006 #include <stdio.h>
0007 #include <stddef.h>
0008 #include <stdlib.h>
0009 #include <unistd.h>
0010 #include <errno.h>
0011 #include <fcntl.h>
0012 #include <string.h>
0013 #include <sys/stat.h>
0014 #include <sys/mman.h>
0015 #include <sys/vfs.h>
0016 #include <linux/magic.h>
0017 #include <init.h>
0018 #include <os.h>
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 void kasan_map_memory(void *start, size_t len)
0029 {
0030 if (mmap(start,
0031 len,
0032 PROT_READ|PROT_WRITE,
0033 MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE|MAP_NORESERVE,
0034 -1,
0035 0) == MAP_FAILED) {
0036 os_info("Couldn't allocate shadow memory: %s\n.",
0037 strerror(errno));
0038 exit(1);
0039 }
0040 }
0041
0042
0043 static char *tempdir = NULL;
0044
0045
0046 static int __init check_tmpfs(const char *dir)
0047 {
0048 struct statfs st;
0049
0050 os_info("Checking if %s is on tmpfs...", dir);
0051 if (statfs(dir, &st) < 0) {
0052 os_info("%s\n", strerror(errno));
0053 } else if (st.f_type != TMPFS_MAGIC) {
0054 os_info("no\n");
0055 } else {
0056 os_info("OK\n");
0057 return 0;
0058 }
0059 return -1;
0060 }
0061
0062
0063
0064
0065
0066
0067
0068
0069 static char * __init choose_tempdir(void)
0070 {
0071 static const char * const vars[] = {
0072 "TMPDIR",
0073 "TMP",
0074 "TEMP",
0075 NULL
0076 };
0077 static const char fallback_dir[] = "/tmp";
0078 static const char * const tmpfs_dirs[] = {
0079 "/dev/shm",
0080 fallback_dir,
0081 NULL
0082 };
0083 int i;
0084 const char *dir;
0085
0086 os_info("Checking environment variables for a tempdir...");
0087 for (i = 0; vars[i]; i++) {
0088 dir = getenv(vars[i]);
0089 if ((dir != NULL) && (*dir != '\0')) {
0090 os_info("%s\n", dir);
0091 if (check_tmpfs(dir) >= 0)
0092 goto done;
0093 else
0094 goto warn;
0095 }
0096 }
0097 os_info("none found\n");
0098
0099 for (i = 0; tmpfs_dirs[i]; i++) {
0100 dir = tmpfs_dirs[i];
0101 if (check_tmpfs(dir) >= 0)
0102 goto done;
0103 }
0104
0105 dir = fallback_dir;
0106 warn:
0107 os_warn("Warning: tempdir %s is not on tmpfs\n", dir);
0108 done:
0109
0110 return strdup(dir);
0111 }
0112
0113
0114
0115
0116
0117 static int __init make_tempfile(const char *template)
0118 {
0119 char *tempname;
0120 int fd;
0121
0122 if (tempdir == NULL) {
0123 tempdir = choose_tempdir();
0124 if (tempdir == NULL) {
0125 os_warn("Failed to choose tempdir: %s\n",
0126 strerror(errno));
0127 return -1;
0128 }
0129 }
0130
0131 #ifdef O_TMPFILE
0132 fd = open(tempdir, O_CLOEXEC | O_RDWR | O_EXCL | O_TMPFILE, 0700);
0133
0134
0135
0136
0137 if (fd != -1 || (errno != EINVAL && errno != EISDIR &&
0138 errno != EOPNOTSUPP))
0139 return fd;
0140 #endif
0141
0142 tempname = malloc(strlen(tempdir) + strlen(template) + 1);
0143 if (tempname == NULL)
0144 return -1;
0145
0146 strcpy(tempname, tempdir);
0147 strcat(tempname, template);
0148 fd = mkstemp(tempname);
0149 if (fd < 0) {
0150 os_warn("open - cannot create %s: %s\n", tempname,
0151 strerror(errno));
0152 goto out;
0153 }
0154 if (unlink(tempname) < 0) {
0155 perror("unlink");
0156 goto close;
0157 }
0158 free(tempname);
0159 return fd;
0160 close:
0161 close(fd);
0162 out:
0163 free(tempname);
0164 return -1;
0165 }
0166
0167 #define TEMPNAME_TEMPLATE "/vm_file-XXXXXX"
0168
0169 static int __init create_tmp_file(unsigned long long len)
0170 {
0171 int fd, err;
0172 char zero;
0173
0174 fd = make_tempfile(TEMPNAME_TEMPLATE);
0175 if (fd < 0)
0176 exit(1);
0177
0178
0179
0180
0181
0182 if (lseek64(fd, len - 1, SEEK_SET) < 0) {
0183 perror("lseek64");
0184 exit(1);
0185 }
0186
0187 zero = 0;
0188
0189 err = write(fd, &zero, 1);
0190 if (err != 1) {
0191 perror("write");
0192 exit(1);
0193 }
0194
0195 return fd;
0196 }
0197
0198 int __init create_mem_file(unsigned long long len)
0199 {
0200 int err, fd;
0201
0202 fd = create_tmp_file(len);
0203
0204 err = os_set_exec_close(fd);
0205 if (err < 0) {
0206 errno = -err;
0207 perror("exec_close");
0208 }
0209 return fd;
0210 }
0211
0212 void __init check_tmpexec(void)
0213 {
0214 void *addr;
0215 int err, fd = create_tmp_file(UM_KERN_PAGE_SIZE);
0216
0217 addr = mmap(NULL, UM_KERN_PAGE_SIZE,
0218 PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
0219 os_info("Checking PROT_EXEC mmap in %s...", tempdir);
0220 if (addr == MAP_FAILED) {
0221 err = errno;
0222 os_warn("%s\n", strerror(err));
0223 close(fd);
0224 if (err == EPERM)
0225 os_warn("%s must be not mounted noexec\n", tempdir);
0226 exit(1);
0227 }
0228 os_info("OK\n");
0229 munmap(addr, UM_KERN_PAGE_SIZE);
0230
0231 close(fd);
0232 }