LCOV - code coverage report
Current view: top level - arch/um/os-Linux - util.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 24 60 40.0 %
Date: 2023-03-27 20:00:47 Functions: 6 12 50.0 %

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

Generated by: LCOV version 1.14