LCOV - code coverage report
Current view: top level - arch/um/os-Linux - util.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 22 58 37.9 %
Date: 2022-12-09 01:23:36 Functions: 5 11 45.5 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
       4             :  */
       5             : 
       6             : #include <stdarg.h>
       7             : #include <stdio.h>
       8             : #include <stdlib.h>
       9             : #include <unistd.h>
      10             : #include <errno.h>
      11             : #include <signal.h>
      12             : #include <string.h>
      13             : #include <termios.h>
      14             : #include <sys/wait.h>
      15             : #include <sys/mman.h>
      16             : #include <sys/utsname.h>
      17             : #include <init.h>
      18             : #include <os.h>
      19             : 
      20           2 : void stack_protections(unsigned long address)
      21             : {
      22           2 :         if (mprotect((void *) address, UM_THREAD_SIZE,
      23             :                     PROT_READ | PROT_WRITE | PROT_EXEC) < 0)
      24           0 :                 panic("protecting stack failed, errno = %d", errno);
      25           2 : }
      26             : 
      27           1 : int raw(int fd)
      28             : {
      29             :         struct termios tt;
      30             :         int err;
      31             : 
      32           1 :         CATCH_EINTR(err = tcgetattr(fd, &tt));
      33           1 :         if (err < 0)
      34           0 :                 return -errno;
      35             : 
      36           1 :         cfmakeraw(&tt);
      37             : 
      38           1 :         CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt));
      39           1 :         if (err < 0)
      40           0 :                 return -errno;
      41             : 
      42             :         /*
      43             :          * XXX tcsetattr could have applied only some changes
      44             :          * (and cfmakeraw() is a set of changes)
      45             :          */
      46             :         return 0;
      47             : }
      48             : 
      49           1 : void setup_machinename(char *machine_out)
      50             : {
      51             :         struct utsname host;
      52             : 
      53           1 :         uname(&host);
      54             : #ifdef UML_CONFIG_UML_X86
      55             : # ifndef UML_CONFIG_64BIT
      56             :         if (!strcmp(host.machine, "x86_64")) {
      57             :                 strcpy(machine_out, "i686");
      58             :                 return;
      59             :         }
      60             : # else
      61           1 :         if (!strcmp(host.machine, "i686")) {
      62           0 :                 strcpy(machine_out, "x86_64");
      63           0 :                 return;
      64             :         }
      65             : # endif
      66             : #endif
      67           1 :         strcpy(machine_out, host.machine);
      68             : }
      69             : 
      70           1 : void setup_hostinfo(char *buf, int len)
      71             : {
      72             :         struct utsname host;
      73             : 
      74           1 :         uname(&host);
      75           1 :         snprintf(buf, len, "%s %s %s %s %s", host.sysname, host.nodename,
      76             :                  host.release, host.version, host.machine);
      77           1 : }
      78             : 
      79             : /*
      80             :  * We cannot use glibc's abort(). It makes use of tgkill() which
      81             :  * has no effect within UML's kernel threads.
      82             :  * After that glibc would execute an invalid instruction to kill
      83             :  * the calling process and UML crashes with SIGSEGV.
      84             :  */
      85           0 : static inline void __attribute__ ((noreturn)) uml_abort(void)
      86             : {
      87             :         sigset_t sig;
      88             : 
      89           0 :         fflush(NULL);
      90             : 
      91           0 :         if (!sigemptyset(&sig) && !sigaddset(&sig, SIGABRT))
      92           0 :                 sigprocmask(SIG_UNBLOCK, &sig, 0);
      93             : 
      94             :         for (;;)
      95           0 :                 if (kill(getpid(), SIGABRT) < 0)
      96           0 :                         exit(127);
      97             : }
      98             : 
      99             : /*
     100             :  * UML helper threads must not handle SIGWINCH/INT/TERM
     101             :  */
     102           0 : void os_fix_helper_signals(void)
     103             : {
     104           0 :         signal(SIGWINCH, SIG_IGN);
     105           0 :         signal(SIGINT, SIG_DFL);
     106           0 :         signal(SIGTERM, SIG_DFL);
     107           0 : }
     108             : 
     109           0 : void os_dump_core(void)
     110             : {
     111             :         int pid;
     112             : 
     113           0 :         signal(SIGSEGV, SIG_DFL);
     114             : 
     115             :         /*
     116             :          * We are about to SIGTERM this entire process group to ensure that
     117             :          * nothing is around to run after the kernel exits.  The
     118             :          * kernel wants to abort, not die through SIGTERM, so we
     119             :          * ignore it here.
     120             :          */
     121             : 
     122           0 :         signal(SIGTERM, SIG_IGN);
     123           0 :         kill(0, SIGTERM);
     124             :         /*
     125             :          * Most of the other processes associated with this UML are
     126             :          * likely sTopped, so give them a SIGCONT so they see the
     127             :          * SIGTERM.
     128             :          */
     129           0 :         kill(0, SIGCONT);
     130             : 
     131             :         /*
     132             :          * Now, having sent signals to everyone but us, make sure they
     133             :          * die by ptrace.  Processes can survive what's been done to
     134             :          * them so far - the mechanism I understand is receiving a
     135             :          * SIGSEGV and segfaulting immediately upon return.  There is
     136             :          * always a SIGSEGV pending, and (I'm guessing) signals are
     137             :          * processed in numeric order so the SIGTERM (signal 15 vs
     138             :          * SIGSEGV being signal 11) is never handled.
     139             :          *
     140             :          * Run a waitpid loop until we get some kind of error.
     141             :          * Hopefully, it's ECHILD, but there's not a lot we can do if
     142             :          * it's something else.  Tell os_kill_ptraced_process not to
     143             :          * wait for the child to report its death because there's
     144             :          * nothing reasonable to do if that fails.
     145             :          */
     146             : 
     147           0 :         while ((pid = waitpid(-1, NULL, WNOHANG | __WALL)) > 0)
     148           0 :                 os_kill_ptraced_process(pid, 0);
     149             : 
     150           0 :         uml_abort();
     151             : }
     152             : 
     153           0 : void um_early_printk(const char *s, unsigned int n)
     154             : {
     155           0 :         printf("%.*s", n, s);
     156           0 : }
     157             : 
     158             : static int quiet_info;
     159             : 
     160           0 : static int __init quiet_cmd_param(char *str, int *add)
     161             : {
     162           0 :         quiet_info = 1;
     163           0 :         return 0;
     164             : }
     165             : 
     166             : __uml_setup("quiet", quiet_cmd_param,
     167             : "quiet\n"
     168             : "    Turns off information messages during boot.\n\n");
     169             : 
     170          55 : void os_info(const char *fmt, ...)
     171             : {
     172             :         va_list list;
     173             : 
     174          55 :         if (quiet_info)
     175           0 :                 return;
     176             : 
     177          55 :         va_start(list, fmt);
     178          55 :         vfprintf(stderr, fmt, list);
     179          55 :         va_end(list);
     180             : }
     181             : 
     182           0 : void os_warn(const char *fmt, ...)
     183             : {
     184             :         va_list list;
     185             : 
     186           0 :         va_start(list, fmt);
     187           0 :         vfprintf(stderr, fmt, list);
     188           0 :         va_end(list);
     189           0 : }

Generated by: LCOV version 1.14