LCOV - code coverage report
Current view: top level - kernel/entry - syscall_user_dispatch.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 0 40 0.0 %
Date: 2021-04-22 12:43:58 Functions: 0 3 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * Copyright (C) 2020 Collabora Ltd.
       4             :  */
       5             : #include <linux/sched.h>
       6             : #include <linux/prctl.h>
       7             : #include <linux/syscall_user_dispatch.h>
       8             : #include <linux/uaccess.h>
       9             : #include <linux/signal.h>
      10             : #include <linux/elf.h>
      11             : 
      12             : #include <linux/sched/signal.h>
      13             : #include <linux/sched/task_stack.h>
      14             : 
      15             : #include <asm/syscall.h>
      16             : 
      17             : #include "common.h"
      18             : 
      19           0 : static void trigger_sigsys(struct pt_regs *regs)
      20             : {
      21           0 :         struct kernel_siginfo info;
      22             : 
      23           0 :         clear_siginfo(&info);
      24           0 :         info.si_signo = SIGSYS;
      25           0 :         info.si_code = SYS_USER_DISPATCH;
      26           0 :         info.si_call_addr = (void __user *)KSTK_EIP(current);
      27           0 :         info.si_errno = 0;
      28           0 :         info.si_arch = syscall_get_arch(current);
      29           0 :         info.si_syscall = syscall_get_nr(current, regs);
      30             : 
      31           0 :         force_sig_info(&info);
      32           0 : }
      33             : 
      34           0 : bool syscall_user_dispatch(struct pt_regs *regs)
      35             : {
      36           0 :         struct syscall_user_dispatch *sd = &current->syscall_dispatch;
      37           0 :         char state;
      38             : 
      39           0 :         if (likely(instruction_pointer(regs) - sd->offset < sd->len))
      40             :                 return false;
      41             : 
      42           0 :         if (unlikely(arch_syscall_is_vdso_sigreturn(regs)))
      43             :                 return false;
      44             : 
      45           0 :         if (likely(sd->selector)) {
      46             :                 /*
      47             :                  * access_ok() is performed once, at prctl time, when
      48             :                  * the selector is loaded by userspace.
      49             :                  */
      50           0 :                 if (unlikely(__get_user(state, sd->selector)))
      51           0 :                         do_exit(SIGSEGV);
      52             : 
      53           0 :                 if (likely(state == SYSCALL_DISPATCH_FILTER_ALLOW))
      54             :                         return false;
      55             : 
      56           0 :                 if (state != SYSCALL_DISPATCH_FILTER_BLOCK)
      57           0 :                         do_exit(SIGSYS);
      58             :         }
      59             : 
      60           0 :         sd->on_dispatch = true;
      61           0 :         syscall_rollback(current, regs);
      62           0 :         trigger_sigsys(regs);
      63             : 
      64           0 :         return true;
      65             : }
      66             : 
      67           0 : int set_syscall_user_dispatch(unsigned long mode, unsigned long offset,
      68             :                               unsigned long len, char __user *selector)
      69             : {
      70           0 :         switch (mode) {
      71           0 :         case PR_SYS_DISPATCH_OFF:
      72           0 :                 if (offset || len || selector)
      73             :                         return -EINVAL;
      74             :                 break;
      75           0 :         case PR_SYS_DISPATCH_ON:
      76             :                 /*
      77             :                  * Validate the direct dispatcher region just for basic
      78             :                  * sanity against overflow and a 0-sized dispatcher
      79             :                  * region.  If the user is able to submit a syscall from
      80             :                  * an address, that address is obviously valid.
      81             :                  */
      82           0 :                 if (offset && offset + len <= offset)
      83             :                         return -EINVAL;
      84             : 
      85           0 :                 if (selector && !access_ok(selector, sizeof(*selector)))
      86             :                         return -EFAULT;
      87             : 
      88             :                 break;
      89             :         default:
      90             :                 return -EINVAL;
      91             :         }
      92             : 
      93           0 :         current->syscall_dispatch.selector = selector;
      94           0 :         current->syscall_dispatch.offset = offset;
      95           0 :         current->syscall_dispatch.len = len;
      96           0 :         current->syscall_dispatch.on_dispatch = false;
      97             : 
      98           0 :         if (mode == PR_SYS_DISPATCH_ON)
      99           0 :                 set_syscall_work(SYSCALL_USER_DISPATCH);
     100             :         else
     101           0 :                 clear_syscall_work(SYSCALL_USER_DISPATCH);
     102             : 
     103             :         return 0;
     104             : }

Generated by: LCOV version 1.14