Commit 3462233d authored by Christophe Leroy's avatar Christophe Leroy Committed by Yuan Can
Browse files

bpf: Take return from set_memory_rox() into account with bpf_jit_binary_lock_ro()

mainline inclusion
from mainline-v6.10-rc1
commit e60adf513275c3a38e5cb67f7fd12387e43a3ff5
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IAGEOD
CVE: CVE-2024-42067

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=e60adf513275

--------------------------------

set_memory_rox() can fail, leaving memory unprotected.

Check return and bail out when bpf_jit_binary_lock_ro() returns
an error.

Link: https://github.com/KSPP/linux/issues/7


Signed-off-by: default avatarChristophe Leroy <christophe.leroy@csgroup.eu>
Cc: linux-hardening@vger.kernel.org <linux-hardening@vger.kernel.org>
Reviewed-by: default avatarKees Cook <keescook@chromium.org>
Reviewed-by: default avatarPuranjay Mohan <puranjay12@gmail.com>
Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com>  # s390x
Acked-by: Tiezhu Yang <yangtiezhu@loongson.cn>  # LoongArch
Reviewed-by: Johan Almbladh <johan.almbladh@anyfinetworks.com> # MIPS Part
Message-ID: <036b6393f23a2032ce75a1c92220b2afcb798d5d.1709850515.git.christophe.leroy@csgroup.eu>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Conflicts:
        include/linux/filter.h
        arch/sparc/net/bpf_jit_comp_64.c
        arch/loongarch/net/bpf_jit.c
        arch/parisc/net/bpf_jit_core.c
        arch/arm/net/bpf_jit_32.c
        arch/mips/net/bpf_jit_comp.c
	arch/arm64/net/bpf_jit_comp.c
	arch/riscv/net/bpf_jit_core.c
	arch/x86/net/bpf_jit_comp.c
[some context conflict and unintroduced files on 5.10]
Signed-off-by: default avatarYuan Can <yuancan@huawei.com>
parent 748eeb7d
Loading
Loading
Loading
Loading
+12 −13
Original line number Diff line number Diff line
@@ -2003,28 +2003,21 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
	/* If building the body of the JITed code fails somehow,
	 * we fall back to the interpretation.
	 */
	if (build_body(&ctx) < 0) {
		image_ptr = NULL;
		bpf_jit_binary_free(header);
		prog = orig_prog;
		goto out_imms;
	}
	if (build_body(&ctx) < 0)
		goto out_free;
	build_epilogue(&ctx);

	/* 3.) Extra pass to validate JITed Code */
	if (validate_code(&ctx)) {
		image_ptr = NULL;
		bpf_jit_binary_free(header);
		prog = orig_prog;
		goto out_imms;
	}
	if (validate_code(&ctx))
		goto out_free;
	flush_icache_range((u32)header, (u32)(ctx.target + ctx.idx));

	if (bpf_jit_enable > 1)
		/* there are 2 passes here */
		bpf_jit_dump(prog->len, image_size, 2, ctx.target);

	bpf_jit_binary_lock_ro(header);
	if (bpf_jit_binary_lock_ro(header))
		goto out_free;
	prog->bpf_func = (void *)ctx.target;
	prog->jited = 1;
	prog->jited_len = image_size;
@@ -2041,5 +2034,11 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
		bpf_jit_prog_release_other(prog, prog == orig_prog ?
					   tmp : orig_prog);
	return prog;

out_free:
	image_ptr = NULL;
	bpf_jit_binary_free(header);
	prog = orig_prog;
	goto out_imms;
}
+8 −1
Original line number Diff line number Diff line
@@ -1425,7 +1425,14 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
			prog->jited_len = 0;
			goto out_off;
		}
		bpf_jit_binary_lock_ro(header);
		if (bpf_jit_binary_lock_ro(header)) {
			bpf_jit_binary_free(header);
			prog = orig_prog;
			prog->bpf_func = NULL;
			prog->jited = 0;
			prog->jited_len = 0;
			goto out_off;
		}
	} else {
		jit_data->ctx = ctx;
		jit_data->image = image_ptr;
+2 −1
Original line number Diff line number Diff line
@@ -1912,7 +1912,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
		/* Dump JIT code */
		bpf_jit_dump(prog->len, image_size, 2, ctx.target);

	bpf_jit_binary_lock_ro(header);
	if (bpf_jit_binary_lock_ro(header))
		goto out_err;
	prog->bpf_func = (void *)ctx.target;
	prog->jited = 1;
	prog->jited_len = image_size;
+8 −1
Original line number Diff line number Diff line
@@ -163,7 +163,14 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
	bpf_flush_icache(jit_data->header, ctx->insns + ctx->ninsns);

	if (!prog->is_func || extra_pass) {
		bpf_jit_binary_lock_ro(jit_data->header);
		if (bpf_jit_binary_lock_ro(jit_data->header)) {
			bpf_jit_binary_free(jit_data->header);
			prog = orig_prog;
			prog->bpf_func = NULL;
			prog->jited = 0;
			prog->jited_len = 0;
			goto out_offset;
		}
		for (i = 0; i < prog->len; i++)
			ctx->offset[i] = ninsns_rvoff(ctx->offset[i]);
		bpf_prog_fill_jited_linfo(prog, ctx->offset);
+5 −1
Original line number Diff line number Diff line
@@ -1807,7 +1807,11 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
		print_fn_code(jit.prg_buf, jit.size_prg);
	}
	if (!fp->is_func || extra_pass) {
		bpf_jit_binary_lock_ro(header);
		if (bpf_jit_binary_lock_ro(header)) {
			bpf_jit_binary_free(header);
			fp = orig_fp;
			goto free_addrs;
		}
	} else {
		jit_data->header = header;
		jit_data->ctx = jit;
Loading