Patch "riscv, bpf: Sign-extend return values" has been added to the 5.10-stable tree

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

 



This is a note to let you know that I've just added the patch titled

    riscv, bpf: Sign-extend return values

to the 5.10-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     riscv-bpf-sign-extend-return-values.patch
and it can be found in the queue-5.10 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit d3e537c17954a8f71e5ff8b1a38915c68ec9d5de
Author: Björn Töpel <bjorn@xxxxxxxxxxxx>
Date:   Wed Oct 4 14:07:05 2023 +0200

    riscv, bpf: Sign-extend return values
    
    [ Upstream commit 2f1b0d3d733169eb11680bfa97c266ae5e757148 ]
    
    The RISC-V architecture does not expose sub-registers, and hold all
    32-bit values in a sign-extended format [1] [2]:
    
      | The compiler and calling convention maintain an invariant that all
      | 32-bit values are held in a sign-extended format in 64-bit
      | registers. Even 32-bit unsigned integers extend bit 31 into bits
      | 63 through 32. Consequently, conversion between unsigned and
      | signed 32-bit integers is a no-op, as is conversion from a signed
      | 32-bit integer to a signed 64-bit integer.
    
    While BPF, on the other hand, exposes sub-registers, and use
    zero-extension (similar to arm64/x86).
    
    This has led to some subtle bugs, where a BPF JITted program has not
    sign-extended the a0 register (return value in RISC-V land), passed
    the return value up the kernel, e.g.:
    
      | int from_bpf(void);
      |
      | long foo(void)
      | {
      |    return from_bpf();
      | }
    
    Here, a0 would be 0xffff_ffff, instead of the expected
    0xffff_ffff_ffff_ffff.
    
    Internally, the RISC-V JIT uses a5 as a dedicated register for BPF
    return values.
    
    Keep a5 zero-extended, but explicitly sign-extend a0 (which is used
    outside BPF land). Now that a0 (RISC-V ABI) and a5 (BPF ABI) differs,
    a0 is only moved to a5 for non-BPF native calls (BPF_PSEUDO_CALL).
    
    Fixes: 2353ecc6f91f ("bpf, riscv: add BPF JIT for RV64G")
    Signed-off-by: Björn Töpel <bjorn@xxxxxxxxxxxx>
    Signed-off-by: Daniel Borkmann <daniel@xxxxxxxxxxxxx>
    Link: https://github.com/riscv/riscv-isa-manual/releases/download/riscv-isa-release-056b6ff-2023-10-02/unpriv-isa-asciidoc.pdf # [2]
    Link: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/releases/download/draft-20230929-e5c800e661a53efe3c2678d71a306323b60eb13b/riscv-abi.pdf # [2]
    Link: https://lore.kernel.org/bpf/20231004120706.52848-2-bjorn@xxxxxxxxxx
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index 53d1f520c5890..0cc3dd9d32e64 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -201,7 +201,7 @@ static void __build_epilogue(bool is_tail_call, struct rv_jit_context *ctx)
 	emit_addi(RV_REG_SP, RV_REG_SP, stack_adjust, ctx);
 	/* Set return value. */
 	if (!is_tail_call)
-		emit_mv(RV_REG_A0, RV_REG_A5, ctx);
+		emit_addiw(RV_REG_A0, RV_REG_A5, 0, ctx);
 	emit_jalr(RV_REG_ZERO, is_tail_call ? RV_REG_T3 : RV_REG_RA,
 		  is_tail_call ? 4 : 0, /* skip TCC init */
 		  ctx);
@@ -856,7 +856,8 @@ int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
 		if (ret)
 			return ret;
 
-		emit_mv(bpf_to_rv_reg(BPF_REG_0, ctx), RV_REG_A0, ctx);
+		if (insn->src_reg != BPF_PSEUDO_CALL)
+			emit_mv(bpf_to_rv_reg(BPF_REG_0, ctx), RV_REG_A0, ctx);
 		break;
 	}
 	/* tail call */



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux