Skip to content

Commit

Permalink
[PATCH] uml: fix error output during early boot
Browse files Browse the repository at this point in the history
The startup code panics a lot if anything goes wrong early on.  This is wrong
for several reasons, like the kernel isn't running, so you can't really be
calling into it yet, but the harm comes from useful error messages being
trapped in the printk ring where no one will ever see them.

This patch changes these panics to perror and printf in wrappers which also
exit.  Normal, informational, prints are also wrapped so that fflush(stdout)
is called after each one.  This is so the output appears in the correct
sequence in the event of an error.

Signed-off-by: Jeff Dike <[email protected]>
Cc: Paolo 'Blaisorblade' Giarrusso <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
cfd-36 authored and Linus Torvalds committed Feb 11, 2007
1 parent 9683da9 commit 3a150e1
Showing 1 changed file with 92 additions and 62 deletions.
154 changes: 92 additions & 62 deletions arch/um/os-Linux/start_up.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,34 @@ static int ptrace_child(void *arg)
_exit(ret);
}

static void fatal_perror(char *str)
{
perror(str);
exit(1);
}

static void fatal(char *fmt, ...)
{
va_list list;

va_start(list, fmt);
vprintf(fmt, list);
va_end(list);
fflush(stdout);

exit(1);
}

static void non_fatal(char *fmt, ...)
{
va_list list;

va_start(list, fmt);
vprintf(fmt, list);
va_end(list);
fflush(stdout);
}

static int start_ptraced_child(void **stack_out)
{
void *stack;
Expand All @@ -82,16 +110,16 @@ static int start_ptraced_child(void **stack_out)
stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if(stack == MAP_FAILED)
panic("check_ptrace : mmap failed, errno = %d", errno);
fatal_perror("check_ptrace : mmap failed");
sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *);
pid = clone(ptrace_child, (void *) sp, SIGCHLD, NULL);
if(pid < 0)
panic("start_ptraced_child : clone failed, errno = %d", errno);
fatal_perror("start_ptraced_child : clone failed");
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
if(n < 0)
panic("check_ptrace : clone failed, errno = %d", errno);
fatal_perror("check_ptrace : clone failed");
if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP))
panic("check_ptrace : expected SIGSTOP, got status = %d",
fatal("check_ptrace : expected SIGSTOP, got status = %d",
status);

*stack_out = stack;
Expand All @@ -105,31 +133,30 @@ static int start_ptraced_child(void **stack_out)
* must work anyway!
*/
static int stop_ptraced_child(int pid, void *stack, int exitcode,
int mustpanic)
int mustexit)
{
int status, n, ret = 0;

if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
panic("check_ptrace : ptrace failed, errno = %d", errno);
fatal_perror("stop_ptraced_child : ptrace failed");
CATCH_EINTR(n = waitpid(pid, &status, 0));
if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) {
int exit_with = WEXITSTATUS(status);
if (exit_with == 2)
printf("check_ptrace : child exited with status 2. "
"Serious trouble happening! Try updating your "
"host skas patch!\nDisabling SYSEMU support.");
printf("check_ptrace : child exited with exitcode %d, while "
"expecting %d; status 0x%x", exit_with,
exitcode, status);
if (mustpanic)
panic("\n");
else
printf("\n");
non_fatal("check_ptrace : child exited with status 2. "
"Serious trouble happening! Try updating "
"your host skas patch!\nDisabling SYSEMU "
"support.");
non_fatal("check_ptrace : child exited with exitcode %d, while "
"expecting %d; status 0x%x\n", exit_with,
exitcode, status);
if (mustexit)
exit(1);
ret = -1;
}

if(munmap(stack, PAGE_SIZE) < 0)
panic("check_ptrace : munmap failed, errno = %d", errno);
fatal_perror("check_ptrace : munmap failed");
return ret;
}

Expand Down Expand Up @@ -184,7 +211,7 @@ static void __init check_sysemu(void)
void *stack;
int pid, n, status, count=0;

printf("Checking syscall emulation patch for ptrace...");
non_fatal("Checking syscall emulation patch for ptrace...");
sysemu_supported = 0;
pid = start_ptraced_child(&stack);

Expand All @@ -193,61 +220,61 @@ static void __init check_sysemu(void)

CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
if (n < 0)
panic("check_sysemu : wait failed, errno = %d", errno);
fatal_perror("check_sysemu : wait failed");
if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
panic("check_sysemu : expected SIGTRAP, "
"got status = %d", status);
fatal("check_sysemu : expected SIGTRAP, got status = %d",
status);

n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
os_getpid());
if(n < 0)
panic("check_sysemu : failed to modify system "
"call return, errno = %d", errno);
fatal_perror("check_sysemu : failed to modify system call "
"return");

if (stop_ptraced_child(pid, stack, 0, 0) < 0)
goto fail_stopped;

sysemu_supported = 1;
printf("OK\n");
non_fatal("OK\n");
set_using_sysemu(!force_sysemu_disabled);

printf("Checking advanced syscall emulation patch for ptrace...");
non_fatal("Checking advanced syscall emulation patch for ptrace...");
pid = start_ptraced_child(&stack);

if(ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
(void *) PTRACE_O_TRACESYSGOOD) < 0)
panic("check_ptrace: PTRACE_OLDSETOPTIONS failed, errno = %d",
errno);
if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
(void *) PTRACE_O_TRACESYSGOOD) < 0))
fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed");

