Re: [Bpf] [PATCH] bpf, docs: Fix modulo zero, division by zero, overflow, and underflow

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxxxxx/) 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



[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux