This patch set adds a new flag BPF_F_ZERO_SEED, which allows
forcing the seed used by hash maps to zero. This makes
it possible to write deterministic tests.
Based on an off-list conversation with Alexei Starovoitov and
Daniel Borkmann.
Lorenz Bauer (3):
bpf: allow zero-initializing hash map seed
tools: sync linux/bpf.h
tools: add selftest for BPF_F_ZERO_SEED
include/uapi/linux/bpf.h | 2 +
kernel/bpf/hashtab.c | 8 ++-
tools/include/uapi/linux/bpf.h | 2 +
tools/testing/selftests/bpf/test_maps.c | 67 +++++++++++++++++++++----
4 files changed, 66 insertions(+), 13 deletions(-)
--
2.17.1
Add a new flag BPF_F_ZERO_SEED, which forces a hash map
to initialize the seed to zero.
---
include/uapi/linux/bpf.h | 2 ++
kernel/bpf/hashtab.c | 8 ++++++--
2 files changed, 8 insertions(+), 2 deletions(-)
From: Daniel Borkmann <daniel@iogearbox.net> Date: 2018-10-02 01:52:04
On 10/01/2018 12:45 PM, Lorenz Bauer wrote:
This patch set adds a new flag BPF_F_ZERO_SEED, which allows
forcing the seed used by hash maps to zero. This makes
it possible to write deterministic tests.
Based on an off-list conversation with Alexei Starovoitov and
Daniel Borkmann.
Lorenz Bauer (3):
bpf: allow zero-initializing hash map seed
tools: sync linux/bpf.h
tools: add selftest for BPF_F_ZERO_SEED
include/uapi/linux/bpf.h | 2 +
kernel/bpf/hashtab.c | 8 ++-
tools/include/uapi/linux/bpf.h | 2 +
tools/testing/selftests/bpf/test_maps.c | 67 +++++++++++++++++++++----
4 files changed, 66 insertions(+), 13 deletions(-)
Please respin with proper SoB for each patch and non-empty commit
description. I think patch 1 should also have a more elaborate
commit description on the use case for BPF_F_ZERO_SEED, and I
think also a better comment in the uapi header that this is only
meant for testing and not production use.
Thanks,
Daniel
On Mon, Oct 1, 2018 at 12:47 PM Lorenz Bauer [off-list ref] wrote:
quoted hunk
Add a new flag BPF_F_ZERO_SEED, which forces a hash map
to initialize the seed to zero.
---
include/uapi/linux/bpf.h | 2 ++
kernel/bpf/hashtab.c | 8 ++++++--
2 files changed, 8 insertions(+), 2 deletions(-)
If this is for testing only, you can slap a capable(CAP_SYS_ADMIN)
check in here, right? I doubt it matters, but I don't really like
seeing something like this exposed to unprivileged userspace just
because you need it for kernel testing.
On Tue, 2 Oct 2018 at 21:00, Jann Horn [off-list ref] wrote:
If this is for testing only, you can slap a capable(CAP_SYS_ADMIN)
check in here, right? I doubt it matters, but I don't really like
seeing something like this exposed to unprivileged userspace just
because you need it for kernel testing.
That would mean all tests have to run as root / with CAP_SYS_ADMIN
which isn't ideal.
--
Lorenz Bauer | Systems Engineer
25 Lavington St., London SE1 0NZ
www.cloudflare.com
On Fri, Oct 5, 2018 at 9:42 AM Lorenz Bauer [off-list ref] wrote:
On Tue, 2 Oct 2018 at 21:00, Jann Horn [off-list ref] wrote:
quoted
If this is for testing only, you can slap a capable(CAP_SYS_ADMIN)
check in here, right? I doubt it matters, but I don't really like
seeing something like this exposed to unprivileged userspace just
because you need it for kernel testing.
That would mean all tests have to run as root / with CAP_SYS_ADMIN
which isn't ideal.
This patch basically means that it becomes easier for a local user to
construct a BPF hash table that has all of its values stuffed into a
single hash bucket, correct? Which makes it easier to create a BPF
program that generates unusually large RCU stalls by performing ~40000
BPF map lookups, each of which has to walk through the entire linked
list of the hash map bucket? I dislike exposing something like that to
unprivileged userspace.
And if you want to run the whole BPF test suite with all its tests,
don't you already need root privileges? Or is this a different test
suite?
On Fri, 5 Oct 2018 at 15:12, Jann Horn [off-list ref] wrote:
On Fri, Oct 5, 2018 at 9:42 AM Lorenz Bauer [off-list ref] wrote:
quoted
On Tue, 2 Oct 2018 at 21:00, Jann Horn [off-list ref] wrote:
quoted
If this is for testing only, you can slap a capable(CAP_SYS_ADMIN)
check in here, right? I doubt it matters, but I don't really like
seeing something like this exposed to unprivileged userspace just
because you need it for kernel testing.
That would mean all tests have to run as root / with CAP_SYS_ADMIN
which isn't ideal.
This patch basically means that it becomes easier for a local user to
construct a BPF hash table that has all of its values stuffed into a
single hash bucket, correct? Which makes it easier to create a BPF
program that generates unusually large RCU stalls by performing ~40000
BPF map lookups, each of which has to walk through the entire linked
list of the hash map bucket? I dislike exposing something like that to
unprivileged userspace.
That's a good point, for which I don't have an answer. You could argue that
this was the status quo until the seed was randomised, so it seems
like this hasn't been a worry so far. Should it be going forward?
And if you want to run the whole BPF test suite with all its tests,
don't you already need root privileges? Or is this a different test
suite?
No, I'm thinking about third parties that want to test their own BPF.
If you enable unprivileged BPF you can use BPF_PROG_TEST_RUN to
test your programs without root, if I'm not mistaken.
--
Lorenz Bauer | Systems Engineer
25 Lavington St., London SE1 0NZ
www.cloudflare.com
On Mon, 1 Oct 2018 at 20:12, Daniel Borkmann [off-list ref] wrote:
On 10/01/2018 12:45 PM, Lorenz Bauer wrote:
quoted
This patch set adds a new flag BPF_F_ZERO_SEED, which allows
forcing the seed used by hash maps to zero. This makes
it possible to write deterministic tests.
Based on an off-list conversation with Alexei Starovoitov and
Daniel Borkmann.
Lorenz Bauer (3):
bpf: allow zero-initializing hash map seed
tools: sync linux/bpf.h
tools: add selftest for BPF_F_ZERO_SEED
include/uapi/linux/bpf.h | 2 +
kernel/bpf/hashtab.c | 8 ++-
tools/include/uapi/linux/bpf.h | 2 +
tools/testing/selftests/bpf/test_maps.c | 67 +++++++++++++++++++++----
4 files changed, 66 insertions(+), 13 deletions(-)
Please respin with proper SoB for each patch and non-empty commit
description.
What does SoB mean? Point taken about the empty commit message.
I think patch 1 should also have a more elaborate
commit description on the use case for BPF_F_ZERO_SEED, and I
This came out of the off-list discussion we had about map hash functions,
where Alexei expressed concern that your change to randomise the seed
might catch users off-guard. I personally don't have a use case, but decided
to tackle it since it seemed a simple-ish fix to get acquainted with
the code base.
Maybe this isn't needed after all?
think also a better comment in the uapi header that this is only
meant for testing and not production use.
Will do, if you decide that this is worth having in the first place.
Thanks,
Daniel
Lorenz
--
Lorenz Bauer | Systems Engineer
25 Lavington St., London SE1 0NZ
www.cloudflare.com
On Fri, Oct 5, 2018 at 4:21 PM Lorenz Bauer [off-list ref] wrote:
On Fri, 5 Oct 2018 at 15:12, Jann Horn [off-list ref] wrote:
quoted
On Fri, Oct 5, 2018 at 9:42 AM Lorenz Bauer [off-list ref] wrote:
quoted
On Tue, 2 Oct 2018 at 21:00, Jann Horn [off-list ref] wrote:
quoted
If this is for testing only, you can slap a capable(CAP_SYS_ADMIN)
check in here, right? I doubt it matters, but I don't really like
seeing something like this exposed to unprivileged userspace just
because you need it for kernel testing.
That would mean all tests have to run as root / with CAP_SYS_ADMIN
which isn't ideal.
This patch basically means that it becomes easier for a local user to
construct a BPF hash table that has all of its values stuffed into a
single hash bucket, correct? Which makes it easier to create a BPF
program that generates unusually large RCU stalls by performing ~40000
BPF map lookups, each of which has to walk through the entire linked
list of the hash map bucket? I dislike exposing something like that to
unprivileged userspace.
That's a good point, for which I don't have an answer. You could argue that
this was the status quo until the seed was randomised, so it seems
like this hasn't been a worry so far. Should it be going forward?
I don't think that local DoS bugs, or bugs that locally degrade
performance, are a big deal, but I also think that the kernel should
try to avoid having such issues.
quoted
And if you want to run the whole BPF test suite with all its tests,
don't you already need root privileges? Or is this a different test
suite?
No, I'm thinking about third parties that want to test their own BPF.
Ah. That wasn't clear to me from your patch description.
Can you please describe exactly why something that is not a kernel
unit test needs deterministic BPF hash map behavior?
If you enable unprivileged BPF you can use BPF_PROG_TEST_RUN to
test your programs without root, if I'm not mistaken.
On Fri, Oct 5, 2018 at 4:27 PM Lorenz Bauer [off-list ref] wrote:
On Mon, 1 Oct 2018 at 20:12, Daniel Borkmann [off-list ref] wrote:
quoted
On 10/01/2018 12:45 PM, Lorenz Bauer wrote:
quoted
This patch set adds a new flag BPF_F_ZERO_SEED, which allows
forcing the seed used by hash maps to zero. This makes
it possible to write deterministic tests.
Based on an off-list conversation with Alexei Starovoitov and
Daniel Borkmann.
Lorenz Bauer (3):
bpf: allow zero-initializing hash map seed
tools: sync linux/bpf.h
tools: add selftest for BPF_F_ZERO_SEED
include/uapi/linux/bpf.h | 2 +
kernel/bpf/hashtab.c | 8 ++-
tools/include/uapi/linux/bpf.h | 2 +
tools/testing/selftests/bpf/test_maps.c | 67 +++++++++++++++++++++----
4 files changed, 66 insertions(+), 13 deletions(-)
Please respin with proper SoB for each patch and non-empty commit
description.
What does SoB mean? Point taken about the empty commit message.
On Fri, Oct 05, 2018 at 04:27:58PM +0200, Jann Horn wrote:
Can you please describe exactly why something that is not a kernel
unit test needs deterministic BPF hash map behavior?
my use case for deterministic hashing is performance analysis.
Both while developing and tuning bpf program and while optimizing
kernel side implementation.
Local dos is a valid concern, so requiring root for this flag makes sense.
On Fri, 5 Oct 2018 at 22:07, Alexei Starovoitov
[off-list ref] wrote:
On Fri, Oct 05, 2018 at 04:27:58PM +0200, Jann Horn wrote:
quoted
Can you please describe exactly why something that is not a kernel
unit test needs deterministic BPF hash map behavior?
my use case for deterministic hashing is performance analysis.
Both while developing and tuning bpf program and while optimizing
kernel side implementation.
Local dos is a valid concern, so requiring root for this flag makes sense.
Ok, I'll respin and address the comments.
--
Lorenz Bauer | Systems Engineer
25 Lavington St., London SE1 0NZ
www.cloudflare.com
Add a new flag BPF_F_ZERO_SEED, which forces a hash map
to initialize the seed to zero. This is useful when doing
performance analysis both on individual BPF programs, as
well as the kernel's hash table implementation.
Signed-off-by: Lorenz Bauer <redacted>
---
include/uapi/linux/bpf.h | 2 ++
kernel/bpf/hashtab.c | 13 +++++++++++--
2 files changed, 13 insertions(+), 2 deletions(-)
@@ -253,6 +253,8 @@ enum bpf_attach_type {#define BPF_F_NO_COMMON_LRU (1U << 1)/* Specify numa node during map creation */#define BPF_F_NUMA_NODE (1U << 2)+/* Zero-initialize hash function seed. This should only be used for testing. */+#define BPF_F_ZERO_SEED (1U << 6)/* flags for BPF_PROG_QUERY */#define BPF_F_QUERY_EFFECTIVE (1U << 0)
@@ -244,6 +244,7 @@ static int htab_map_alloc_check(union bpf_attr *attr)*/boolpercpu_lru=(attr->map_flags&BPF_F_NO_COMMON_LRU);boolprealloc=!(attr->map_flags&BPF_F_NO_PREALLOC);+boolzero_seed=(attr->map_flags&BPF_F_ZERO_SEED);intnuma_node=bpf_map_attr_numa_node(attr);BUILD_BUG_ON(offsetof(structhtab_elem,htab)!=
@@ -257,6 +258,10 @@ static int htab_map_alloc_check(union bpf_attr *attr)*/return-EPERM;+if(zero_seed&&!capable(CAP_SYS_ADMIN))+/* Guard against local DoS, and discourage production use. */+return-EPERM;+if(attr->map_flags&~HTAB_CREATE_FLAG_MASK)/* reserved bits should not be used */return-EINVAL;
@@ -253,6 +253,8 @@ enum bpf_attach_type {#define BPF_F_NO_COMMON_LRU (1U << 1)/* Specify numa node during map creation */#define BPF_F_NUMA_NODE (1U << 2)+/* Zero-initialize hash function seed. This should only be used for testing. */+#define BPF_F_ZERO_SEED (1U << 6)/* flags for BPF_PROG_QUERY */#define BPF_F_QUERY_EFFECTIVE (1U << 0)
Check that iterating two separate hash maps produces the same
order of keys if BPF_F_ZERO_SEED is used.
Signed-off-by: Lorenz Bauer <redacted>
---
tools/testing/selftests/bpf/test_maps.c | 68 +++++++++++++++++++++----
1 file changed, 57 insertions(+), 11 deletions(-)
On Mon, Oct 8, 2018 at 3:34 AM Lorenz Bauer [off-list ref] wrote:
quoted hunk
Add a new flag BPF_F_ZERO_SEED, which forces a hash map
to initialize the seed to zero. This is useful when doing
performance analysis both on individual BPF programs, as
well as the kernel's hash table implementation.
Signed-off-by: Lorenz Bauer <redacted>
---
include/uapi/linux/bpf.h | 2 ++
kernel/bpf/hashtab.c | 13 +++++++++++--
2 files changed, 13 insertions(+), 2 deletions(-)
@@ -253,6 +253,8 @@ enum bpf_attach_type {#define BPF_F_NO_COMMON_LRU (1U << 1)/* Specify numa node during map creation */#define BPF_F_NUMA_NODE (1U << 2)+/* Zero-initialize hash function seed. This should only be used for testing. */+#define BPF_F_ZERO_SEED (1U << 6)
Please add this line after
#define BPF_F_STACK_BUILD_ID (1U << 5)
Other than this
Acked-by: Song Liu <redacted>
quoted hunk
/* flags for BPF_PROG_QUERY */
#define BPF_F_QUERY_EFFECTIVE (1U << 0)
@@ -244,6 +244,7 @@ static int htab_map_alloc_check(union bpf_attr *attr)*/boolpercpu_lru=(attr->map_flags&BPF_F_NO_COMMON_LRU);boolprealloc=!(attr->map_flags&BPF_F_NO_PREALLOC);+boolzero_seed=(attr->map_flags&BPF_F_ZERO_SEED);intnuma_node=bpf_map_attr_numa_node(attr);BUILD_BUG_ON(offsetof(structhtab_elem,htab)!=
@@ -257,6 +258,10 @@ static int htab_map_alloc_check(union bpf_attr *attr)*/return-EPERM;+if(zero_seed&&!capable(CAP_SYS_ADMIN))+/* Guard against local DoS, and discourage production use. */+return-EPERM;+if(attr->map_flags&~HTAB_CREATE_FLAG_MASK)/* reserved bits should not be used */return-EINVAL;
@@ -253,6 +253,8 @@ enum bpf_attach_type {#define BPF_F_NO_COMMON_LRU (1U << 1)/* Specify numa node during map creation */#define BPF_F_NUMA_NODE (1U << 2)+/* Zero-initialize hash function seed. This should only be used for testing. */+#define BPF_F_ZERO_SEED (1U << 6)
On Mon, Oct 8, 2018 at 3:34 AM Lorenz Bauer [off-list ref] wrote:
quoted hunk
Check that iterating two separate hash maps produces the same
order of keys if BPF_F_ZERO_SEED is used.
Signed-off-by: Lorenz Bauer <redacted>
---
tools/testing/selftests/bpf/test_maps.c | 68 +++++++++++++++++++++----
1 file changed, 57 insertions(+), 11 deletions(-)
On Tue, 9 Oct 2018 at 01:12, Song Liu [off-list ref] wrote:
On Mon, Oct 8, 2018 at 3:34 AM Lorenz Bauer [off-list ref] wrote:
quoted
Synchronize changes to linux/bpf.h from
commit 88db241b34bf ("bpf: allow zero-initializing hash map seed").
I guess we cannot keep this hash during git-am? We probably don't
need this hash anyway, as the two patches will be applied back to back.
I copied what was done in one of the previous commits that synced the
header. I'm a bit at a
loss what to put in the commit message otherwise.
--
Lorenz Bauer | Systems Engineer
25 Lavington St., London SE1 0NZ
www.cloudflare.com
@@ -253,6 +253,8 @@ enum bpf_attach_type {#define BPF_F_NO_COMMON_LRU (1U << 1)/* Specify numa node during map creation */#define BPF_F_NUMA_NODE (1U << 2)+/* Zero-initialize hash function seed. This should only be used for testing. */+#define BPF_F_ZERO_SEED (1U << 6)
Please add this line after
#define BPF_F_STACK_BUILD_ID (1U << 5)
I wanted to keep the flags for BPF_MAP_CREATE grouped together.
Maybe the correct value is (1U << 3)? It seemed like the other flags
were allocated to avoid
overlap between different BPF commands, however, so I tried to follow suit.
--
Lorenz Bauer | Systems Engineer
25 Lavington St., London SE1 0NZ
www.cloudflare.com
@@ -253,6 +253,8 @@ enum bpf_attach_type {#define BPF_F_NO_COMMON_LRU (1U << 1)/* Specify numa node during map creation */#define BPF_F_NUMA_NODE (1U << 2)+/* Zero-initialize hash function seed. This should only be used for testing. */+#define BPF_F_ZERO_SEED (1U << 6)
Please add this line after
#define BPF_F_STACK_BUILD_ID (1U << 5)
I wanted to keep the flags for BPF_MAP_CREATE grouped together.
Maybe the correct value is (1U << 3)? It seemed like the other flags
were allocated to avoid
overlap between different BPF commands, however, so I tried to follow suit.
I think it should be (1U << 6). We probably should move BPF_F_QUERY_EFFECTIVE
to after BPF_F_STACK_BUILD_ID (and BPF_F_ZERO_SEED).
Also, please rebase against the latest bpf-next tree and resubmit the set.
Thanks,
Song
Add a new flag BPF_F_ZERO_SEED, which forces a hash map
to initialize the seed to zero. This is useful when doing
performance analysis both on individual BPF programs, as
well as the kernel's hash table implementation.
Signed-off-by: Lorenz Bauer <redacted>
---
include/uapi/linux/bpf.h | 3 +++
kernel/bpf/hashtab.c | 13 +++++++++++--
2 files changed, 14 insertions(+), 2 deletions(-)
@@ -269,6 +269,9 @@ enum bpf_attach_type {/* Flag for stack_map, store build_id+offset instead of pointer */#define BPF_F_STACK_BUILD_ID (1U << 5)+/* Zero-initialize hash function seed. This should only be used for testing. */+#define BPF_F_ZERO_SEED (1U << 6)+enumbpf_stack_build_id_status{/* user space need an empty entry to identify end of a trace */BPF_STACK_BUILD_ID_EMPTY=0,
@@ -244,6 +244,7 @@ static int htab_map_alloc_check(union bpf_attr *attr)*/boolpercpu_lru=(attr->map_flags&BPF_F_NO_COMMON_LRU);boolprealloc=!(attr->map_flags&BPF_F_NO_PREALLOC);+boolzero_seed=(attr->map_flags&BPF_F_ZERO_SEED);intnuma_node=bpf_map_attr_numa_node(attr);BUILD_BUG_ON(offsetof(structhtab_elem,htab)!=
@@ -257,6 +258,10 @@ static int htab_map_alloc_check(union bpf_attr *attr)*/return-EPERM;+if(zero_seed&&!capable(CAP_SYS_ADMIN))+/* Guard against local DoS, and discourage production use. */+return-EPERM;+if(attr->map_flags&~HTAB_CREATE_FLAG_MASK)/* reserved bits should not be used */return-EINVAL;
BPF_F_QUERY_EFFECTIVE is in the middle of the flags valid
for BPF_MAP_CREATE. Move it to its own section to reduce confusion.
Signed-off-by: Lorenz Bauer <redacted>
---
include/uapi/linux/bpf.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
@@ -257,9 +257,6 @@ enum bpf_attach_type {/* Specify numa node during map creation */#define BPF_F_NUMA_NODE (1U << 2)-/* flags for BPF_PROG_QUERY */-#define BPF_F_QUERY_EFFECTIVE (1U << 0)-#define BPF_OBJ_NAME_LEN 16U/* Flags for accessing BPF object */
@@ -272,6 +269,9 @@ enum bpf_attach_type {/* Zero-initialize hash function seed. This should only be used for testing. */#define BPF_F_ZERO_SEED (1U << 6)+/* flags for BPF_PROG_QUERY */+#define BPF_F_QUERY_EFFECTIVE (1U << 0)+enumbpf_stack_build_id_status{/* user space need an empty entry to identify end of a trace */BPF_STACK_BUILD_ID_EMPTY=0,
@@ -257,9 +257,6 @@ enum bpf_attach_type {/* Specify numa node during map creation */#define BPF_F_NUMA_NODE (1U << 2)-/* flags for BPF_PROG_QUERY */-#define BPF_F_QUERY_EFFECTIVE (1U << 0)-#define BPF_OBJ_NAME_LEN 16U/* Flags for accessing BPF object */
@@ -269,6 +266,12 @@ enum bpf_attach_type {/* Flag for stack_map, store build_id+offset instead of pointer */#define BPF_F_STACK_BUILD_ID (1U << 5)+/* Zero-initialize hash function seed. This should only be used for testing. */+#define BPF_F_ZERO_SEED (1U << 6)++/* flags for BPF_PROG_QUERY */+#define BPF_F_QUERY_EFFECTIVE (1U << 0)+enumbpf_stack_build_id_status{/* user space need an empty entry to identify end of a trace */BPF_STACK_BUILD_ID_EMPTY=0,
@@ -2201,6 +2204,8 @@ union bpf_attr {***CONFIG_NET**configurationoption.*Return*Pointerto*structbpf_sock*,orNULLincaseoffailure.+*Forsocketswithreuseportoption,*structbpf_sock*+*returnisfromreuse->socks[]usinghashofthepacket.**structbpf_sock*bpf_sk_lookup_udp(void*ctx,structbpf_sock_tuple*tuple,u32tuple_size,u32netns,u64flags)*Description
@@ -2233,6 +2238,8 @@ union bpf_attr {***CONFIG_NET**configurationoption.*Return*Pointerto*structbpf_sock*,orNULLincaseoffailure.+*Forsocketswithreuseportoption,*structbpf_sock*+*returnisfromreuse->socks[]usinghashofthepacket.**intbpf_sk_release(structbpf_sock*sk)*Description
Check that iterating two separate hash maps produces the same
order of keys if BPF_F_ZERO_SEED is used.
Signed-off-by: Lorenz Bauer <redacted>
---
tools/testing/selftests/bpf/test_maps.c | 68 +++++++++++++++++++++----
1 file changed, 57 insertions(+), 11 deletions(-)