while(1){
count++;
if(ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0)
goto fail;
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
if(n < 0)
panic("check_ptrace : wait failed, errno = %d", errno);
fatal_perror("check_ptrace : wait failed");

if(WIFSTOPPED(status) && (WSTOPSIG(status) == (SIGTRAP|0x80))){
if (!count)
panic("check_ptrace : SYSEMU_SINGLESTEP "
fatal("check_ptrace : SYSEMU_SINGLESTEP "
"doesn't singlestep");
n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET,
os_getpid());
if(n < 0)
panic("check_sysemu : failed to modify system "
"call return, errno = %d", errno);
fatal_perror("check_sysemu : failed to modify "
"system call return");
break;
}
else if(WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP))
count++;
else
panic("check_ptrace : expected SIGTRAP or "
"(SIGTRAP|0x80), got status = %d", status);
fatal("check_ptrace : expected SIGTRAP or "
"(SIGTRAP | 0x80), got status = %d", status);
}
if (stop_ptraced_child(pid, stack, 0, 0) < 0)
goto fail_stopped;

sysemu_supported = 2;
printf("OK\n");
non_fatal("OK\n");

if ( !force_sysemu_disabled )
set_using_sysemu(sysemu_supported);
Expand All @@ -256,44 +283,47 @@ static void __init check_sysemu(void)
fail:
stop_ptraced_child(pid, stack, 1, 0);
fail_stopped:
printf("missing\n");
non_fatal("missing\n");
}

static void __init check_ptrace(void)
{
void *stack;
int pid, syscall, n, status;

printf("Checking that ptrace can change system call numbers...");
non_fatal("Checking that ptrace can change system call numbers...");
pid = start_ptraced_child(&stack);

if(ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
panic("check_ptrace: PTRACE_OLDSETOPTIONS failed, errno = %d", errno);
if((ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
(void *) PTRACE_O_TRACESYSGOOD) < 0))
fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed");

while(1){
if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
panic("check_ptrace : ptrace failed, errno = %d",
errno);
fatal_perror("check_ptrace : ptrace failed");

CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
if(n < 0)
panic("check_ptrace : wait failed, errno = %d", errno);
if(!WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP|0x80)))
panic("check_ptrace : expected (SIGTRAP|0x80), "
"got status = %d", status);
fatal_perror("check_ptrace : wait failed");

if(!WIFSTOPPED(status) ||
(WSTOPSIG(status) != (SIGTRAP | 0x80)))
fatal("check_ptrace : expected (SIGTRAP|0x80), "
"got status = %d", status);

syscall = ptrace(PTRACE_PEEKUSR, pid, PT_SYSCALL_NR_OFFSET,
0);
if(syscall == __NR_getpid){
n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET,
__NR_getppid);
if(n < 0)
panic("check_ptrace : failed to modify system "
"call, errno = %d", errno);
fatal_perror("check_ptrace : failed to modify "
"system call");
break;
}
}
stop_ptraced_child(pid, stack, 0, 1);
printf("OK\n");
non_fatal("OK\n");
check_sysemu();
}

Expand Down Expand Up @@ -352,22 +382,22 @@ static inline void check_skas3_ptrace_faultinfo(void)
void *stack;
int pid, n;

printf(" - PTRACE_FAULTINFO...");
non_fatal(" - PTRACE_FAULTINFO...");
pid = start_ptraced_child(&stack);

n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi);
if (n < 0) {
ptrace_faultinfo = 0;
if(errno == EIO)
printf("not found\n");
non_fatal("not found\n");
else
perror("not found");
}
else {
if (!ptrace_faultinfo)
printf("found but disabled on command line\n");
non_fatal("found but disabled on command line\n");
else
printf("found\n");
non_fatal("found\n");
}

init_registers(pid);
Expand All @@ -385,23 +415,23 @@ static inline void check_skas3_ptrace_ldt(void)
.ptr = ldtbuf,
.bytecount = sizeof(ldtbuf)};

printf(" - PTRACE_LDT...");
non_fatal(" - PTRACE_LDT...");
pid = start_ptraced_child(&stack);

n = ptrace(PTRACE_LDT, pid, 0, (unsigned long) &ldt_op);
if (n < 0) {
if(errno == EIO)
printf("not found\n");
non_fatal("not found\n");
else {
perror("not found");
}
ptrace_ldt = 0;
}
else {
if(ptrace_ldt)
printf("found\n");
non_fatal("found\n");
else
printf("found, but use is disabled\n");
non_fatal("found, but use is disabled\n");
}

stop_ptraced_child(pid, stack, 1, 1);
Expand All @@ -416,22 +446,22 @@ static inline void check_skas3_ptrace_ldt(void)

static inline void check_skas3_proc_mm(void)
{
printf(" - /proc/mm...");
non_fatal(" - /proc/mm...");
if (access("/proc/mm", W_OK) < 0) {
proc_mm = 0;
printf("not found\n");
perror("not found");
}
else {
if (!proc_mm)
printf("found but disabled on command line\n");
non_fatal("found but disabled on command line\n");
else
printf("found\n");
non_fatal("found\n");
}
}

int can_do_skas(void)
{
printf("Checking for the skas3 patch in the host:\n");
non_fatal("Checking for the skas3 patch in the host:\n");

check_skas3_proc_mm();
check_skas3_ptrace_faultinfo();
Expand Down

0 comments on commit 3a150e1

Please sign in to comment.