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

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
...@@ -386,8 +386,8 @@ static int handle_mmio(struct pt_regs *regs, struct ve_info *ve) ...@@ -386,8 +386,8 @@ static int handle_mmio(struct pt_regs *regs, struct ve_info *ve)
{ {
unsigned long *reg, val, vaddr; unsigned long *reg, val, vaddr;
char buffer[MAX_INSN_SIZE]; char buffer[MAX_INSN_SIZE];
enum insn_mmio_type mmio;
struct insn insn = {}; struct insn insn = {};
enum mmio_type mmio;
int size, extend_size; int size, extend_size;
u8 extend_val = 0; u8 extend_val = 0;
...@@ -402,10 +402,10 @@ static int handle_mmio(struct pt_regs *regs, struct ve_info *ve) ...@@ -402,10 +402,10 @@ static int handle_mmio(struct pt_regs *regs, struct ve_info *ve)
return -EINVAL; return -EINVAL;
mmio = insn_decode_mmio(&insn, &size); 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; 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); reg = insn_get_modrm_reg_ptr(&insn, regs);
if (!reg) if (!reg)
return -EINVAL; return -EINVAL;
...@@ -426,23 +426,23 @@ static int handle_mmio(struct pt_regs *regs, struct ve_info *ve) ...@@ -426,23 +426,23 @@ static int handle_mmio(struct pt_regs *regs, struct ve_info *ve)
/* Handle writes first */ /* Handle writes first */
switch (mmio) { switch (mmio) {
case MMIO_WRITE: case INSN_MMIO_WRITE:
memcpy(&val, reg, size); memcpy(&val, reg, size);
if (!mmio_write(size, ve->gpa, val)) if (!mmio_write(size, ve->gpa, val))
return -EIO; return -EIO;
return insn.length; return insn.length;
case MMIO_WRITE_IMM: case INSN_MMIO_WRITE_IMM:
val = insn.immediate.value; val = insn.immediate.value;
if (!mmio_write(size, ve->gpa, val)) if (!mmio_write(size, ve->gpa, val))
return -EIO; return -EIO;
return insn.length; return insn.length;
case MMIO_READ: case INSN_MMIO_READ:
case MMIO_READ_ZERO_EXTEND: case INSN_MMIO_READ_ZERO_EXTEND:
case MMIO_READ_SIGN_EXTEND: case INSN_MMIO_READ_SIGN_EXTEND:
/* Reads are handled below */ /* Reads are handled below */
break; break;
case MMIO_MOVS: case INSN_MMIO_MOVS:
case MMIO_DECODE_FAILED: case INSN_MMIO_DECODE_FAILED:
/* /*
* MMIO was accessed with an instruction that could not be * MMIO was accessed with an instruction that could not be
* decoded or handled properly. It was likely not using io.h * 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) ...@@ -459,15 +459,15 @@ static int handle_mmio(struct pt_regs *regs, struct ve_info *ve)
return -EIO; return -EIO;
switch (mmio) { switch (mmio) {
case MMIO_READ: case INSN_MMIO_READ:
/* Zero-extend for 32-bit operation */ /* Zero-extend for 32-bit operation */
extend_size = size == 4 ? sizeof(*reg) : 0; extend_size = size == 4 ? sizeof(*reg) : 0;
break; break;
case MMIO_READ_ZERO_EXTEND: case INSN_MMIO_READ_ZERO_EXTEND:
/* Zero extend based on operand size */ /* Zero extend based on operand size */
extend_size = insn.opnd_bytes; extend_size = insn.opnd_bytes;
break; break;
case MMIO_READ_SIGN_EXTEND: case INSN_MMIO_READ_SIGN_EXTEND:
/* Sign extend based on operand size */ /* Sign extend based on operand size */
extend_size = insn.opnd_bytes; extend_size = insn.opnd_bytes;
if (size == 1 && val & BIT(7)) if (size == 1 && val & BIT(7))
......
...@@ -32,16 +32,16 @@ int insn_fetch_from_user_inatomic(struct pt_regs *regs, ...@@ -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, bool insn_decode_from_regs(struct insn *insn, struct pt_regs *regs,
unsigned char buf[MAX_INSN_SIZE], int buf_size); unsigned char buf[MAX_INSN_SIZE], int buf_size);
enum mmio_type { enum insn_mmio_type {
MMIO_DECODE_FAILED, INSN_MMIO_DECODE_FAILED,
MMIO_WRITE, INSN_MMIO_WRITE,
MMIO_WRITE_IMM, INSN_MMIO_WRITE_IMM,
MMIO_READ, INSN_MMIO_READ,
MMIO_READ_ZERO_EXTEND, INSN_MMIO_READ_ZERO_EXTEND,
MMIO_READ_SIGN_EXTEND, INSN_MMIO_READ_SIGN_EXTEND,
MMIO_MOVS, 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 */ #endif /* _ASM_X86_INSN_EVAL_H */
...@@ -1981,6 +1981,8 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl) ...@@ -1981,6 +1981,8 @@ static int ib_prctl_set(struct task_struct *task, unsigned long ctrl)
if (ctrl == PR_SPEC_FORCE_DISABLE) if (ctrl == PR_SPEC_FORCE_DISABLE)
task_set_spec_ib_force_disable(task); task_set_spec_ib_force_disable(task);
task_update_spec_tif(task); task_update_spec_tif(task);
if (task == current)
indirect_branch_prediction_barrier();
break; break;
default: default:
return -ERANGE; return -ERANGE;
......
...@@ -401,10 +401,8 @@ int crash_load_segments(struct kimage *image) ...@@ -401,10 +401,8 @@ int crash_load_segments(struct kimage *image)
kbuf.buf_align = ELF_CORE_HEADER_ALIGN; kbuf.buf_align = ELF_CORE_HEADER_ALIGN;
kbuf.mem = KEXEC_BUF_MEM_UNKNOWN; kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
ret = kexec_add_buffer(&kbuf); ret = kexec_add_buffer(&kbuf);
if (ret) { if (ret)
vfree((void *)image->elf_headers);
return ret; return ret;
}
image->elf_load_addr = kbuf.mem; image->elf_load_addr = kbuf.mem;
pr_debug("Loaded ELF headers at 0x%lx bufsz=0x%lx memsz=0x%lx\n", pr_debug("Loaded ELF headers at 0x%lx bufsz=0x%lx memsz=0x%lx\n",
image->elf_load_addr, kbuf.bufsz, kbuf.memsz); image->elf_load_addr, kbuf.bufsz, kbuf.memsz);
......
...@@ -1536,32 +1536,32 @@ static enum es_result vc_handle_mmio_movs(struct es_em_ctxt *ctxt, ...@@ -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) static enum es_result vc_handle_mmio(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
{ {
struct insn *insn = &ctxt->insn; struct insn *insn = &ctxt->insn;
enum insn_mmio_type mmio;
unsigned int bytes = 0; unsigned int bytes = 0;
enum mmio_type mmio;
enum es_result ret; enum es_result ret;
u8 sign_byte; u8 sign_byte;
long *reg_data; long *reg_data;
mmio = insn_decode_mmio(insn, &bytes); mmio = insn_decode_mmio(insn, &bytes);
if (mmio == MMIO_DECODE_FAILED) if (mmio == INSN_MMIO_DECODE_FAILED)
return ES_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); reg_data = insn_get_modrm_reg_ptr(insn, ctxt->regs);
if (!reg_data) if (!reg_data)
return ES_DECODE_FAILED; return ES_DECODE_FAILED;
} }
switch (mmio) { switch (mmio) {
case MMIO_WRITE: case INSN_MMIO_WRITE:
memcpy(ghcb->shared_buffer, reg_data, bytes); memcpy(ghcb->shared_buffer, reg_data, bytes);
ret = vc_do_mmio(ghcb, ctxt, bytes, false); ret = vc_do_mmio(ghcb, ctxt, bytes, false);
break; break;
case MMIO_WRITE_IMM: case INSN_MMIO_WRITE_IMM:
memcpy(ghcb->shared_buffer, insn->immediate1.bytes, bytes); memcpy(ghcb->shared_buffer, insn->immediate1.bytes, bytes);
ret = vc_do_mmio(ghcb, ctxt, bytes, false); ret = vc_do_mmio(ghcb, ctxt, bytes, false);
break; break;
case MMIO_READ: case INSN_MMIO_READ:
ret = vc_do_mmio(ghcb, ctxt, bytes, true); ret = vc_do_mmio(ghcb, ctxt, bytes, true);
if (ret) if (ret)
break; break;
...@@ -1572,7 +1572,7 @@ static enum es_result vc_handle_mmio(struct ghcb *ghcb, struct es_em_ctxt *ctxt) ...@@ -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); memcpy(reg_data, ghcb->shared_buffer, bytes);
break; break;
case MMIO_READ_ZERO_EXTEND: case INSN_MMIO_READ_ZERO_EXTEND:
ret = vc_do_mmio(ghcb, ctxt, bytes, true); ret = vc_do_mmio(ghcb, ctxt, bytes, true);
if (ret) if (ret)
break; break;
...@@ -1581,7 +1581,7 @@ static enum es_result vc_handle_mmio(struct ghcb *ghcb, struct es_em_ctxt *ctxt) ...@@ -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); memset(reg_data, 0, insn->opnd_bytes);
memcpy(reg_data, ghcb->shared_buffer, bytes); memcpy(reg_data, ghcb->shared_buffer, bytes);
break; break;
case MMIO_READ_SIGN_EXTEND: case INSN_MMIO_READ_SIGN_EXTEND:
ret = vc_do_mmio(ghcb, ctxt, bytes, true); ret = vc_do_mmio(ghcb, ctxt, bytes, true);
if (ret) if (ret)
break; break;
...@@ -1600,7 +1600,7 @@ static enum es_result vc_handle_mmio(struct ghcb *ghcb, struct es_em_ctxt *ctxt) ...@@ -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); memset(reg_data, sign_byte, insn->opnd_bytes);
memcpy(reg_data, ghcb->shared_buffer, bytes); memcpy(reg_data, ghcb->shared_buffer, bytes);
break; break;
case MMIO_MOVS: case INSN_MMIO_MOVS:
ret = vc_handle_mmio_movs(ctxt, bytes); ret = vc_handle_mmio_movs(ctxt, bytes);
break; break;
default: default:
......
...@@ -1595,16 +1595,16 @@ bool insn_decode_from_regs(struct insn *insn, struct pt_regs *regs, ...@@ -1595,16 +1595,16 @@ bool insn_decode_from_regs(struct insn *insn, struct pt_regs *regs,
* Returns: * Returns:
* *
* Type of the instruction. Size of the memory operand is stored in * Type of the instruction. Size of the memory operand is stored in
* @bytes. If decode failed, MMIO_DECODE_FAILED returned. * @bytes. If decode failed, INSN_MMIO_DECODE_FAILED returned.
*/ */
enum mmio_type insn_decode_mmio(struct insn *insn, int *bytes) enum insn_mmio_type insn_decode_mmio(struct insn *insn, int *bytes)
{ {
enum mmio_type type = MMIO_DECODE_FAILED; enum insn_mmio_type type = INSN_MMIO_DECODE_FAILED;
*bytes = 0; *bytes = 0;
if (insn_get_opcode(insn)) if (insn_get_opcode(insn))
return MMIO_DECODE_FAILED; return INSN_MMIO_DECODE_FAILED;
switch (insn->opcode.bytes[0]) { switch (insn->opcode.bytes[0]) {
case 0x88: /* MOV m8,r8 */ case 0x88: /* MOV m8,r8 */
...@@ -1613,7 +1613,7 @@ enum mmio_type insn_decode_mmio(struct insn *insn, int *bytes) ...@@ -1613,7 +1613,7 @@ enum mmio_type insn_decode_mmio(struct insn *insn, int *bytes)
case 0x89: /* MOV m16/m32/m64, r16/m32/m64 */ case 0x89: /* MOV m16/m32/m64, r16/m32/m64 */
if (!*bytes) if (!*bytes)
*bytes = insn->opnd_bytes; *bytes = insn->opnd_bytes;
type = MMIO_WRITE; type = INSN_MMIO_WRITE;
break; break;
case 0xc6: /* MOV m8, imm8 */ case 0xc6: /* MOV m8, imm8 */
...@@ -1622,7 +1622,7 @@ enum mmio_type insn_decode_mmio(struct insn *insn, int *bytes) ...@@ -1622,7 +1622,7 @@ enum mmio_type insn_decode_mmio(struct insn *insn, int *bytes)
case 0xc7: /* MOV m16/m32/m64, imm16/imm32/imm64 */ case 0xc7: /* MOV m16/m32/m64, imm16/imm32/imm64 */
if (!*bytes) if (!*bytes)
*bytes = insn->opnd_bytes; *bytes = insn->opnd_bytes;
type = MMIO_WRITE_IMM; type = INSN_MMIO_WRITE_IMM;
break; break;
case 0x8a: /* MOV r8, m8 */ case 0x8a: /* MOV r8, m8 */
...@@ -1631,7 +1631,7 @@ enum mmio_type insn_decode_mmio(struct insn *insn, int *bytes) ...@@ -1631,7 +1631,7 @@ enum mmio_type insn_decode_mmio(struct insn *insn, int *bytes)
case 0x8b: /* MOV r16/r32/r64, m16/m32/m64 */ case 0x8b: /* MOV r16/r32/r64, m16/m32/m64 */
if (!*bytes) if (!*bytes)
*bytes = insn->opnd_bytes; *bytes = insn->opnd_bytes;
type = MMIO_READ; type = INSN_MMIO_READ;
break; break;
case 0xa4: /* MOVS m8, m8 */ case 0xa4: /* MOVS m8, m8 */
...@@ -1640,7 +1640,7 @@ enum mmio_type insn_decode_mmio(struct insn *insn, int *bytes) ...@@ -1640,7 +1640,7 @@ enum mmio_type insn_decode_mmio(struct insn *insn, int *bytes)
case 0xa5: /* MOVS m16/m32/m64, m16/m32/m64 */ case 0xa5: /* MOVS m16/m32/m64, m16/m32/m64 */
if (!*bytes) if (!*bytes)
*bytes = insn->opnd_bytes; *bytes = insn->opnd_bytes;
type = MMIO_MOVS; type = INSN_MMIO_MOVS;
break; break;
case 0x0f: /* Two-byte instruction */ case 0x0f: /* Two-byte instruction */
...@@ -1651,7 +1651,7 @@ enum mmio_type insn_decode_mmio(struct insn *insn, int *bytes) ...@@ -1651,7 +1651,7 @@ enum mmio_type insn_decode_mmio(struct insn *insn, int *bytes)
case 0xb7: /* MOVZX r32/r64, m16 */ case 0xb7: /* MOVZX r32/r64, m16 */
if (!*bytes) if (!*bytes)
*bytes = 2; *bytes = 2;
type = MMIO_READ_ZERO_EXTEND; type = INSN_MMIO_READ_ZERO_EXTEND;
break; break;
case 0xbe: /* MOVSX r16/r32/r64, m8 */ case 0xbe: /* MOVSX r16/r32/r64, m8 */
...@@ -1660,7 +1660,7 @@ enum mmio_type insn_decode_mmio(struct insn *insn, int *bytes) ...@@ -1660,7 +1660,7 @@ enum mmio_type insn_decode_mmio(struct insn *insn, int *bytes)
case 0xbf: /* MOVSX r32/r64, m16 */ case 0xbf: /* MOVSX r32/r64, m16 */
if (!*bytes) if (!*bytes)
*bytes = 2; *bytes = 2;
type = MMIO_READ_SIGN_EXTEND; type = INSN_MMIO_READ_SIGN_EXTEND;
break; break;
} }
break; break;
......
...@@ -10,6 +10,6 @@ ...@@ -10,6 +10,6 @@
*/ */
SYM_FUNC_START(__iowrite32_copy) SYM_FUNC_START(__iowrite32_copy)
movl %edx,%ecx movl %edx,%ecx
rep movsd rep movsl
RET RET
SYM_FUNC_END(__iowrite32_copy) SYM_FUNC_END(__iowrite32_copy)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment