1 /* 2 * os-posix.c 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * Copyright (c) 2010 Red Hat, Inc. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 * THE SOFTWARE. 24 */ 25 26 #include <unistd.h> 27 #include <fcntl.h> 28 #include <signal.h> 29 #include <sys/types.h> 30 #include <sys/wait.h> 31 /*needed for MAP_POPULATE before including qemu-options.h */ 32 #include <sys/mman.h> 33 #include <pwd.h> 34 #include <grp.h> 35 #include <libgen.h> 36 37 /* Needed early for CONFIG_BSD etc. */ 38 #include "config-host.h" 39 #include "sysemu.h" 40 #include "net/slirp.h" 41 #include "qemu-options.h" 42 43 #ifdef CONFIG_LINUX 44 #include <sys/prctl.h> 45 #include <sys/syscall.h> 46 #endif 47 48 #ifdef CONFIG_EVENTFD 49 #include <sys/eventfd.h> 50 #endif 51 52 static struct passwd *user_pwd; 53 static const char *chroot_dir; 54 static int daemonize; 55 static int fds[2]; 56 57 void os_setup_early_signal_handling(void) 58 { 59 struct sigaction act; 60 sigfillset(&act.sa_mask); 61 act.sa_flags = 0; 62 act.sa_handler = SIG_IGN; 63 sigaction(SIGPIPE, &act, NULL); 64 } 65 66 static void termsig_handler(int signal, siginfo_t *info, void *c) 67 { 68 qemu_system_killed(info->si_signo, info->si_pid); 69 } 70 71 void os_setup_signal_handling(void) 72 { 73 struct sigaction act; 74 75 memset(&act, 0, sizeof(act)); 76 act.sa_sigaction = termsig_handler; 77 act.sa_flags = SA_SIGINFO; 78 sigaction(SIGINT, &act, NULL); 79 sigaction(SIGHUP, &act, NULL); 80 sigaction(SIGTERM, &act, NULL); 81 } 82 83 /* Find a likely location for support files using the location of the binary. 84 For installed binaries this will be "$bindir/../share/qemu". When 85 running from the build tree this will be "$bindir/../pc-bios". */ 86 #define SHARE_SUFFIX "/share/qemu" 87 #define BUILD_SUFFIX "/pc-bios" 88 char *os_find_datadir(const char *argv0) 89 { 90 char *dir; 91 char *p = NULL; 92 char *res; 93 char buf[PATH_MAX]; 94 size_t max_len; 95 96 #if defined(__linux__) 97 { 98 int len; 99 len = readlink("/proc/self/exe", buf, sizeof(buf) - 1); 100 if (len > 0) { 101 buf[len] = 0; 102 p = buf; 103 } 104 } 105 #elif defined(__FreeBSD__) 106 { 107 static int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; 108 size_t len = sizeof(buf) - 1; 109 110 *buf = '\0'; 111 if (!sysctl(mib, ARRAY_SIZE(mib), buf, &len, NULL, 0) && 112 *buf) { 113 buf[sizeof(buf) - 1] = '\0'; 114 p = buf; 115 } 116 } 117 #endif 118 /* If we don't have any way of figuring out the actual executable 119 location then try argv[0]. */ 120 if (!p) { 121 p = realpath(argv0, buf); 122 if (!p) { 123 return NULL; 124 } 125 } 126 dir = dirname(p); 127 dir = dirname(dir); 128 129 max_len = strlen(dir) + 130 MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1; 131 res = g_malloc0(max_len); 132 snprintf(res, max_len, "%s%s", dir, SHARE_SUFFIX); 133 if (access(res, R_OK)) { 134 snprintf(res, max_len, "%s%s", dir, BUILD_SUFFIX); 135 if (access(res, R_OK)) { 136 g_free(res); 137 res = NULL; 138 } 139 } 140 141 return res; 142 } 143 #undef SHARE_SUFFIX 144 #undef BUILD_SUFFIX 145 146 void os_set_proc_name(const char *s) 147 { 148 #if defined(PR_SET_NAME) 149 char name[16]; 150 if (!s) 151 return; 152 name[sizeof(name) - 1] = 0; 153 strncpy(name, s, sizeof(name)); 154 /* Could rewrite argv[0] too, but that's a bit more complicated. 155 This simple way is enough for `top'. */ 156 if (prctl(PR_SET_NAME, name)) { 157 perror("unable to change process name"); 158 exit(1); 159 } 160 #else 161 fprintf(stderr, "Change of process name not supported by your OS\n"); 162 exit(1); 163 #endif 164 } 165 166 /* 167 * Parse OS specific command line options. 168 * return 0 if option handled, -1 otherwise 169 */ 170 void os_parse_cmd_args(int index, const char *optarg) 171 { 172 switch (index) { 173 #ifdef CONFIG_SLIRP 174 case QEMU_OPTION_smb: 175 if (net_slirp_smb(optarg) < 0) 176 exit(1); 177 break; 178 #endif 179 case QEMU_OPTION_runas: 180 user_pwd = getpwnam(optarg); 181 if (!user_pwd) { 182 fprintf(stderr, "User \"%s\" doesn't exist\n", optarg); 183 exit(1); 184 } 185 break; 186 case QEMU_OPTION_chroot: 187 chroot_dir = optarg; 188 break; 189 case QEMU_OPTION_daemonize: 190 daemonize = 1; 191 break; 192 } 193 return; 194 } 195 196 static void change_process_uid(void) 197 { 198 if (user_pwd) { 199 if (setgid(user_pwd->pw_gid) < 0) { 200 fprintf(stderr, "Failed to setgid(%d)\n", user_pwd->pw_gid); 201 exit(1); 202 } 203 if (initgroups(user_pwd->pw_name, user_pwd->pw_gid) < 0) { 204 fprintf(stderr, "Failed to initgroups(\"%s\", %d)\n", 205 user_pwd->pw_name, user_pwd->pw_gid); 206 exit(1); 207 } 208 if (setuid(user_pwd->pw_uid) < 0) { 209 fprintf(stderr, "Failed to setuid(%d)\n", user_pwd->pw_uid); 210 exit(1); 211 } 212 if (setuid(0) != -1) { 213 fprintf(stderr, "Dropping privileges failed\n"); 214 exit(1); 215 } 216 } 217 } 218 219 static void change_root(void) 220 { 221 if (chroot_dir) { 222 if (chroot(chroot_dir) < 0) { 223 fprintf(stderr, "chroot failed\n"); 224 exit(1); 225 } 226 if (chdir("/")) { 227 perror("not able to chdir to /"); 228 exit(1); 229 } 230 } 231 232 } 233 234 void os_daemonize(void) 235 { 236 if (daemonize) { 237 pid_t pid; 238 239 if (pipe(fds) == -1) 240 exit(1); 241 242 pid = fork(); 243 if (pid > 0) { 244 uint8_t status; 245 ssize_t len; 246 247 close(fds[1]); 248 249 again: 250 len = read(fds[0], &status, 1); 251 if (len == -1 && (errno == EINTR)) 252 goto again; 253 254 if (len != 1) 255 exit(1); 256 else if (status == 1) { 257 fprintf(stderr, "Could not acquire pidfile: %s\n", strerror(errno)); 258 exit(1); 259 } else 260 exit(0); 261 } else if (pid < 0) 262 exit(1); 263 264 close(fds[0]); 265 qemu_set_cloexec(fds[1]); 266 267 setsid(); 268 269 pid = fork(); 270 if (pid > 0) 271 exit(0); 272 else if (pid < 0) 273 exit(1); 274 275 umask(027); 276 277 signal(SIGTSTP, SIG_IGN); 278 signal(SIGTTOU, SIG_IGN); 279 signal(SIGTTIN, SIG_IGN); 280 } 281 } 282 283 void os_setup_post(void) 284 { 285 int fd = 0; 286 287 if (daemonize) { 288 uint8_t status = 0; 289 ssize_t len; 290 291 again1: 292 len = write(fds[1], &status, 1); 293 if (len == -1 && (errno == EINTR)) 294 goto again1; 295 296 if (len != 1) 297 exit(1); 298 299 if (chdir("/")) { 300 perror("not able to chdir to /"); 301 exit(1); 302 } 303 TFR(fd = qemu_open("/dev/null", O_RDWR)); 304 if (fd == -1) 305 exit(1); 306 } 307 308 change_root(); 309 change_process_uid(); 310 311 if (daemonize) { 312 dup2(fd, 0); 313 dup2(fd, 1); 314 dup2(fd, 2); 315 316 close(fd); 317 } 318 } 319 320 void os_pidfile_error(void) 321 { 322 if (daemonize) { 323 uint8_t status = 1; 324 if (write(fds[1], &status, 1) != 1) { 325 perror("daemonize. Writing to pipe\n"); 326 } 327 } else 328 fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno)); 329 } 330 331 void os_set_line_buffering(void) 332 { 333 setvbuf(stdout, NULL, _IOLBF, 0); 334 } 335 336 /* 337 * Creates an eventfd that looks like a pipe and has EFD_CLOEXEC set. 338 */ 339 int qemu_eventfd(int fds[2]) 340 { 341 #ifdef CONFIG_EVENTFD 342 int ret; 343 344 ret = eventfd(0, 0); 345 if (ret >= 0) { 346 fds[0] = ret; 347 qemu_set_cloexec(ret); 348 if ((fds[1] = dup(ret)) == -1) { 349 close(ret); 350 return -1; 351 } 352 qemu_set_cloexec(fds[1]); 353 return 0; 354 } 355 356 if (errno != ENOSYS) { 357 return -1; 358 } 359 #endif 360 361 return qemu_pipe(fds); 362 } 363 364 int qemu_create_pidfile(const char *filename) 365 { 366 char buffer[128]; 367 int len; 368 int fd; 369 370 fd = qemu_open(filename, O_RDWR | O_CREAT, 0600); 371 if (fd == -1) { 372 return -1; 373 } 374 if (lockf(fd, F_TLOCK, 0) == -1) { 375 return -1; 376 } 377 len = snprintf(buffer, sizeof(buffer), FMT_pid "\n", getpid()); 378 if (write(fd, buffer, len) != len) { 379 return -1; 380 } 381 382 return 0; 383 } 384 385 int qemu_get_thread_id(void) 386 { 387 #if defined (__linux__) 388 return syscall(SYS_gettid); 389 #else 390 return getpid(); 391 #endif 392 } 393