* [PATCH] bpf, docs: Fix modulo zero, division by zero, overflow, and underflow
@ 2023-01-05 16:32 dthaler1968
2023-01-05 19:01 ` sdf
0 siblings, 1 reply; 5+ messages in thread
From: dthaler1968 @ 2023-01-05 16:32 UTC (permalink / raw)
To: bpf; +Cc: Dave Thaler
From: Dave Thaler <dthaler@microsoft.com>
Fix modulo zero, division by zero, overflow, and underflow.
Also clarify how a negative immediate value is used in unsigned division
Signed-off-by: Dave Thaler <dthaler@microsoft.com>
---
Documentation/bpf/instruction-set.rst | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/Documentation/bpf/instruction-set.rst b/Documentation/bpf/instruction-set.rst
index e672d5ec6cc..2ba7c618f33 100644
--- a/Documentation/bpf/instruction-set.rst
+++ b/Documentation/bpf/instruction-set.rst
@@ -99,19 +99,26 @@ code value description
BPF_ADD 0x00 dst += src
BPF_SUB 0x10 dst -= src
BPF_MUL 0x20 dst \*= src
-BPF_DIV 0x30 dst /= src
+BPF_DIV 0x30 dst = (src != 0) ? (dst / src) : 0
BPF_OR 0x40 dst \|= src
BPF_AND 0x50 dst &= src
BPF_LSH 0x60 dst <<= src
BPF_RSH 0x70 dst >>= src
BPF_NEG 0x80 dst = ~src
-BPF_MOD 0x90 dst %= src
+BPF_MOD 0x90 dst = (src != 0) ? (dst % src) : dst
BPF_XOR 0xa0 dst ^= src
BPF_MOV 0xb0 dst = src
BPF_ARSH 0xc0 sign extending shift right
BPF_END 0xd0 byte swap operations (see `Byte swap instructions`_ below)
======== ===== ==========================================================
+Underflow and overflow are allowed during arithmetic operations,
+meaning the 64-bit or 32-bit value will wrap. If
+eBPF program execution would result in division by zero,
+the destination register is instead set to zero.
+If execution would result in modulo by zero,
+the destination register is instead left unchanged.
+
``BPF_ADD | BPF_X | BPF_ALU`` means::
dst_reg = (u32) dst_reg + (u32) src_reg;
@@ -128,6 +135,10 @@ BPF_END 0xd0 byte swap operations (see `Byte swap instructions`_ below)
dst_reg = dst_reg ^ imm32
+Also note that the division and modulo operations are unsigned,
+where 'imm' is first sign extended to 64 bits and then converted
+to an unsigned 64-bit value. There are no instructions for
+signed division or modulo.
Byte swap instructions
~~~~~~~~~~~~~~~~~~~~~~
--
2.33.4
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] bpf, docs: Fix modulo zero, division by zero, overflow, and underflow
2023-01-05 16:32 [PATCH] bpf, docs: Fix modulo zero, division by zero, overflow, and underflow dthaler1968
@ 2023-01-05 19:01 ` sdf
2023-01-06 16:27 ` Daniel Borkmann
0 siblings, 1 reply; 5+ messages in thread
From: sdf @ 2023-01-05 19:01 UTC (permalink / raw)
To: dthaler1968; +Cc: bpf, Dave Thaler
On 01/05, dthaler1968@googlemail.com wrote:
> From: Dave Thaler <dthaler@microsoft.com>
> Fix modulo zero, division by zero, overflow, and underflow.
> Also clarify how a negative immediate value is used in unsigned division
> Signed-off-by: Dave Thaler <dthaler@microsoft.com>
Acked-by: Stanislav Fomichev <sdf@google.com>
With a small note below.
> ---
> Documentation/bpf/instruction-set.rst | 15 +++++++++++++--
> 1 file changed, 13 insertions(+), 2 deletions(-)
> diff --git a/Documentation/bpf/instruction-set.rst
> b/Documentation/bpf/instruction-set.rst
> index e672d5ec6cc..2ba7c618f33 100644
> --- a/Documentation/bpf/instruction-set.rst
> +++ b/Documentation/bpf/instruction-set.rst
> @@ -99,19 +99,26 @@ code value description
> BPF_ADD 0x00 dst += src
> BPF_SUB 0x10 dst -= src
> BPF_MUL 0x20 dst \*= src
> -BPF_DIV 0x30 dst /= src
> +BPF_DIV 0x30 dst = (src != 0) ? (dst / src) : 0
> BPF_OR 0x40 dst \|= src
> BPF_AND 0x50 dst &= src
> BPF_LSH 0x60 dst <<= src
> BPF_RSH 0x70 dst >>= src
> BPF_NEG 0x80 dst = ~src
> -BPF_MOD 0x90 dst %= src
> +BPF_MOD 0x90 dst = (src != 0) ? (dst % src) : dst
> BPF_XOR 0xa0 dst ^= src
> BPF_MOV 0xb0 dst = src
> BPF_ARSH 0xc0 sign extending shift right
> BPF_END 0xd0 byte swap operations (see `Byte swap instructions`_
> below)
> ======== =====
> ==========================================================
> +Underflow and overflow are allowed during arithmetic operations,
> +meaning the 64-bit or 32-bit value will wrap. If
> +eBPF program execution would result in division by zero,
> +the destination register is instead set to zero.
> +If execution would result in modulo by zero,
> +the destination register is instead left unchanged.
> +
> ``BPF_ADD | BPF_X | BPF_ALU`` means::
> dst_reg = (u32) dst_reg + (u32) src_reg;
> @@ -128,6 +135,10 @@ BPF_END 0xd0 byte swap operations (see `Byte
> swap instructions`_ below)
> dst_reg = dst_reg ^ imm32
[..]
> +Also note that the division and modulo operations are unsigned,
> +where 'imm' is first sign extended to 64 bits and then converted
> +to an unsigned 64-bit value. There are no instructions for
> +signed division or modulo.
Less sure about this part, but it looks to be true at least by looking at
the interpreter which does:
DST = DST / IMM
where:
DST === (u64) regs[insn->dst_reg]
IMM === (s32) insn->imm
(and s32 is sign-expanded to u64 according to C rules)
> Byte swap instructions
> ~~~~~~~~~~~~~~~~~~~~~~
> --
> 2.33.4
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] bpf, docs: Fix modulo zero, division by zero, overflow, and underflow
2023-01-05 19:01 ` sdf
@ 2023-01-06 16:27 ` Daniel Borkmann
2023-01-06 18:11 ` Dave Thaler
0 siblings, 1 reply; 5+ messages in thread
From: Daniel Borkmann @ 2023-01-06 16:27 UTC (permalink / raw)
To: sdf, dthaler1968; +Cc: bpf, Dave Thaler
On 1/5/23 8:01 PM, sdf@google.com wrote:
> On 01/05, dthaler1968@googlemail.com wrote:
>> From: Dave Thaler <dthaler@microsoft.com>
>
>> Fix modulo zero, division by zero, overflow, and underflow.
>> Also clarify how a negative immediate value is used in unsigned division
>
>> Signed-off-by: Dave Thaler <dthaler@microsoft.com>
>
> Acked-by: Stanislav Fomichev <sdf@google.com>
>
> With a small note below.
>
>> ---
>> Documentation/bpf/instruction-set.rst | 15 +++++++++++++--
>> 1 file changed, 13 insertions(+), 2 deletions(-)
>
>> diff --git a/Documentation/bpf/instruction-set.rst b/Documentation/bpf/instruction-set.rst
>> index e672d5ec6cc..2ba7c618f33 100644
>> --- a/Documentation/bpf/instruction-set.rst
>> +++ b/Documentation/bpf/instruction-set.rst
>> @@ -99,19 +99,26 @@ code value description
>> BPF_ADD 0x00 dst += src
>> BPF_SUB 0x10 dst -= src
>> BPF_MUL 0x20 dst \*= src
>> -BPF_DIV 0x30 dst /= src
>> +BPF_DIV 0x30 dst = (src != 0) ? (dst / src) : 0
>> BPF_OR 0x40 dst \|= src
>> BPF_AND 0x50 dst &= src
>> BPF_LSH 0x60 dst <<= src
>> BPF_RSH 0x70 dst >>= src
>> BPF_NEG 0x80 dst = ~src
>> -BPF_MOD 0x90 dst %= src
>> +BPF_MOD 0x90 dst = (src != 0) ? (dst % src) : dst
>> BPF_XOR 0xa0 dst ^= src
>> BPF_MOV 0xb0 dst = src
>> BPF_ARSH 0xc0 sign extending shift right
>> BPF_END 0xd0 byte swap operations (see `Byte swap instructions`_ below)
>> ======== ===== ==========================================================
>
>> +Underflow and overflow are allowed during arithmetic operations,
>> +meaning the 64-bit or 32-bit value will wrap. If
>> +eBPF program execution would result in division by zero,
>> +the destination register is instead set to zero.
>> +If execution would result in modulo by zero,
>> +the destination register is instead left unchanged.
>> +
>> ``BPF_ADD | BPF_X | BPF_ALU`` means::
>
>> dst_reg = (u32) dst_reg + (u32) src_reg;
>> @@ -128,6 +135,10 @@ BPF_END 0xd0 byte swap operations (see `Byte swap instructions`_ below)
>
>> dst_reg = dst_reg ^ imm32
>
>
> [..]
>
>> +Also note that the division and modulo operations are unsigned,
>> +where 'imm' is first sign extended to 64 bits and then converted
>> +to an unsigned 64-bit value. There are no instructions for
>> +signed division or modulo.
>
> Less sure about this part, but it looks to be true at least by looking at
> the interpreter which does:
>
> DST = DST / IMM
>
> where:
>
> DST === (u64) regs[insn->dst_reg]
> IMM === (s32) insn->imm
>
> (and s32 is sign-expanded to u64 according to C rules)
Yeap, the actual operation is in the target width, so for 32 bit it's casted
to u32, e.g. for modulo (note that the verifier rewrites it into `(src != 0) ?
(dst % src) : dst` form, so here is just the extract of the plain mod insn and
it's similar for div):
ALU64_MOD_X:
div64_u64_rem(DST, SRC, &AX);
DST = AX;
CONT;
ALU_MOD_X:
AX = (u32) DST;
DST = do_div(AX, (u32) SRC);
CONT;
ALU64_MOD_K:
div64_u64_rem(DST, IMM, &AX);
DST = AX;
CONT;
ALU_MOD_K:
AX = (u32) DST;
DST = do_div(AX, (u32) IMM);
CONT;
So in above phrasing the middle part needs to be adapted or just removed.
Thanks,
Daniel
^ permalink raw reply [flat|nested] 5+ messages in thread
* RE: [PATCH] bpf, docs: Fix modulo zero, division by zero, overflow, and underflow
2023-01-06 16:27 ` Daniel Borkmann
@ 2023-01-06 18:11 ` Dave Thaler
2023-01-06 21:08 ` [Bpf] " Daniel Borkmann
0 siblings, 1 reply; 5+ messages in thread
From: Dave Thaler @ 2023-01-06 18:11 UTC (permalink / raw)
To: Daniel Borkmann, sdf, dthaler1968; +Cc: bpf, bpf
Daniel Borkmann wrote:
[...]
> >> +Also note that the division and modulo operations are unsigned,
> >> +where 'imm' is first sign extended to 64 bits and then converted to
> >> +an unsigned 64-bit value. There are no instructions for signed
> >> +division or modulo.
> >
> > Less sure about this part, but it looks to be true at least by looking
> > at the interpreter which does:
> >
> > DST = DST / IMM
> >
> > where:
> >
> > DST === (u64) regs[insn->dst_reg]
> > IMM === (s32) insn->imm
> >
> > (and s32 is sign-expanded to u64 according to C rules)
>
> Yeap, the actual operation is in the target width, so for 32 bit it's casted to
> u32, e.g. for modulo (note that the verifier rewrites it into `(src != 0) ?
> (dst % src) : dst` form, so here is just the extract of the plain mod insn and it's
> similar for div):
>
> ALU64_MOD_X:
> div64_u64_rem(DST, SRC, &AX);
> DST = AX;
> CONT;
> ALU_MOD_X:
> AX = (u32) DST;
> DST = do_div(AX, (u32) SRC);
> CONT;
> ALU64_MOD_K:
> div64_u64_rem(DST, IMM, &AX);
> DST = AX;
> CONT;
> ALU_MOD_K:
> AX = (u32) DST;
> DST = do_div(AX, (u32) IMM);
> CONT;
>
> So in above phrasing the middle part needs to be adapted or just removed.
The phrasing was based on the earlier discussion on this list (see
https://lore.kernel.org/bpf/CAADnVQJ387tWd7WgxqfoB44xMe17bY0RRp_Sng3xMnKsywFpxg@mail.gmail.com/) where
Alexei wrote "imm32 is _sign_ extended everywhere",
and I cited the div_k tests in lib/test_bpf.c that assume sign extension
not zero extension.
So I don't know how to reconcile your comments with that thread.
If you do, please educate me :)
Dave
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Bpf] [PATCH] bpf, docs: Fix modulo zero, division by zero, overflow, and underflow
2023-01-06 18:11 ` Dave Thaler
@ 2023-01-06 21:08 ` Daniel Borkmann
0 siblings, 0 replies; 5+ messages in thread
From: Daniel Borkmann @ 2023-01-06 21:08 UTC (permalink / raw)
To: Dave Thaler, sdf, dthaler1968; +Cc: bpf, bpf
On 1/6/23 7:11 PM, Dave Thaler wrote:
> Daniel Borkmann wrote:
> [...]
>>>> +Also note that the division and modulo operations are unsigned,
>>>> +where 'imm' is first sign extended to 64 bits and then converted to
>>>> +an unsigned 64-bit value. There are no instructions for signed
>>>> +division or modulo.
>>>
>>> Less sure about this part, but it looks to be true at least by looking
>>> at the interpreter which does:
>>>
>>> DST = DST / IMM
>>>
>>> where:
>>>
>>> DST === (u64) regs[insn->dst_reg]
>>> IMM === (s32) insn->imm
>>>
>>> (and s32 is sign-expanded to u64 according to C rules)
>>
>> Yeap, the actual operation is in the target width, so for 32 bit it's casted to
>> u32, e.g. for modulo (note that the verifier rewrites it into `(src != 0) ?
>> (dst % src) : dst` form, so here is just the extract of the plain mod insn and it's
>> similar for div):
>>
>> ALU64_MOD_X:
>> div64_u64_rem(DST, SRC, &AX);
>> DST = AX;
>> CONT;
>> ALU_MOD_X:
>> AX = (u32) DST;
>> DST = do_div(AX, (u32) SRC);
>> CONT;
>> ALU64_MOD_K:
>> div64_u64_rem(DST, IMM, &AX);
>> DST = AX;
>> CONT;
>> ALU_MOD_K:
>> AX = (u32) DST;
>> DST = do_div(AX, (u32) IMM);
>> CONT;
>>
>> So in above phrasing the middle part needs to be adapted or just removed.
>
> The phrasing was based on the earlier discussion on this list (see
> https://lore.kernel.org/bpf/CAADnVQJ387tWd7WgxqfoB44xMe17bY0RRp_Sng3xMnKsywFpxg@mail.gmail.com/) where
> Alexei wrote "imm32 is _sign_ extended everywhere",
> and I cited the div_k tests in lib/test_bpf.c that assume sign extension
> not zero extension.
`Where 'imm' is first sign extended to 64 bits and then converted to an unsigned
64-bit value` is true for the 64 bit operation, for the 32-bit it's just converted
to an unsigned 32-bit value, see the (u32)IMM which is (u32)(s32) insn->imm. From
the phrasing, it was a bit less clear perhaps.
Thanks,
Daniel
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2023-01-06 21:08 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-05 16:32 [PATCH] bpf, docs: Fix modulo zero, division by zero, overflow, and underflow dthaler1968
2023-01-05 19:01 ` sdf
2023-01-06 16:27 ` Daniel Borkmann
2023-01-06 18:11 ` Dave Thaler
2023-01-06 21:08 ` [Bpf] " Daniel Borkmann
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).