static int lookup_bad_addr(const int type, const unsigned long addr, const size_t size) { /* Is this a valid memory access? * * Note we're using access_ok() here. This is only supposed to be * called when we're in task context. Occasionally lookup_bad_addr() * gets called when not in task context. If in_task() exists, only * call access_ok() when we're in task context (otherwise we'll get * a kernel warning). If we aren't in task context, we'll just do a * range check. */ #if !defined(in_task) if (size == 0 || ULONG_MAX - addr < size - 1 || !access_ok(type, (void *)addr, size)) return 1; #else if (size == 0 || ULONG_MAX - addr < size - 1 || (in_task() && !access_ok(type, (void *)addr, size)) || (!in_task() #if defined(user_addr_max) && ((user_addr_max() - size) < addr) #endif )) return 1; #endif #if ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPDEV) && \ ! STP_PRIVILEGE_CONTAINS (STP_PRIVILEGE, STP_PR_STAPSYS) /* Unprivileged users must not access memory while the context does not refer to their own process. */ if (! is_myproc ()) return 1; /* Unprivileged users must not access kernel space memory. */ if (addr + size > TASK_SIZE) return 1; #endif return 0; }
/* * Entry point from instrumented code. * This is called once per basic-block/edge. */ void notrace __sanitizer_cov_trace_pc(void) { struct task_struct *t; enum kcov_mode mode; t = current; /* * We are interested in code coverage as a function of a syscall inputs, * so we ignore code executed in interrupts. */ if (!t || !in_task()) return; mode = READ_ONCE(t->kcov_mode); if (mode == KCOV_MODE_TRACE) { unsigned long *area; unsigned long pos; unsigned long ip = _RET_IP_; #ifdef CONFIG_RANDOMIZE_BASE ip -= kaslr_offset(); #endif /* * There is some code that runs in interrupts but for which * in_interrupt() returns false (e.g. preempt_schedule_irq()). * READ_ONCE()/barrier() effectively provides load-acquire wrt * interrupts, there are paired barrier()/WRITE_ONCE() in * kcov_ioctl_locked(). */ barrier(); area = t->kcov_area; /* The first word is number of subsequent PCs. */ pos = READ_ONCE(area[0]) + 1; if (likely(pos < t->kcov_size)) { area[pos] = ip; WRITE_ONCE(area[0], pos); } } }