On Fri, Jul 29, 2016 at 5:19 PM, Daniel Borkmann <dan...@iogearbox.net> wrote:
> On 07/29/2016 10:03 PM, William Tu wrote:
>>
>> Hi Daniel and Alexei,
>>
>> Thanks for the reply. My apology for too brief description. In short,
>> in my environment, running samples/bpf/test_map always segfault under
>> percpu array/hash map operations. I think it's due to stack
>> corruption.
>>
>> I'm not using ARM. It's x86 in a VM with 2 vcpu. By printk() in kernel, I
>> got
>>    num_possible_cpu == 64
>>    num_online_cpu == 2 == sysconf(_SC_NPROCESSORS_CONF)
>
>
> Ok, thanks for the data!
>
>> So at samples/bpf/test_maps.c, test_percpu_arraymap_sanity(),
>> we define:
>>    long values[nr_cpus]; //nr_cpus=2
>>
>>    ... // create map and update map ...
>>
>>    /* check that key=0 is also found and zero initialized */
>>    assert(bpf_lookup_elem(map_fd, &key, values) == 0 &&
>>              values[0] == 0 && values[nr_cpus - 1] == 0);
>>
>> Here we enter the bpf syscall, calls into kernel "map_lookup_elem()"
>> and we calculate:
>>    value_size = round_up(map->value_size, 8) * num_possible_cpus();
>>    // which in my case 8 * 64 = 512
>>    ...
>>    // then copy to user, which writes 512B to the "values[nr_cpus]" on
>> stack
>>    if (copy_to_user(uvalue, value, value_size) != 0)
>>
>> And I think this 512B write to userspace corrupts the userspace stack
>> and causes a coredump. After bpf_lookup_elem() calls, gdb shows
>> 'values' points to memory address 0x0.
>>
>> To fix it, I could either
>> 1). declare values array based on num_possible_cpu in test_map.c,
>>    long values[64];
>> or 2) in kernel, only copying 8*2 = 16 byte from kernel to user.
>
>
> But I think the patch of using num_online_cpus() would also not be correct
> in the sense that f.e. your application could alloc an array at time X
> where map lookup at time Y would not fit to the expectations anymore due
> to CPU hotplugging (since apparently _SC_NPROCESSORS_CONF maps to online
> CPUs in some cases). So also there you could potentially corrupt your
> application or mem allocator in user space, or not all your valid data
> might get copied, hmm.
>
Yes, you're right. CPU hotplugging might cause the same issue.

Since percpu array adds variable length of data passing between kernel
and userspace, I wonder if we should add a 'value_len' field in 'union
bpf_attr' so kernel knows how much data to copy to user?

Regards,
William

Reply via email to