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>
16
#include <os.h>
L
Linus Torvalds 已提交
17 18 19

void stack_protections(unsigned long address)
{
J
Jeff Dike 已提交
20
	if (mprotect((void *) address, UM_THREAD_SIZE,
J
Jeff Dike 已提交
21
		    PROT_READ | PROT_WRITE | PROT_EXEC) < 0)
L
Linus Torvalds 已提交
22 23 24 25 26 27 28 29 30
		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 已提交
31
	if (err < 0)
32
		return -errno;
L
Linus Torvalds 已提交
33 34 35

	cfmakeraw(&tt);

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

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

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

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

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

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

R
Richard Weinberger 已提交
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
/*
 * 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 已提交
97 98
void os_dump_core(void)
{
99 100
	int pid;

J
Jeff Dike 已提交
101
	signal(SIGSEGV, SIG_DFL);
102 103 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

	/*
	 * 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.
	 */

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

R
Richard Weinberger 已提交
138
	uml_abort();
J
Jeff Dike 已提交
139
}
R
Richard Weinberger 已提交
140 141 142 143 144

void um_early_printk(const char *s, unsigned int n)
{
	printf("%.*s", n, s);
}