Commit 512dee0c authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'x86-urgent-2023-01-04' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull misc x86 fixes from Ingo Molnar:
 "Fix a double-free bug, a binutils warning, a header namespace clash
  and a bug in ib_prctl_set()"

* tag 'x86-urgent-2023-01-04' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/bugs: Flush IBP in ib_prctl_set()
  x86/insn: Avoid namespace clash by separating instruction decoder MMIO type from MMIO trace type
  x86/asm: Fix an assembler warning with current binutils
  x86/kexec: Fix double-free of elf header buffer
parents 2ac44821 a664ec91
Loading
Loading
Loading
Loading
+13 −13
Original line number Diff line number Diff line
@@ -386,8 +386,8 @@ static int handle_mmio(struct pt_regs *regs, struct ve_info *ve)
{
	unsigned long *reg, val, vaddr;
	char buffer[MAX_INSN_SIZE];
	enum insn_mmio_type mmio;
	struct insn insn = {};
	enum mmio_type mmio;
	int size, extend_size;
	u8 extend_val = 0;

@@ -402,10 +402,10 @@ static int handle_mmio(struct pt_regs *regs, struct ve_info *ve)
		return -EINVAL;

	mmio = insn_decode_mmio(&insn, &size);
	if (WARN_ON_ONCE(mmio == MMIO_DECODE_FAILED))
	if (WARN_ON_ONCE(mmio == INSN_MMIO_DECODE_FAILED))
		return -EINVAL;

	if (mmio != MMIO_WRITE_IMM && mmio != MMIO_MOVS) {
	if (mmio != INSN_MMIO_WRITE_IMM && mmio != INSN_MMIO_MOVS) {
		reg = insn_get_modrm_reg_ptr(&insn, regs);
		if (!reg)
			return -EINVAL;
@@ -426,23 +426,23 @@ static int handle_mmio(struct pt_regs *regs, struct ve_info *ve)

	/* Handle writes first */
	switch (mmio) {
	case MMIO_WRITE:
	case INSN_MMIO_WRITE:
		memcpy(&val, reg, size);
		if (!mmio_write(size, ve->gpa, val))
			return -EIO;
		return insn.length;
	case MMIO_WRITE_IMM:
	case INSN_MMIO_WRITE_IMM:
		val = insn.immediate.value;
		if (!mmio_write(size, ve->gpa, val))
			return -EIO;
		return insn.length;
	case MMIO_READ:
	case MMIO_READ_ZERO_EXTEND:
	case MMIO_READ_SIGN_EXTEND:
	case INSN_MMIO_READ:
	case INSN_MMIO_READ_ZERO_EXTEND:
	case INSN_MMIO_READ_SIGN_EXTEND:
		/* Reads are handled below */
		break;
	case MMIO_MOVS:
	case MMIO_DECODE_FAILED:
	case INSN_MMIO_MOVS:
	case INSN_MMIO_DECODE_FAILED:
		/*
		 * MMIO was accessed with an instruction that could not be
		 * decoded or handled properly. It was likely not using io.h
@@ -459,15 +459,15 @@ static int handle_mmio(struct pt_regs *regs, struct ve_info *ve)
		return -EIO;

	switch (mmio) {
	case MMIO_READ:
	case INSN_MMIO_READ:
		/* Zero-extend for 32-bit operation */
		extend_size = size == 4 ? sizeof(*reg) : 0;
		break;
	case MMIO_READ_ZERO_EXTEND:
	case INSN_MMIO_READ_ZERO_EXTEND:
		/* Zero extend based on operand size */
		extend_size = insn.opnd_bytes;
		break;
	case MMIO_READ_SIGN_EXTEND:
	case INSN_MMIO_READ_SIGN_EXTEND:
		/* Sign extend based on operand size */
		extend_size = insn.opnd_bytes;
		if (size == 1 && val & BIT(7))
+9 −9
Original line number Diff line number Diff line
@@ -32,16 +32,16 @@ int insn_fetch_from_user_inatomic(struct pt_regs *regs,
bool insn_decode_from_regs(struct insn *insn, struct pt_regs *regs,
			   unsigned char buf[MAX_INSN_SIZE], int buf_size);

enum mmio_type {
	MMIO_DECODE_FAILED,
	MMIO_WRITE,
	MMIO_WRITE_IMM,
	MMIO_READ,
	MMIO_READ_ZERO_EXTEND,
	MMIO_READ_SIGN_EXTEND,
	MMIO_MOVS,
enum insn_mmio_type {
	INSN_MMIO_DECODE_FAILED,
	INSN_MMIO_WRITE,
	INSN_MMIO_WRITE_IMM,
	INSN_MMIO_READ,
	INSN_MMIO_READ_ZERO_EXTEND,
	INSN_MMIO_READ_SIGN_EXTEND,
	INSN_MMIO_MOVS,
};

enum mmio_type insn_decode_mmio(struct insn *insn, int *bytes);
enum insn_mmio_type insn_decode_mmio(struct insn *insn, int *bytes);

#endif /* _ASM_X86_INSN_EVAL_H */
+2 −0
Original line number Diff line number Diff line
@@ -1981,6 +1981,8 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
		if (ctrl == PR_SPEC_FORCE_DISABLE)
			task_set_spec_ib_force_disable(task);
		task_update_spec_tif(task);
		if (task == current)
			indirect_branch_prediction_barrier();
		break;
	default:
		return -ERANGE;
+1 −3
Original line number Diff line number Diff line
@@ -401,10 +401,8 @@ int crash_load_segments(struct kimage *image)
	kbuf.buf_align = ELF_CORE_HEADER_ALIGN;
	kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
	ret = kexec_add_buffer(&kbuf);
	if (ret) {
		vfree((void *)image->elf_headers);
	if (ret)
		return ret;
	}
	image->elf_load_addr = kbuf.mem;
	pr_debug("Loaded ELF headers at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
		 image->elf_load_addr, kbuf.bufsz, kbuf.memsz);
+9 −9
Original line number Diff line number Diff line
@@ -1536,32 +1536,32 @@ static enum es_result vc_handle_mmio_movs(struct es_em_ctxt *ctxt,
static enum es_result vc_handle_mmio(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
{
	struct insn *insn = &ctxt->insn;
	enum insn_mmio_type mmio;
	unsigned int bytes = 0;
	enum mmio_type mmio;
	enum es_result ret;
	u8 sign_byte;
	long *reg_data;

	mmio = insn_decode_mmio(insn, &bytes);
	if (mmio == MMIO_DECODE_FAILED)
	if (mmio == INSN_MMIO_DECODE_FAILED)
		return ES_DECODE_FAILED;

	if (mmio != MMIO_WRITE_IMM && mmio != MMIO_MOVS) {
	if (mmio != INSN_MMIO_WRITE_IMM && mmio != INSN_MMIO_MOVS) {
		reg_data = insn_get_modrm_reg_ptr(insn, ctxt->regs);
		if (!reg_data)
			return ES_DECODE_FAILED;
	}

	switch (mmio) {
	case MMIO_WRITE:
	case INSN_MMIO_WRITE:
		memcpy(ghcb->shared_buffer, reg_data, bytes);
		ret = vc_do_mmio(ghcb, ctxt, bytes, false);
		break;
	case MMIO_WRITE_IMM:
	case INSN_MMIO_WRITE_IMM:
		memcpy(ghcb->shared_buffer, insn->immediate1.bytes, bytes);
		ret = vc_do_mmio(ghcb, ctxt, bytes, false);
		break;
	case MMIO_READ:
	case INSN_MMIO_READ:
		ret = vc_do_mmio(ghcb, ctxt, bytes, true);
		if (ret)
			break;
@@ -1572,7 +1572,7 @@ static enum es_result vc_handle_mmio(struct ghcb *ghcb, struct es_em_ctxt *ctxt)

		memcpy(reg_data, ghcb->shared_buffer, bytes);
		break;
	case MMIO_READ_ZERO_EXTEND:
	case INSN_MMIO_READ_ZERO_EXTEND:
		ret = vc_do_mmio(ghcb, ctxt, bytes, true);
		if (ret)
			break;
@@ -1581,7 +1581,7 @@ static enum es_result vc_handle_mmio(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
		memset(reg_data, 0, insn->opnd_bytes);
		memcpy(reg_data, ghcb->shared_buffer, bytes);
		break;
	case MMIO_READ_SIGN_EXTEND:
	case INSN_MMIO_READ_SIGN_EXTEND:
		ret = vc_do_mmio(ghcb, ctxt, bytes, true);
		if (ret)
			break;
@@ -1600,7 +1600,7 @@ static enum es_result vc_handle_mmio(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
		memset(reg_data, sign_byte, insn->opnd_bytes);
		memcpy(reg_data, ghcb->shared_buffer, bytes);
		break;
	case MMIO_MOVS:
	case INSN_MMIO_MOVS:
		ret = vc_handle_mmio_movs(ctxt, bytes);
		break;
	default:
Loading