mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Edward Cree <ecree@solarflare.com>
To: Daniel Borkmann <daniel@iogearbox.net>, <davem@davemloft.net>,
	"Alexei Starovoitov" <alexei.starovoitov@gmail.com>,
	Alexei Starovoitov <ast@fb.com>
Cc: <netdev@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	iovisor-dev <iovisor-dev@lists.iovisor.org>
Subject: Re: [PATCH v3 net-next 02/12] bpf/verifier: rework value tracking
Date: Wed, 28 Jun 2017 17:07:36 +0100	[thread overview]
Message-ID: <71aae126-352d-d916-d64a-9d4045d0abe9@solarflare.com> (raw)
In-Reply-To: <5953C7FE.1050205@iogearbox.net>

On 28/06/17 16:15, Daniel Borkmann wrote:
> On 06/27/2017 02:56 PM, Edward Cree wrote:
>> Tracks value alignment by means of tracking known & unknown bits.
>> Tightens some min/max value checks and fixes a couple of bugs therein.
>
> You mean the one in relation to patch 1/12? Would be good to elaborate
> here since otherwise this gets forgotten few weeks later.
That wasn't the only one; there were also some in the new min/max value
 calculation for ALU ops.  For instance, in subtraction we were taking
 the new bounds as [min-min, max-max] instead of [min-max, max-min].
I can't remember what else there was and there might also have been some
 that I missed but that got incidentally fixed by the rewrite.  But I
 guess I should change "checks" to "checks and updates" in the above?
> Could you also document all the changes that verifier will then start
> allowing for after the patch?
Maybe not the changes, because the old verifier had a lot of special
 cases, but I could, and probably should, document the new behaviour
 (maybe in Documentation/networking/filter.txt, that already has a bit
 of description of the verifier).
> [...]
>>   /* check whether memory at (regno + off) is accessible for t = (read | write)
>> @@ -899,52 +965,79 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
>>       struct bpf_reg_state *reg = &state->regs[regno];
>>       int size, err = 0;
>>
>> -    if (reg->type == PTR_TO_STACK)
>> -        off += reg->imm;
>> -
>>       size = bpf_size_to_bytes(bpf_size);
>>       if (size < 0)
>>           return size;
>>
> [...]
>> -    if (reg->type == PTR_TO_MAP_VALUE ||
>> -        reg->type == PTR_TO_MAP_VALUE_ADJ) {
>> +    /* for access checks, reg->off is just part of off */
>> +    off += reg->off;
>
> Could you elaborate on why removing the reg->type == PTR_TO_STACK?
Previously bpf_reg_state had a member 'imm' which, for PTR_TO_STACK, was
 a fixed offset, so we had to add it in to the offset.  Now we instead
 have reg->off and it's generic to all pointerish types, so we don't need
 special handling of PTR_TO_STACK here.
> Also in context of below PTR_TO_CTX.
>
> [...]
>>       } else if (reg->type == PTR_TO_CTX) {
>> -        enum bpf_reg_type reg_type = UNKNOWN_VALUE;
>> +        enum bpf_reg_type reg_type = SCALAR_VALUE;
>>
>>           if (t == BPF_WRITE && value_regno >= 0 &&
>>               is_pointer_value(env, value_regno)) {
>>               verbose("R%d leaks addr into ctx\n", value_regno);
>>               return -EACCES;
>>           }
>> +        /* ctx accesses must be at a fixed offset, so that we can
>> +         * determine what type of data were returned.
>> +         */
>> +        if (!tnum_is_const(reg->var_off)) {
>> +            char tn_buf[48];
>> +
>> +            tnum_strn(tn_buf, sizeof(tn_buf), reg->var_off);
>> +            verbose("variable ctx access var_off=%s off=%d size=%d",
>> +                tn_buf, off, size);
>> +            return -EACCES;
>> +        }
>> +        off += reg->var_off.value;
>
> ... f.e. in PTR_TO_CTX case the only access that is currently
> allowed is LDX/STX with fixed offset from insn->off, which is
> passed as off param to check_mem_access(). Can you elaborate on
> off += reg->var_off.value? Meaning we make this more dynamic
> as long as access is known const?
So, I can't actually figure out how to construct a pointer with a known
 variable offset, but future changes to the verifier (like learning from
 comparing two pointers with the same base) could make it possible.  The
 situation we're handling here is where our register holds ctx + x,
 where x is also known to be some constant value k, and currently I don't
 know if that's possible except for the trivial case of k==0, and the edge
 case where k is too big to fit in the s32 reg->off (in which case the
 check_ctx_access will presumably reject it).
Stepping back a bit, each register holding a pointer type has two offsets,
 reg->off and reg->var_off, and the latter is a tnum representing
 knowledge about a value that's not necessarily exactly known.  But
 tnum_is_const checks that it _is_ exactly known.
There is another case that we allow now through the reg->off handling:
 adding a constant to a pointer and then dereferencing it.
So, with r1=ctx, instead of r2 = *(r1 + off), you can write
    r3 = r1 + off
    r2 = *(r1 + 0)
 if for some reason that suits you better.  But in that case, because off
 is a known value (either an immediate, or a register whose value is
 exactly known), that value gets added to r3->off rather than r3->var_off;
 see adjust_ptr_min_max_vals().

Hope that's clear,
-Ed

  reply	other threads:[~2017-06-28 16:07 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-27 12:53 [PATCH v3 net-next 00/12] bpf: rewrite value tracking in verifier Edward Cree
2017-06-27 12:56 ` [PATCH v3 net-next 01/12] selftests/bpf: add test for mixed signed and unsigned bounds checks Edward Cree
2017-06-28 13:51   ` Daniel Borkmann
2017-06-27 12:56 ` [PATCH v3 net-next 02/12] bpf/verifier: rework value tracking Edward Cree
2017-06-28 15:15   ` Daniel Borkmann
2017-06-28 16:07     ` Edward Cree [this message]
2017-06-28 19:44       ` Daniel Borkmann
2017-06-28 17:09   ` Daniel Borkmann
2017-06-28 18:28     ` Edward Cree
2017-06-29  7:48   ` kbuild test robot
2017-07-06 21:21   ` [iovisor-dev] " Nadav Amit
2017-07-07 13:48     ` Edward Cree
2017-07-07 17:45       ` Nadav Amit
2017-07-08  0:54         ` Nadav Amit
2017-07-12 19:13         ` Edward Cree
2017-07-12 22:07           ` Nadav Amit
2017-07-17 17:02             ` Edward Cree
2017-06-27 12:57 ` [PATCH v3 net-next 03/12] nfp: change bpf verifier hooks to match new verifier data structures Edward Cree
2017-06-28 20:47   ` Daniel Borkmann
2017-06-29  3:47   ` Jakub Kicinski
2017-06-27 12:57 ` [PATCH v3 net-next 04/12] bpf/verifier: track signed and unsigned min/max values Edward Cree
2017-06-27 12:58 ` [PATCH v3 net-next 05/12] bpf/verifier: more concise register state logs for constant var_off Edward Cree
2017-06-27 12:58 ` [PATCH v3 net-next 06/12] selftests/bpf: change test_verifier expectations Edward Cree
2017-06-27 12:59 ` [PATCH v3 net-next 07/12] selftests/bpf: rewrite test_align Edward Cree
2017-06-27 12:59 ` [PATCH v3 net-next 08/12] selftests/bpf: add a test to test_align Edward Cree
2017-06-27 12:59 ` [PATCH v3 net-next 09/12] selftests/bpf: add test for bogus operations on pointers Edward Cree
2017-06-27 12:59 ` [PATCH v3 net-next 10/12] selftests/bpf: don't try to access past MAX_PACKET_OFF in test_verifier Edward Cree
2017-06-27 13:00 ` [PATCH v3 net-next 11/12] selftests/bpf: add tests for subtraction & negative numbers Edward Cree
2017-06-27 13:00 ` [PATCH v3 net-next 12/12] selftests/bpf: variable offset negative tests Edward Cree
2017-06-28 13:50 ` [PATCH v3 net-next 00/12] bpf: rewrite value tracking in verifier Daniel Borkmann
2017-06-28 14:11   ` Edward Cree
2017-06-28 20:38     ` Daniel Borkmann
2017-06-28 21:37       ` Alexei Starovoitov
2017-06-30 16:44         ` Edward Cree
2017-06-30 17:34           ` [TEST PATCH] bpf/verifier: roll back ptr&const handling, and fix signed bounds Edward Cree
2017-06-30 18:15           ` [PATCH v3 net-next 00/12] bpf: rewrite value tracking in verifier Alexei Starovoitov
2017-07-04 19:22             ` Edward Cree
2017-07-04 22:28               ` Daniel Borkmann
2017-07-06 18:27                 ` Edward Cree
2017-07-07  9:14                   ` Daniel Borkmann
2017-07-07 12:50                     ` Edward Cree
2017-07-07 13:05                       ` Daniel Borkmann
2017-07-06 14:07               ` Edward Cree
2017-07-14 20:03 ` [iovisor-dev] " Y 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=71aae126-352d-d916-d64a-9d4045d0abe9@solarflare.com \
    --to=ecree@solarflare.com \
    --cc=alexei.starovoitov@gmail.com \
    --cc=ast@fb.com \
    --cc=daniel@iogearbox.net \
    --cc=davem@davemloft.net \
    --cc=iovisor-dev@lists.iovisor.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    /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

all inboxes | Powered by JetHome®