Subject: 25.0.50; struct selection_input_event data might be corrupted by assignments as another structure type

From: YAMAMOTO Mitsuharu <[email-masked]>
Date: Sun, 07 Jun 2015 17:13:31 +0900

On X11, each element of `kbd_buffer' is implicitly used as a union of
two structure types: `struct input_event' (in termhooks.h) for general
use and `struct selection_input_event' (in xterm.h) for selection
events.  These types have different layouts, especially with respect
to paddings.  But elements of `kbd_buffer' are copied via assignments
for one structure type, `struct input_event', in several places in
keyboard.c.  For example,

  3685	/* Put an input event back in the head of the event queue.  */
  3686	
  3687	void
  3688	kbd_buffer_unget_event (register struct input_event *event)
  3689	{
  3690	  if (kbd_fetch_ptr == kbd_buffer)
  3691	    kbd_fetch_ptr = kbd_buffer + KBD_BUFFER_SIZE;
  3692	
  3693	  /* Don't let the very last slot in the buffer become full,  */
  3694	  if (kbd_fetch_ptr - 1 != kbd_store_ptr)
  3695	    {
  3696	      --kbd_fetch_ptr;
  3697	      *kbd_fetch_ptr = *event;
  3698	    }
  3699	}

This is problematic because structure copy via assignments may not
preserve the contents of the paddings in general, and they might
contain sensitive information for the other structure, `struct
selection_input_event'.

Actually, I can reproduce the crash with `C-w' on a 64-bit executable
compiled with the following version of llvm-gcc for OS X 10.7:

  i686-apple-darwin11-llvm-gcc-4.2 (GCC) 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)

The disassembly output below shows that 4 bytes from 12-byte offset
are not copied.  These correspond to a part of `dpyinfo' member in
`struct selection_input_event', and it gets corrupted.

_kbd_buffer_unget_event:
00000000000001d0	pushq	%rbp
00000000000001d1	movq	%rsp, %rbp
00000000000001d4	leaq	(%rip), %rax
00000000000001db	movq	(%rip), %rcx
00000000000001e2	cmpq	%rax, %rcx
00000000000001e5	jne	0x1f5
00000000000001e7	leaq	229376(%rip), %rcx
00000000000001ee	movq	%rcx, (%rip)
00000000000001f5	leaq	-56(%rcx), %rax
00000000000001f9	cmpq	(%rip), %rax
0000000000000200	je	0x242
0000000000000202	movq	%rax, (%rip)
0000000000000209	movl	(%rdi), %eax
000000000000020b	movl	%eax, -56(%rcx)
000000000000020e	movl	4(%rdi), %eax
0000000000000211	movl	%eax, -52(%rcx)
0000000000000214	movl	8(%rdi), %eax
0000000000000217	movl	%eax, -48(%rcx)
000000000000021a	movq	16(%rdi), %rax
000000000000021e	movq	%rax, -40(%rcx)
0000000000000222	movq	24(%rdi), %rax
0000000000000226	movq	%rax, -32(%rcx)
000000000000022a	movq	32(%rdi), %rax
000000000000022e	movq	%rax, -24(%rcx)
0000000000000232	movq	40(%rdi), %rax
0000000000000236	movq	%rax, -16(%rcx)
000000000000023a	movq	48(%rdi), %rax
000000000000023e	movq	%rax, -8(%rcx)
0000000000000242	popq	%rbp
0000000000000243	ret
0000000000000244	nopw	(%rax,%rax)
000000000000024a	nopw	(%rax,%rax)

				     YAMAMOTO Mitsuharu
				[email-masked]

In GNU Emacs 25.0.50.1 (x86_64-apple-darwin11.4.2, GTK+ Version 3.16.3)
 of 2015-06-07 on yamamoto-no-MacBook-Air.local
Windowing system distributor `The X.Org Foundation', version 11.0.11006000
Configured using:
 `configure LDFLAGS=-L/opt/local/lib CPPFLAGS=-I/opt/local/include'