|
@@ -324,6 +324,21 @@ static int kcov_close(struct inode *inode, struct file *filep)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Fault in a lazily-faulted vmalloc area before it can be used by
|
|
|
+ * __santizer_cov_trace_pc(), to avoid recursion issues if any code on the
|
|
|
+ * vmalloc fault handling path is instrumented.
|
|
|
+ */
|
|
|
+static void kcov_fault_in_area(struct kcov *kcov)
|
|
|
+{
|
|
|
+ unsigned long stride = PAGE_SIZE / sizeof(unsigned long);
|
|
|
+ unsigned long *area = kcov->area;
|
|
|
+ unsigned long offset;
|
|
|
+
|
|
|
+ for (offset = 0; offset < kcov->size; offset += stride)
|
|
|
+ READ_ONCE(area[offset]);
|
|
|
+}
|
|
|
+
|
|
|
static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd,
|
|
|
unsigned long arg)
|
|
|
{
|
|
@@ -372,6 +387,7 @@ static int kcov_ioctl_locked(struct kcov *kcov, unsigned int cmd,
|
|
|
#endif
|
|
|
else
|
|
|
return -EINVAL;
|
|
|
+ kcov_fault_in_area(kcov);
|
|
|
/* Cache in task struct for performance. */
|
|
|
t->kcov_size = kcov->size;
|
|
|
t->kcov_area = kcov->area;
|