Commit 4c9174d9 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()

stable inclusion
from stable-v6.6.37
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=e60adf513275c3a38e5cb67f7fd12387e43a3ff5

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

[ Upstream commit e60adf513275c3a38e5cb67f7fd12387e43a3ff5 ]

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:
        arch/arm64/net/bpf_jit_comp.c
        arch/powerpc/net/bpf_jit_comp.c
        arch/sw_64/net/bpf_jit_comp.c
[Check return values of bpf_jit_binary_lock_ro() to avoid return values uncheck waring]
Signed-off-by: default avatarYuan Can <yuancan@huawei.com>
parent 81a41d2a
Loading
Loading
Loading
Loading
+12 −13
Original line number Diff line number Diff line
@@ -1982,28 +1982,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;
@@ -2020,5 +2013,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
@@ -1648,7 +1648,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;
+16 −6
Original line number Diff line number Diff line
@@ -1206,16 +1206,19 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
	flush_icache_range((unsigned long)header, (unsigned long)(ctx.image + ctx.idx));

	if (!prog->is_func || extra_pass) {
		int err;

		if (extra_pass && ctx.idx != jit_data->ctx.idx) {
			pr_err_once("multi-func JIT bug %d != %d\n",
				    ctx.idx, jit_data->ctx.idx);
			bpf_jit_binary_free(header);
			prog->bpf_func = NULL;
			prog->jited = 0;
			prog->jited_len = 0;
			goto out_offset;
			goto out_free;
		}
		err = bpf_jit_binary_lock_ro(header);
		if (err) {
			pr_err_once("bpf_jit_binary_lock_ro() returned %d\n",
				    err);
			goto out_free;
		}
		bpf_jit_binary_lock_ro(header);
	} else {
		jit_data->ctx = ctx;
		jit_data->image = image_ptr;
@@ -1246,6 +1249,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
	out_offset = -1;

	return prog;

out_free:
	bpf_jit_binary_free(header);
	prog->bpf_func = NULL;
	prog->jited = 0;
	prog->jited_len = 0;
	goto out_offset;
}

/* Indicate the JIT backend supports mixing bpf2bpf and tailcalls. */
+2 −1
Original line number Diff line number Diff line
@@ -1012,7 +1012,8 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog)
	bpf_prog_fill_jited_linfo(prog, &ctx.descriptors[1]);

	/* Set as read-only exec and flush instruction cache */
	bpf_jit_binary_lock_ro(header);
	if (bpf_jit_binary_lock_ro(header))
		goto out_err;
	flush_icache_range((unsigned long)header,
			   (unsigned long)&ctx.target[ctx.jit_index]);

+7 −1
Original line number Diff line number Diff line
@@ -167,7 +167,13 @@ 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->bpf_func = NULL;
			prog->jited = 0;
			prog->jited_len = 0;
			goto out_offset;
		}
		prologue_len = ctx->epilogue_offset - ctx->body_len;
		for (i = 0; i < prog->len; i++)
			ctx->offset[i] += prologue_len;
Loading