From: Jiri Olsa <jolsa@redhat.com>
To: Yonghong Song <yhs@fb.com>
Cc: Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
bpf@vger.kernel.org, netdev@vger.kernel.org,
Andrii Nakryiko <andriin@fb.com>, Martin KaFai Lau <kafai@fb.com>,
Song Liu <songliubraving@fb.com>,
John Fastabend <john.fastabend@gmail.com>,
KP Singh <kpsingh@chromium.org>
Subject: Re: [RFC] bpf: verifier check for dead branch
Date: Mon, 10 Aug 2020 15:54:51 +0200 [thread overview]
Message-ID: <20200810135451.GA699846@krava> (raw)
In-Reply-To: <f13fde40-0c07-ff73-eeb3-3c59c5694f74@fb.com>
On Sun, Aug 09, 2020 at 06:21:01PM -0700, Yonghong Song wrote:
>
>
> On 8/7/20 10:30 AM, Jiri Olsa wrote:
> > hi,
> > we have a customer facing some odd verifier fails on following
> > sk_skb program:
> >
> > 0. r2 = *(u32 *)(r1 + data_end)
> > 1. r4 = *(u32 *)(r1 + data)
> > 2. r3 = r4
> > 3. r3 += 42
> > 4. r1 = 0
> > 5. if r3 > r2 goto 8
> > 6. r4 += 14
> > 7. r1 = r4
> > 8. if r3 > r2 goto 10
> > 9. r2 = *(u8 *)(r1 + 9)
> > 10. r0 = 0
> > 11. exit
> >
> > The code checks if the skb data is big enough (5) and if it is,
> > it prepares pointer in r1 (7), then there's again size check (8)
> > and finally data load from r1 (9).
> >
> > It's and odd code, but apparently this is something that can
> > get produced by clang.
>
> Could you provide a test case where clang generates the above code?
> I would like to see whether clang can do a better job to avoid
> such codes.
I get that code genrated by using recent enough upstream clang
on the attached source.
/opt/clang/bin/clang --version
clang version 11.0.0 (https://github.com/llvm/llvm-project.git 4cbfb98eb362b0629d5d1cd113af4427e2904763)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /opt/clang/bin
$ llvm-objdump -d verifier-cond-repro.o
verifier-cond-repro.o: file format ELF64-BPF
Disassembly of section .text:
0000000000000000 my_prog:
0: 61 12 50 00 00 00 00 00 r2 = *(u32 *)(r1 + 80)
1: 61 14 4c 00 00 00 00 00 r4 = *(u32 *)(r1 + 76)
2: bf 43 00 00 00 00 00 00 r3 = r4
3: 07 03 00 00 2a 00 00 00 r3 += 42
4: b7 01 00 00 00 00 00 00 r1 = 0
5: 2d 23 02 00 00 00 00 00 if r3 > r2 goto +2 <LBB0_2>
6: 07 04 00 00 0e 00 00 00 r4 += 14
7: bf 41 00 00 00 00 00 00 r1 = r4
0000000000000040 LBB0_2:
8: 2d 23 05 00 00 00 00 00 if r3 > r2 goto +5 <LBB0_5>
9: 71 12 09 00 00 00 00 00 r2 = *(u8 *)(r1 + 9)
10: 56 02 03 00 11 00 00 00 if w2 != 17 goto +3 <LBB0_5>
11: b4 00 00 00 d2 04 00 00 w0 = 1234
12: 69 11 16 00 00 00 00 00 r1 = *(u16 *)(r1 + 22)
13: 16 01 01 00 d2 04 00 00 if w1 == 1234 goto +1 <LBB0_6>
0000000000000070 LBB0_5:
14: b4 00 00 00 ff ff ff ff w0 = -1
0000000000000078 LBB0_6:
15: 95 00 00 00 00 00 00 00 exit
thanks,
jirka
---
// Copyright (c) 2019 Tigera, Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stddef.h>
#include <string.h>
#include <linux/bpf.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/ip.h>
#include <linux/ipv6.h>
#include <linux/in.h>
#include <linux/udp.h>
#include <linux/tcp.h>
#include <linux/pkt_cls.h>
#include <sys/socket.h>
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_endian.h>
#include <stddef.h>
#define INLINE inline __attribute__((always_inline))
#define skb_shorter(skb, len) ((void *)(long)(skb)->data + (len) > (void *)(long)skb->data_end)
#define ETH_IPV4_UDP_SIZE (14+20+8)
static INLINE struct iphdr *get_iphdr (struct __sk_buff *skb)
{
struct iphdr *ip = NULL;
struct ethhdr *eth;
if (skb_shorter(skb, ETH_IPV4_UDP_SIZE))
goto out;
eth = (void *)(long)skb->data;
ip = (void *)(eth + 1);
out:
return ip;
}
int my_prog(struct __sk_buff *skb)
{
struct iphdr *ip = NULL;
struct udphdr *udp;
__u8 proto = 0;
if (!(ip = get_iphdr(skb)))
goto out;
proto = ip->protocol;
if (proto != IPPROTO_UDP)
goto out;
udp = (void*)(ip + 1);
if (udp->dest != 1234)
goto out;
if (!udp)
goto out;
return udp->dest;
out:
return -1;
}
next prev parent reply other threads:[~2020-08-10 13:55 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-08-07 17:30 [RFC] bpf: verifier check for dead branch Jiri Olsa
2020-08-10 1:21 ` Yonghong Song
2020-08-10 13:54 ` Jiri Olsa [this message]
2020-08-10 17:16 ` Yonghong Song
2020-08-11 7:14 ` Jiri Olsa
2020-08-11 16:08 ` Yonghong Song
2020-08-12 7:48 ` Jiri Olsa
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=20200810135451.GA699846@krava \
--to=jolsa@redhat.com \
--cc=andriin@fb.com \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=john.fastabend@gmail.com \
--cc=kafai@fb.com \
--cc=kpsingh@chromium.org \
--cc=netdev@vger.kernel.org \
--cc=songliubraving@fb.com \
--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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).