> Am 16.08.2019 um 01:01 schrieb Yonghong Song <yhs@xxxxxx>: > > > > On 8/15/19 4:20 AM, Ilya Leoshkevich wrote: >> "ctx:file_pos sysctl:read write ok" fails on s390 with "Read value != >> nux". This is because verifier rewrites a complete 32-bit >> bpf_sysctl.file_pos update to a partial update of the first 32 bits of >> 64-bit *bpf_sysctl_kern.ppos, which is not correct on big-endian >> systems. >> >> Fix by using an offset on big-endian systems. >> >> Ditto for bpf_sysctl.file_pos reads. Currently the test does not detect >> a problem there, since it expects to see 0, which it gets with high >> probability in error cases, so change it to seek to offset 3 and expect >> 3 in bpf_sysctl.file_pos. >> >> Fixes: e1550bfe0de4 ("bpf: Add file_pos field to bpf_sysctl ctx") >> Signed-off-by: Ilya Leoshkevich <iii@xxxxxxxxxxxxx> >> --- >> include/linux/filter.h | 10 ++++++++++ >> kernel/bpf/cgroup.c | 9 +++++++-- >> tools/testing/selftests/bpf/test_sysctl.c | 9 ++++++++- >> 3 files changed, 25 insertions(+), 3 deletions(-) >> >> diff --git a/include/linux/filter.h b/include/linux/filter.h >> index 92c6e31fb008..94e81c56d81c 100644 >> --- a/include/linux/filter.h >> +++ b/include/linux/filter.h >> @@ -760,6 +760,16 @@ bpf_ctx_narrow_load_shift(u32 off, u32 size, u32 size_default) >> #endif >> } >> >> +static inline s16 >> +bpf_ctx_narrow_access_offset(size_t variable_size, size_t access_size) >> +{ >> +#ifdef __LITTLE_ENDIAN >> + return 0; >> +#else >> + return variable_size - access_size; >> +#endif >> +} > > The change looks correct to me. > But now in include/linux/filter.h we have to macros: > > static inline u8 > bpf_ctx_narrow_load_shift(u32 off, u32 size, u32 size_default) > { > u8 load_off = off & (size_default - 1); > > #ifdef __LITTLE_ENDIAN > return load_off * 8; > #else > return (size_default - (load_off + size)) * 8; > #endif > } > > static inline s16 > bpf_ctx_narrow_access_offset(size_t variable_size, size_t access_size) > { > #ifdef __LITTLE_ENDIAN > return 0; > #else > return variable_size - access_size; > #endif > } > > It would be good if we can have ifdef __LITTLE_ENDIAN only in one place. > How about something like below: > > static inline u8 > bpf_ctx_narrow_access_offset(u32 off, u32 size, u32 size_default) > { > u8 access_off = off & (size_default - 1); > > #ifdef __LITTLE_ENDIAN > return access_off; > #else > return size_default - (access_off + size); > #endif > } > > static inline u8 > bpf_ctx_narrow_load_shift(u32 off, u32 size, u32 size_default) > { > return bpf_ctx_narrow_access_offset(off, size, size_default) * 8; > } This does indeed look better, thanks! In this case, we don't even need bpf_ctx_narrow_load_shift() anymore, since doing u8 shift = bpf_ctx_narrow_access_offset( off, size, size_default) * 8; directly is quite readable. I will test and send a v2.