lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <534755B6.3040102@hitachi.com>
Date:	Fri, 11 Apr 2014 11:38:46 +0900
From:	Masami Hiramatsu <masami.hiramatsu.pt@...achi.com>
To:	Oleg Nesterov <oleg@...hat.com>
Cc:	Denys Vlasenko <dvlasenk@...hat.com>,
	Jim Keniston <jkenisto@...ux.vnet.ibm.com>,
	Ingo Molnar <mingo@...e.hu>,
	Srikar Dronamraju <srikar@...ux.vnet.ibm.com>,
	Ananth N Mavinakayanahalli <ananth@...ibm.com>,
	Anton Arapov <aarapov@...hat.com>,
	David Long <dave.long@...aro.org>,
	"Frank Ch. Eigler" <fche@...hat.com>,
	Jonathan Lebon <jlebon@...hat.com>,
	linux-kernel@...r.kernel.org
Subject: Re: [RFC PATCH 4/6] uprobes/x86: Emulate rip-relative call's

(2014/04/11 2:00), Oleg Nesterov wrote:
> On 04/10, Oleg Nesterov wrote:
>>
>> On 04/10, Masami Hiramatsu wrote:
>>>
>>> (2014/04/10 22:41), Denys Vlasenko wrote:
>>>> There is this monstrosity, "16-bit override for branches" in 64-mode:
>>>>
>>>> 66 e8 nn nn       callw   <offset16>
>>>>
>>>> Nobody sane uses it because it truncates instruction pointer.
>>>
>>> No problem, insn.c can handle that too. :)
>>
>> Does it?
>>
>> 	"callw 1f; 1:\n"
>> 	"rep; nop\n"
>>
>> objdump:
>>
>> 	66 e8 00 00             callw  485 <_init-0x3ffed3>
>> 	f3 90                   pause
>>
>>
>> if we probe this "callw", we copy MAX_INSN_BYTES into auprobe->insn,
>> and after insn_get_length() (insn_complete() == T)
>>
>> 	// this is correct
>> 	OPCODE1() == e8
>>
>> 	// this all looks wrong
>> 	insn->length == 6
>> 	insn->immediate.value == -1863122944
>> 	insn->immediate.nbytes == 4
>>
>> so it seems that lib/insn.c treats the next "pause" insn as the high
>> 16 bits of address.
> 
> Or perhaps lib/insn.c is fine but objdump is wrong? And everything
> should work correctly? Although in this case I do not understand what
> this "callw" actually does.

Yeah, I think objdump is wrong. see below.

> 
> 	int main(void)
> 	{
> 		asm (
> 			"nop\n"
> 
> 			"callw 1f; 1:\n"
> 			".byte 0\n"
> 			".byte 0\n"
> 		);
> 
> 		return 0;
> 	}
> 
> this runs just fine. With or without gdb. And gdb shows that ->ip is
> incremented by 6 after "callw".
> 
> 	int main(void)
> 	{
> 		asm (
> 			"nop\n"
> 
> 			"callw 1f; 1:\n"
> 			".byte 10\n"
> 			".byte 20\n"
> 		);
> 
> 		return 0;
> 	}
> 
> objdump:
> 
> 	000000000040047c <main>:
> 	  40047c:       55                      push   %rbp
> 	  40047d:       48 89 e5                mov    %rsp,%rbp
> 	  400480:       90                      nop
> 	  400481:       66 e8 00 00             callw  485 <_init-0x3ffed3>
> 	  400485:       0a 14 b8                or     (%rax,%rdi,4),%dl
> 	  400488:       00 00                   add    %al,(%rax)
> 	  40048a:       00 00                   add    %al,(%rax)
> 	  40048c:       c9                      leaveq
> 	  40048d:       c3                      retq
> 
> run:
> 
> 	$ ./t
> 	Segmentation fault (core dumped)
> 
> 	$ gdb ./t core.*
> 	...
> 	#0  0x00000000144a0487 in ?? ()
> 
> 0x144a0487 - 0x400481 == 0x140a0006, this matches the additional 2 .bytes treated
> as offset.

Ah, OK. Ive also forgotten the operand size prefix on x86/x86-64.

The callw is actually "call with operand-size override prefix".
The operand-size prefix(0x66) changes the number of bytes (size) of
its operand (including immediate). But that depends on the opcode.

As I said, opcode 0xe8 (call) has Jz operand (jump offset immediate
with 16bit or 32bit size, depends on the operand size).
And on x86-32, the default operand-size is 4bytes, and it
changes to 2bytes with the 0x66 prefix. This means that the "66 e8"
becomes "callw" on x86-32.

However, please see Intel SDM 2b, appendix A,
A.2.5 Superscripts Utilized in Opcode Tables
----
f64
The operand size is forced to a 64-bit operand size when in 64-bit mode
(prefixes that change operand size are ignored for this instruction in 64-bit
mode
----
And Table A-2. One-byte Opcode Map: (08H — FFH)
-----
CALL(f64) Jz
-----

Ah, I got this. This means that "call" on x86-64 never be "callw",
because the operand-size always 64bit, and in that case, immediate
is 4 bytes(*).

(*) again, at A.2.2 Codes for Operand Type
---
z Word for 16-bit operand-size or doubleword for 32 or 64-bit operand-size.
---

So, at least for this case, objdump is wrong. lib/insn.c is correct. :)

Thank you,

-- 
Masami HIRAMATSU
Software Platform Research Dept. Linux Technology Center
Hitachi, Ltd., Yokohama Research Laboratory
E-mail: masami.hiramatsu.pt@...achi.com


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