Re: [PATCH 11/18] maccess: remove strncpy_from_unsafe

From: Masami Hiramatsu
Date: Wed May 13 2020 - 19:21:04 EST


On Thu, 14 May 2020 00:36:28 +0200
Daniel Borkmann <daniel@xxxxxxxxxxxxx> wrote:

> On 5/13/20 9:28 PM, Christoph Hellwig wrote:
> > On Wed, May 13, 2020 at 12:11:27PM -0700, Linus Torvalds wrote:
> >> On Wed, May 13, 2020 at 9:01 AM Christoph Hellwig <hch@xxxxxx> wrote:
> >>>
> >>> +static void bpf_strncpy(char *buf, long unsafe_addr)
> >>> +{
> >>> + buf[0] = 0;
> >>> + if (strncpy_from_kernel_nofault(buf, (void *)unsafe_addr,
> >>> + BPF_STRNCPY_LEN))
> >>> + strncpy_from_user_nofault(buf, (void __user *)unsafe_addr,
> >>> + BPF_STRNCPY_LEN);
> >>> +}
> >>
> >> This seems buggy when I look at it.
> >>
> >> It seems to think that strncpy_from_kernel_nofault() returns an error code.
> >>
> >> Not so, unless I missed where you changed the rules.
> >
> > I didn't change the rules, so yes, this is wrong.
> >
> >> Also, I do wonder if we shouldn't gate this on TASK_SIZE, and do the
> >> user trial first. On architectures where this thing is valid in the
> >> first place (ie kernel and user addresses are separate), the test for
> >> address size would allow us to avoid a pointless fault due to an
> >> invalid kernel access to user space.
> >>
> >> So I think this function should look something like
> >>
> >> static void bpf_strncpy(char *buf, long unsafe_addr)
> >> {
> >> /* Try user address */
> >> if (unsafe_addr < TASK_SIZE) {
> >> void __user *ptr = (void __user *)unsafe_addr;
> >> if (strncpy_from_user_nofault(buf, ptr, BPF_STRNCPY_LEN) >= 0)
> >> return;
> >> }
> >>
> >> /* .. fall back on trying kernel access */
> >> buf[0] = 0;
> >> strncpy_from_kernel_nofault(buf, (void *)unsafe_addr,
> >> BPF_STRNCPY_LEN);
> >> }
> >>
> >> or similar. No?
> >
> > So on say s390 TASK_SIZE_USUALLy is (-PAGE_SIZE), which means we'd alway
> > try the user copy first, which seems odd.
> >
> > I'd really like to here from the bpf folks what the expected use case
> > is here, and if the typical argument is kernel or user memory.
>
> It's used for both. Given this is enabled on pretty much all program types, my
> assumption would be that usage is still more often on kernel memory than user one.

For trace_kprobe.c current order (kernel -> user fallback) is preferred
because it has another function dedicated for user memory.

Thank you,

--
Masami Hiramatsu <mhiramat@xxxxxxxxxx>