On Fri, Jul 31, 2020 at 10:56:17AM +0800, Jin Yao wrote:
> @@ -6973,7 +6973,8 @@ static struct perf_callchain_entry __empty_callchain = 
> { .nr = 0, };
>  struct perf_callchain_entry *
>  perf_callchain(struct perf_event *event, struct pt_regs *regs)
>  {
> -     bool kernel = !event->attr.exclude_callchain_kernel;
> +     bool kernel = !event->attr.exclude_callchain_kernel &&
> +                   !event->attr.exclude_kernel;

This seems weird; how can we get there. Also it seems to me that if you
have !exclude_callchain_kernel you already have permission for kernel
bits, so who cares.

>       bool user   = !event->attr.exclude_callchain_user;
>       /* Disallow cross-task user callchains. */
>       bool crosstask = event->ctx->task && event->ctx->task != current;
> @@ -6988,12 +6989,39 @@ perf_callchain(struct perf_event *event, struct 
> pt_regs *regs)
>       return callchain ?: &__empty_callchain;
>  }
>  
> +static struct pt_regs *leak_check(struct perf_event_header *header,
> +                               struct perf_event *event,
> +                               struct pt_regs *regs)
> +{
> +     struct pt_regs *regs_fake = NULL;
> +
> +     if (event->attr.exclude_kernel && !user_mode(regs)) {
> +             if (!(current->flags & PF_KTHREAD)) {
> +                     regs_fake = task_pt_regs(current);
> +                     if (!user_mode(regs_fake)) {
> +                             regs_fake = NULL;
> +                             instruction_pointer_set(regs, -1L);
> +                     }
> +             } else
> +                     instruction_pointer_set(regs, -1L);

That violates coding style, also:

                if (!(current->flags & PF_KTHREAD)) {
                        regs_fake = task_pt_regs(current);
                        if (!user_mode(regs_fake)) /* is this not a BUG?  */
                                regs_fake = NULL;
                }

                if (!regs_fake)
                        instruction_pointer_set(regs, -1L);

Seems simpler to me.

> +             if ((header->misc & PERF_RECORD_MISC_CPUMODE_MASK) ==
> +                  PERF_RECORD_MISC_KERNEL) {
> +                     header->misc &= ~PERF_RECORD_MISC_CPUMODE_MASK;
> +                     header->misc |= PERF_RECORD_MISC_USER;
> +             }

Why the conditional? At this point it had better be unconditionally
user, no?

                headers->misc &= ~PERF_RECORD_MISC_CPUMODE_MASK;
                headers->misc |= PERF_RECORD_MISC_USER;

> +     }
> +
> +     return regs_fake;
> +}

Reply via email to