Hi,
There are just two clean-up patches for BPF_LOG_KERNEL log level:
patch #1 fixes the possible extra newline for bpf_log() and removes
the unnecessary calculation and truncation, and patch #2 disallows
BPF_LOG_KERNEL log level for bpf_btf_load().
Comments are welcome.
Regards,
Tao
Change Log:
v2:
* rebased on bpf-next
* patch #1: add a trailing newline if needed (suggested by Martin)
* add patch #2
v1: https://www.spinics.net/lists/bpf/msg48550.html
Hou Tao (2):
bpf: clean-up bpf_verifier_vlog() for BPF_LOG_KERNEL log level
bpf: disallow BPF_LOG_KERNEL log level for sys(BPF_BTF_LOAD)
include/linux/bpf_verifier.h | 6 ++++++
kernel/bpf/btf.c | 3 +--
kernel/bpf/verifier.c | 16 +++++++++-------
3 files changed, 16 insertions(+), 9 deletions(-)
--
2.29.2
An extra newline will output for bpf_log() with BPF_LOG_KERNEL level
as shown below:
[ 52.095704] BPF:The function test_3 has 12 arguments. Too many.
[ 52.095704]
[ 52.096896] Error in parsing func ptr test_3 in struct bpf_dummy_ops
Now all bpf_log() are ended by newline, but not all btf_verifier_log()
are ended by newline, so checking whether or not the log message
has the trailing newline and adding a newline if not.
Also there is no need to calculate the left userspace buffer size
for kernel log output and to truncate the output by '\0' which
has already been done by vscnprintf(), so only do these for
userspace log output.
Signed-off-by: Hou Tao <redacted>
---
kernel/bpf/verifier.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
BPF_LOG_KERNEL is only used internally, so disallow bpf_btf_load()
to set log level as BPF_LOG_KERNEL. The same checking has already
been done in bpf_check(), so factor out a helper to check the
validity of log attributes and use it in both places.
Signed-off-by: Hou Tao <redacted>
---
include/linux/bpf_verifier.h | 6 ++++++
kernel/bpf/btf.c | 3 +--
kernel/bpf/verifier.c | 6 +++---
3 files changed, 10 insertions(+), 5 deletions(-)
@@ -13935,11 +13935,11 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr)log->ubuf=(char__user*)(unsignedlong)attr->log_buf;log->len_total=attr->log_size;-ret=-EINVAL;/* log attributes have to be sane */-if(log->len_total<128||log->len_total>UINT_MAX>>2||-!log->level||!log->ubuf||log->level&~BPF_LOG_MASK)+if(!bpf_verifier_log_attr_valid(log)){+ret=-EINVAL;gotoerr_unlock;+}}if(IS_ERR(btf_vmlinux)){
From: Daniel Borkmann <daniel@iogearbox.net> Date: 2021-11-01 21:59:34
On 10/29/21 3:53 PM, Hou Tao wrote:
quoted hunk
BPF_LOG_KERNEL is only used internally, so disallow bpf_btf_load()
to set log level as BPF_LOG_KERNEL. The same checking has already
been done in bpf_check(), so factor out a helper to check the
validity of log attributes and use it in both places.
Signed-off-by: Hou Tao <redacted>
---
include/linux/bpf_verifier.h | 6 ++++++
kernel/bpf/btf.c | 3 +--
kernel/bpf/verifier.c | 6 +++---
3 files changed, 10 insertions(+), 5 deletions(-)
nit: No surrounding () needed.
This should probably also get a Fixes tag wrt BPF_LOG_KERNEL exposure?
Is there a need to bump log->len_total for BTF so significantly?
@@ -13935,11 +13935,11 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr)log->ubuf=(char__user*)(unsignedlong)attr->log_buf;log->len_total=attr->log_size;-ret=-EINVAL;/* log attributes have to be sane */-if(log->len_total<128||log->len_total>UINT_MAX>>2||-!log->level||!log->ubuf||log->level&~BPF_LOG_MASK)+if(!bpf_verifier_log_attr_valid(log)){+ret=-EINVAL;gotoerr_unlock;+}}if(IS_ERR(btf_vmlinux)){
From: Daniel Borkmann <daniel@iogearbox.net> Date: 2021-11-01 22:01:37
On 10/29/21 3:53 PM, Hou Tao wrote:
quoted hunk
An extra newline will output for bpf_log() with BPF_LOG_KERNEL level
as shown below:
[ 52.095704] BPF:The function test_3 has 12 arguments. Too many.
[ 52.095704]
[ 52.096896] Error in parsing func ptr test_3 in struct bpf_dummy_ops
Now all bpf_log() are ended by newline, but not all btf_verifier_log()
are ended by newline, so checking whether or not the log message
has the trailing newline and adding a newline if not.
Also there is no need to calculate the left userspace buffer size
for kernel log output and to truncate the output by '\0' which
has already been done by vscnprintf(), so only do these for
userspace log output.
Signed-off-by: Hou Tao <redacted>
---
kernel/bpf/verifier.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
BPF_LOG_KERNEL is only used internally, so disallow bpf_btf_load()
to set log level as BPF_LOG_KERNEL. The same checking has already
been done in bpf_check(), so factor out a helper to check the
validity of log attributes and use it in both places.
Signed-off-by: Hou Tao <redacted>
---
include/linux/bpf_verifier.h | 6 ++++++
kernel/bpf/btf.c | 3 +--
kernel/bpf/verifier.c | 6 +++---
3 files changed, 10 insertions(+), 5 deletions(-)
This should probably also get a Fixes tag wrt BPF_LOG_KERNEL exposure?
If log->level is set as BPF_LOG_KERNEL, the only harm is the user-space tool
(still need being bpf_capable()) may flood the kernel with BPF error message,
so i didn't add it. Adding the Fixes tags incurs no harm, so will do in v3.
Is there a need to bump log->len_total for BTF so significantly?
I had noticed the values of these two max length are different, but doesn't find
any clue about why the different is necessary. So just use the bigger one for
the simplicity of bpf_verifier_log_attr_valid(). Will pass the required max
length to bpf_verifier_log_attr_valid() in v3.