LCOV - code coverage report
Current view: top level - arch/x86/um - syscalls_64.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 2 27 7.4 %
Date: 2023-08-24 13:40:31 Functions: 1 4 25.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright (C) 2003 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
       3             :  * Copyright 2003 PathScale, Inc.
       4             :  *
       5             :  * Licensed under the GPL
       6             :  */
       7             : 
       8             : #include <linux/sched.h>
       9             : #include <linux/sched/mm.h>
      10             : #include <linux/syscalls.h>
      11             : #include <linux/uaccess.h>
      12             : #include <asm/prctl.h> /* XXX This should get the constants from libc */
      13             : #include <registers.h>
      14             : #include <os.h>
      15             : 
      16           0 : long arch_prctl(struct task_struct *task, int option,
      17             :                 unsigned long __user *arg2)
      18             : {
      19           0 :         unsigned long *ptr = arg2, tmp;
      20             :         long ret;
      21           0 :         int pid = task->mm->context.id.u.pid;
      22             : 
      23             :         /*
      24             :          * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to
      25             :          * be safe), we need to call arch_prctl on the host because
      26             :          * setting %fs may result in something else happening (like a
      27             :          * GDT or thread.fs being set instead).  So, we let the host
      28             :          * fiddle the registers and thread struct and restore the
      29             :          * registers afterwards.
      30             :          *
      31             :          * So, the saved registers are stored to the process (this
      32             :          * needed because a stub may have been the last thing to run),
      33             :          * arch_prctl is run on the host, then the registers are read
      34             :          * back.
      35             :          */
      36           0 :         switch (option) {
      37             :         case ARCH_SET_FS:
      38             :         case ARCH_SET_GS:
      39           0 :                 ret = restore_pid_registers(pid, &current->thread.regs.regs);
      40           0 :                 if (ret)
      41             :                         return ret;
      42             :                 break;
      43             :         case ARCH_GET_FS:
      44             :         case ARCH_GET_GS:
      45             :                 /*
      46             :                  * With these two, we read to a local pointer and
      47             :                  * put_user it to the userspace pointer that we were
      48             :                  * given.  If addr isn't valid (because it hasn't been
      49             :                  * faulted in or is just bogus), we want put_user to
      50             :                  * fault it in (or return -EFAULT) instead of having
      51             :                  * the host return -EFAULT.
      52             :                  */
      53           0 :                 ptr = &tmp;
      54             :         }
      55             : 
      56           0 :         ret = os_arch_prctl(pid, option, ptr);
      57           0 :         if (ret)
      58             :                 return ret;
      59             : 
      60           0 :         switch (option) {
      61             :         case ARCH_SET_FS:
      62           0 :                 current->thread.arch.fs = (unsigned long) ptr;
      63           0 :                 ret = save_registers(pid, &current->thread.regs.regs);
      64           0 :                 break;
      65             :         case ARCH_SET_GS:
      66           0 :                 ret = save_registers(pid, &current->thread.regs.regs);
      67           0 :                 break;
      68             :         case ARCH_GET_FS:
      69           0 :                 ret = put_user(tmp, arg2);
      70           0 :                 break;
      71             :         case ARCH_GET_GS:
      72           0 :                 ret = put_user(tmp, arg2);
      73           0 :                 break;
      74             :         }
      75             : 
      76             :         return ret;
      77             : }
      78             : 
      79           0 : SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2)
      80             : {
      81           0 :         return arch_prctl(current, option, (unsigned long __user *) arg2);
      82             : }
      83             : 
      84         856 : void arch_switch_to(struct task_struct *to)
      85             : {
      86         856 :         if ((to->thread.arch.fs == 0) || (to->mm == NULL))
      87             :                 return;
      88             : 
      89           0 :         arch_prctl(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs);
      90             : }
      91             : 
      92           0 : SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,
      93             :                 unsigned long, prot, unsigned long, flags,
      94             :                 unsigned long, fd, unsigned long, off)
      95             : {
      96           0 :         if (off & ~PAGE_MASK)
      97             :                 return -EINVAL;
      98             : 
      99           0 :         return ksys_mmap_pgoff(addr, len, prot, flags, fd, off >> PAGE_SHIFT);
     100             : }

Generated by: LCOV version 1.14