util.c 3.2 KB
Newer Older
1
/*
J
Jeff Dike 已提交
2
 * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
L
Linus Torvalds 已提交
3 4 5 6 7
 * Licensed under the GPL
 */

#include <stdio.h>
#include <stdlib.h>
R
Richard Weinberger 已提交
8
#include <unistd.h>
L
Linus Torvalds 已提交
9
#include <errno.h>
J
Jeff Dike 已提交
10
#include <signal.h>
L
Linus Torvalds 已提交
11
#include <string.h>
J
Jeff Dike 已提交
12 13 14 15
#include <termios.h>
#include <wait.h>
#include <sys/mman.h>
#include <sys/utsname.h>
J
Jeff Dike 已提交
16
#include "kern_constants.h"
J
Jeff Dike 已提交
17 18
#include "os.h"
#include "user.h"
L
Linus Torvalds 已提交
19 20 21

void stack_protections(unsigned long address)
{
J
Jeff Dike 已提交
22
	if (mprotect((void *) address, UM_THREAD_SIZE,
J
Jeff Dike 已提交
23
		    PROT_READ | PROT_WRITE | PROT_EXEC) < 0)
L
Linus Torvalds 已提交
24 25 26 27 28 29 30 31 32
		panic("protecting stack failed, errno = %d", errno);
}

int raw(int fd)
{
	struct termios tt;
	int err;

	CATCH_EINTR(err = tcgetattr(fd, &tt));
J
Jeff Dike 已提交
33
	if (err < 0)
34
		return -errno;
L
Linus Torvalds 已提交
35 36 37

	cfmakeraw(&tt);

38
	CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt));
J
Jeff Dike 已提交
39
	if (err < 0)
40
		return -errno;
L
Linus Torvalds 已提交
41

J
Jeff Dike 已提交
42 43 44 45
	/*
	 * XXX tcsetattr could have applied only some changes
	 * (and cfmakeraw() is a set of changes)
	 */
J
Jeff Dike 已提交
46
	return 0;
L
Linus Torvalds 已提交
47 48 49 50 51 52 53
}

void setup_machinename(char *machine_out)
{
	struct utsname host;

	uname(&host);
54 55
#ifdef UML_CONFIG_UML_X86
# ifndef UML_CONFIG_64BIT
56 57 58 59
	if (!strcmp(host.machine, "x86_64")) {
		strcpy(machine_out, "i686");
		return;
	}
60 61 62 63 64 65
# else
	if (!strcmp(host.machine, "i686")) {
		strcpy(machine_out, "x86_64");
		return;
	}
# endif
66
#endif
L
Linus Torvalds 已提交
67 68 69
	strcpy(machine_out, host.machine);
}

J
Jeff Dike 已提交
70
void setup_hostinfo(char *buf, int len)
L
Linus Torvalds 已提交
71 72 73 74
{
	struct utsname host;

	uname(&host);
J
Jeff Dike 已提交
75 76
	snprintf(buf, len, "%s %s %s %s %s", host.sysname, host.nodename,
		 host.release, host.version, host.machine);
L
Linus Torvalds 已提交
77 78
}

R
Richard Weinberger 已提交
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
/*
 * We cannot use glibc's abort(). It makes use of tgkill() which
 * has no effect within UML's kernel threads.
 * After that glibc would execute an invalid instruction to kill
 * the calling process and UML crashes with SIGSEGV.
 */
static inline void __attribute__ ((noreturn)) uml_abort(void)
{
	sigset_t sig;

	fflush(NULL);

	if (!sigemptyset(&sig) && !sigaddset(&sig, SIGABRT))
		sigprocmask(SIG_UNBLOCK, &sig, 0);

	for (;;)
		if (kill(getpid(), SIGABRT) < 0)
			exit(127);
}

J
Jeff Dike 已提交
99 100
void os_dump_core(void)
{
101 102
	int pid;

J
Jeff Dike 已提交
103
	signal(SIGSEGV, SIG_DFL);
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136

	/*
	 * We are about to SIGTERM this entire process group to ensure that
	 * nothing is around to run after the kernel exits.  The
	 * kernel wants to abort, not die through SIGTERM, so we
	 * ignore it here.
	 */

	signal(SIGTERM, SIG_IGN);
	kill(0, SIGTERM);
	/*
	 * Most of the other processes associated with this UML are
	 * likely sTopped, so give them a SIGCONT so they see the
	 * SIGTERM.
	 */
	kill(0, SIGCONT);

	/*
	 * Now, having sent signals to everyone but us, make sure they
	 * die by ptrace.  Processes can survive what's been done to
	 * them so far - the mechanism I understand is receiving a
	 * SIGSEGV and segfaulting immediately upon return.  There is
	 * always a SIGSEGV pending, and (I'm guessing) signals are
	 * processed in numeric order so the SIGTERM (signal 15 vs
	 * SIGSEGV being signal 11) is never handled.
	 *
	 * Run a waitpid loop until we get some kind of error.
	 * Hopefully, it's ECHILD, but there's not a lot we can do if
	 * it's something else.  Tell os_kill_ptraced_process not to
	 * wait for the child to report its death because there's
	 * nothing reasonable to do if that fails.
	 */

137
	while ((pid = waitpid(-1, NULL, WNOHANG | __WALL)) > 0)
138 139
		os_kill_ptraced_process(pid, 0);

R
Richard Weinberger 已提交
140
	uml_abort();
J
Jeff Dike 已提交
141
}