All of lore.kernel.org
 help / color / mirror / Atom feed
From: Arnaldo Carvalho de Melo <acme@kernel.org>
To: Yonghong Song <yhs@fb.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>,
	Gianluca Borello <g.borello@gmail.com>,
	Alexei Starovoitov <ast@kernel.org>,
	David Miller <davem@davemloft.net>,
	Linux Networking Development Mailing List
	<netdev@vger.kernel.org>
Subject: Re: len = bpf_probe_read_str(); bpf_perf_event_output(... len) == FAIL
Date: Tue, 21 Nov 2017 11:29:05 -0300	[thread overview]
Message-ID: <20171121142905.GJ7918@kernel.org> (raw)
In-Reply-To: <0839587a-9520-c844-61a3-01a7a30f0015@fb.com>

Em Tue, Nov 14, 2017 at 02:58:24PM -0800, Yonghong Song escreveu:
> On 11/14/17 12:25 PM, Daniel Borkmann wrote:
> > Yeah, I know, that's what I mentioned earlier in this thread to resolve it,
> > but do we really want to add this hack everywhere? :( Potentially any function
> > having ARG_CONST_SIZE would need to handle size 0 and bail out again in their
> > helper implementation and it ends up that progs start relying on this runtime
> > check where we won't be able to get rid of it later on anymore.
 
> The compiler actually does the right thing for the below code:
>          int ret = bpf_probe_read_str(filename, sizeof(filename),
>                                       filename_ptr);
>          if (ret > 0)
>            bpf_perf_event_output(ctx, &__bpf_stdout__,BPF_F_CURRENT_CPU,
>                            filename, ret & (sizeof(filename) - 1));
 
> Just from the above code without consulting bpf_probe_read_str internals, it
> is totally possible that ret = 128, then
> ret & (sizeof(filename) - 1) = 0.

> The issue is that the verifier did not set the "ret" initial range as (-inf,
> sizeof(filename) - 1). We could have this information associated with helper
> and feed back to verifier.
 
> If we have this range, later for ret & (sizeof(filename) - 1) with ret >= 1,
> the verifier should be able to conclude
>  ret & (sizeof(filename) - 1) >= 1.
 
> To workaround the immediate problem, I tested the following hack
> with bcc and it works fine.
 
> BPF_PERF_OUTPUT(events);
> int trace(struct pt_regs *ctx) {
>   char filename[128];
>   int ret = bpf_probe_read_str(filename, sizeof(filename), 0);
>   if (ret > 0) {
>     if (ret == 1)
>           events.perf_submit(ctx, filename, ret);
>     else if (ret < 128)
>           events.perf_submit(ctx, filename, ret);
>   }
>   return 1;
> }
 
> The idea is to make control flow more complex to prevent llvm
> do certain optimizations.

So, the hack makes it work for me, using clang 6.0:

set env: NR_CPUS=4
set env: LINUX_VERSION_CODE=0x40e00
set env: CLANG_EXEC=/usr/local/bin/clang
unset env: CLANG_OPTIONS
set env: KERNEL_INC_OPTIONS= -nostdinc -isystem /usr/lib/gcc/x86_64-redhat-linux/7/include -I/home/acme/git/linux/arch/x86/include -I./arch/x86/include/generated  -I/home/acme/git/linux/include -I./include -I/home/acme/git/linux/arch/x86/include/uapi -I./arch/x86/include/generated/uapi -I/home/acme/git/linux/include/uapi -I./include/generated/uapi -include /home/acme/git/linux/include/linux/kconfig.h 
set env: WORKING_DIR=/lib/modules/4.14.0+/build
set env: CLANG_SOURCE=/home/acme/bpf/open.c
llvm compiling command template: $CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS -DLINUX_VERSION_CODE=$LINUX_VERSION_CODE $CLANG_OPTIONS $KERNEL_INC_OPTIONS -Wno-unused-value -Wno-pointer-sign -working-directory $WORKING_DIR -c "$CLANG_SOURCE" -target bpf -O2 -o -

[root@jouet bpf]# perf probe -V do_sys_open
Available variables at do_sys_open
        @<do_sys_open+0>
                char*   filename
                int     dfd
                int     flags
                struct open_flags       op
                umode_t mode
[root@jouet bpf]# cat open.c 
#include "bpf.h"

SEC("prog=do_sys_open filename")
int prog(void *ctx, int err, char *filename_ptr)
{
	char filename[128];
	int len = bpf_probe_read_str(filename, sizeof(filename), filename_ptr); 
	if (len > 0) {
		if (len == 1)
       			perf_event_output(ctx, &__bpf_stdout__, BPF_F_CURRENT_CPU, filename, len);
		else if (len < 128)
       			perf_event_output(ctx, &__bpf_stdout__, BPF_F_CURRENT_CPU, filename, len);
	}
	return 1;
}
[root@jouet bpf]#
[root@jouet bpf]# perf trace -e *open,open.c touch /tmp/Thanks.Yonghong.Song\!
LLVM: dumping open.o
     0.000 ( 0.009 ms): touch/9034 open(filename: 0x5b678e37, flags: CLOEXEC                             ) ...
     0.009 (         ): __bpf_stdout__:/etc/ld.so.cache....)
     0.011 (         ): perf_bpf_probe:prog:(ffffffff8f260da0) filename=0x7f805b678e37)
     0.000 ( 0.016 ms): touch/9034  ... [continued]: open()) = 3
     0.034 ( 0.002 ms): touch/9034 open(filename: 0x5b87c640, flags: CLOEXEC                             ) ...
     0.036 (         ): __bpf_stdout__:/lib64/libc.so.6....)
     0.037 (         ): perf_bpf_probe:prog:(ffffffff8f260da0) filename=0x7f805b87c640)
     0.034 ( 0.009 ms): touch/9034  ... [continued]: open()) = 3
     0.251 ( 0.002 ms): touch/9034 open(filename: 0x5b422c70, flags: CLOEXEC                             ) ...
     0.253 (         ): __bpf_stdout__:/usr/lib/locale/locale-archive......)
     0.254 (         ): perf_bpf_probe:prog:(ffffffff8f260da0) filename=0x7f805b422c70)
     0.251 ( 0.009 ms): touch/9034  ... [continued]: open()) = 3
     0.296 ( 0.002 ms): touch/9034 open(filename: 0x1d3a00f1, flags: CREAT|NOCTTY|NONBLOCK|WRONLY, mode: IRUGO|IWUGO) ...
     0.298 (         ): __bpf_stdout__:/tmp/Thanks.Yonghong.Song!..)
     0.299 (         ): perf_bpf_probe:prog:(ffffffff8f260da0) filename=0x7ffd1d3a00f1)
     0.296 ( 0.009 ms): touch/9034  ... [continued]: open()) = 3
[root@jouet bpf]#

  reply	other threads:[~2017-11-21 14:29 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-11-13 14:30 len = bpf_probe_read_str(); bpf_perf_event_output(... len) == FAIL Arnaldo Carvalho de Melo
2017-11-13 14:56 ` Daniel Borkmann
2017-11-13 15:08   ` Arnaldo Carvalho de Melo
2017-11-14  0:09     ` Daniel Borkmann
2017-11-14 12:58       ` Arnaldo Carvalho de Melo
2017-11-14 13:09         ` Daniel Borkmann
2017-11-14 13:42           ` Arnaldo Carvalho de Melo
2017-11-14 14:19             ` Daniel Borkmann
2017-11-14 14:58               ` Arnaldo Carvalho de Melo
2017-11-14 18:15               ` Yonghong Song
2017-11-14 20:25                 ` Daniel Borkmann
2017-11-14 22:58                   ` Yonghong Song
2017-11-21 14:29                     ` Arnaldo Carvalho de Melo [this message]
2017-11-21 22:31                       ` Alexei Starovoitov
2017-11-22 18:42                         ` Gianluca Borello
2018-01-22 15:06                           ` Arnaldo Carvalho de Melo
2018-01-22 18:28                             ` Yonghong Song
2018-01-22 20:52                               ` Arnaldo Carvalho de Melo
2017-11-20 13:31                   ` Arnaldo Carvalho de Melo
2017-11-20 16:47                     ` Yonghong Song

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20171121142905.GJ7918@kernel.org \
    --to=acme@kernel.org \
    --cc=ast@kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=davem@davemloft.net \
    --cc=g.borello@gmail.com \
    --cc=netdev@vger.kernel.org \
    --cc=yhs@fb.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.