mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	KVM: x86: Introduce segmented_write_std
Introduces segemented_write_std. Switches from emulated reads/writes to standard read/writes in fxsave, fxrstor, sgdt, and sidt. This fixes CVE-2017-2584, a longstanding kernel memory leak. Since commit283c95d0e3("KVM: x86: emulate FXSAVE and FXRSTOR", 2016-11-09), which is luckily not yet in any final release, this would also be an exploitable kernel memory *write*! Reported-by: Dmitry Vyukov <dvyukov@google.com> Cc: stable@vger.kernel.org Fixes:96051572c8Fixes:283c95d0e3Suggested-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Steve Rutherford <srutherford@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
		
							parent
							
								
									cef84c302f
								
							
						
					
					
						commit
						129a72a0d3
					
				
					 1 changed files with 18 additions and 4 deletions
				
			
		| 
						 | 
				
			
			@ -818,6 +818,20 @@ static int segmented_read_std(struct x86_emulate_ctxt *ctxt,
 | 
			
		|||
	return ctxt->ops->read_std(ctxt, linear, data, size, &ctxt->exception);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int segmented_write_std(struct x86_emulate_ctxt *ctxt,
 | 
			
		||||
			       struct segmented_address addr,
 | 
			
		||||
			       void *data,
 | 
			
		||||
			       unsigned int size)
 | 
			
		||||
{
 | 
			
		||||
	int rc;
 | 
			
		||||
	ulong linear;
 | 
			
		||||
 | 
			
		||||
	rc = linearize(ctxt, addr, size, true, &linear);
 | 
			
		||||
	if (rc != X86EMUL_CONTINUE)
 | 
			
		||||
		return rc;
 | 
			
		||||
	return ctxt->ops->write_std(ctxt, linear, data, size, &ctxt->exception);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Prefetch the remaining bytes of the instruction without crossing page
 | 
			
		||||
 * boundary if they are not in fetch_cache yet.
 | 
			
		||||
| 
						 | 
				
			
			@ -3685,8 +3699,8 @@ static int emulate_store_desc_ptr(struct x86_emulate_ctxt *ctxt,
 | 
			
		|||
	}
 | 
			
		||||
	/* Disable writeback. */
 | 
			
		||||
	ctxt->dst.type = OP_NONE;
 | 
			
		||||
	return segmented_write(ctxt, ctxt->dst.addr.mem,
 | 
			
		||||
			       &desc_ptr, 2 + ctxt->op_bytes);
 | 
			
		||||
	return segmented_write_std(ctxt, ctxt->dst.addr.mem,
 | 
			
		||||
				   &desc_ptr, 2 + ctxt->op_bytes);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int em_sgdt(struct x86_emulate_ctxt *ctxt)
 | 
			
		||||
| 
						 | 
				
			
			@ -3932,7 +3946,7 @@ static int em_fxsave(struct x86_emulate_ctxt *ctxt)
 | 
			
		|||
	else
 | 
			
		||||
		size = offsetof(struct fxregs_state, xmm_space[0]);
 | 
			
		||||
 | 
			
		||||
	return segmented_write(ctxt, ctxt->memop.addr.mem, &fx_state, size);
 | 
			
		||||
	return segmented_write_std(ctxt, ctxt->memop.addr.mem, &fx_state, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int fxrstor_fixup(struct x86_emulate_ctxt *ctxt,
 | 
			
		||||
| 
						 | 
				
			
			@ -3974,7 +3988,7 @@ static int em_fxrstor(struct x86_emulate_ctxt *ctxt)
 | 
			
		|||
	if (rc != X86EMUL_CONTINUE)
 | 
			
		||||
		return rc;
 | 
			
		||||
 | 
			
		||||
	rc = segmented_read(ctxt, ctxt->memop.addr.mem, &fx_state, 512);
 | 
			
		||||
	rc = segmented_read_std(ctxt, ctxt->memop.addr.mem, &fx_state, 512);
 | 
			
		||||
	if (rc != X86EMUL_CONTINUE)
 | 
			
		||||
		return rc;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue