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: <20190307120317.GD32477@hirez.programming.kicks-ass.net>
Date:   Thu, 7 Mar 2019 13:03:17 +0100
From:   Peter Zijlstra <peterz@...radead.org>
To:     torvalds@...ux-foundation.org, tglx@...utronix.de, hpa@...or.com,
        julien.thierry@....com, will.deacon@....com, luto@...capital.net,
        mingo@...nel.org, catalin.marinas@....com, james.morse@....com,
        valentin.schneider@....com, brgerst@...il.com, jpoimboe@...hat.com,
        luto@...nel.org, bp@...en8.de, dvlasenk@...hat.com
Cc:     linux-kernel@...r.kernel.org, dvyukov@...gle.com,
        rostedt@...dmis.org
Subject: Re: [PATCH 00/20] objtool: UACCESS validation v3

On Thu, Mar 07, 2019 at 12:45:11PM +0100, Peter Zijlstra wrote:
> I've only got a few randconfig
> failures left (GCC-8) that I'm not quite understanding.

Take for instance this one (.config attached); it has both
CONFIG_PROFILE_ALL_BRANCHES=y and CONFIG_TRACE_BRANCH_PROFILING=y
and it compiles:

(from kernel/exit.c)

SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
		infop, int, options, struct rusage __user *, ru)
{
	struct rusage r;
	struct waitid_info info = {.status = 0};
	long err = kernel_waitid(which, upid, &info, options, ru ? &r : NULL);
	int signo = 0;

	if (err > 0) {
		signo = SIGCHLD;
		err = 0;
		if (ru && copy_to_user(ru, &r, sizeof(struct rusage)))
			return -EFAULT;
	}
	if (!infop)
		return err;

	if (!user_access_begin(infop, sizeof(*infop)))
		return -EFAULT;

	unsafe_put_user(signo, &infop->si_signo, Efault);
	unsafe_put_user(0, &infop->si_errno, Efault);
	unsafe_put_user(info.cause, &infop->si_code, Efault);
	unsafe_put_user(info.pid, &infop->si_pid, Efault);
	unsafe_put_user(info.uid, &infop->si_uid, Efault);
	unsafe_put_user(info.status, &infop->si_status, Efault);
	user_access_end();
	return err;
Efault:
	user_access_end();
	return -EFAULT;
}

into this atrocious crap (grep -v ffffffffffffe0eb; if you want the src
to go away):

$ objdump -Sdr randconfig-build/kernel/exit.o | awk "/>:\$/ { P=0; } /__do_sys_waitid>:\$/ { P=1; O=strtonum(\"0x\" \$1); } { if (P) { o=strtonum(\"0x\" \$1); printf(\"%04x \", o-O); print \$0; } }"

0000 0000000000001f15 <__do_sys_waitid>:
ffffffffffffe0eb 
ffffffffffffe0eb SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
ffffffffffffe0eb 		infop, int, options, struct rusage __user *, ru)
ffffffffffffe0eb {
0000     1f15:	55                   	push   %rbp
ffffffffffffe0eb 	struct rusage r;
ffffffffffffe0eb 	struct waitid_info info = {.status = 0};
ffffffffffffe0eb 	long err = kernel_waitid(which, upid, &info, options, ru ? &r : NULL);
0001     1f16:	b8 00 00 00 00       	mov    $0x0,%eax
ffffffffffffe0eb {
0006     1f1b:	48 89 e5             	mov    %rsp,%rbp
0009     1f1e:	41 57                	push   %r15
000b     1f20:	41 56                	push   %r14
000d     1f22:	41 55                	push   %r13
000f     1f24:	41 54                	push   %r12
0011     1f26:	4d 89 c4             	mov    %r8,%r12
0014     1f29:	53                   	push   %rbx
0015     1f2a:	48 89 d3             	mov    %rdx,%rbx
0018     1f2d:	48 83 e4 f0          	and    $0xfffffffffffffff0,%rsp
001c     1f31:	48 81 ec a0 00 00 00 	sub    $0xa0,%rsp
ffffffffffffe0eb 	long err = kernel_waitid(which, upid, &info, options, ru ? &r : NULL);
0023     1f38:	4d 85 e4             	test   %r12,%r12
0026     1f3b:	4c 8d 44 24 10       	lea    0x10(%rsp),%r8
002b     1f40:	48 89 e2             	mov    %rsp,%rdx
ffffffffffffe0eb 	struct waitid_info info = {.status = 0};
002e     1f43:	48 c7 04 24 00 00 00 	movq   $0x0,(%rsp)
0035     1f4a:	00 
0036     1f4b:	48 c7 44 24 08 00 00 	movq   $0x0,0x8(%rsp)
003d     1f52:	00 00 
ffffffffffffe0eb 	long err = kernel_waitid(which, upid, &info, options, ru ? &r : NULL);
003f     1f54:	4c 0f 44 c0          	cmove  %rax,%r8
0043     1f58:	e8 9c fe ff ff       	callq  1df9 <kernel_waitid>
ffffffffffffe0eb 	int signo = 0;
ffffffffffffe0eb 
ffffffffffffe0eb 	if (err > 0) {
0048     1f5d:	48 85 c0             	test   %rax,%rax
ffffffffffffe0eb 	long err = kernel_waitid(which, upid, &info, options, ru ? &r : NULL);
004b     1f60:	49 89 c7             	mov    %rax,%r15
ffffffffffffe0eb 	if (err > 0) {
004e     1f63:	0f 9f c0             	setg   %al
0051     1f66:	0f b6 c0             	movzbl %al,%eax
0054     1f69:	48 83 c0 02          	add    $0x2,%rax
0058     1f6d:	48 ff 04 c5 00 00 00 	incq   0x0(,%rax,8)
005f     1f74:	00 
005c 			1f71: R_X86_64_32S	_ftrace_branch+0x1c0
0060     1f75:	4d 85 ff             	test   %r15,%r15
0063     1f78:	7e 7b                	jle    1ff5 <__do_sys_waitid+0xe0>
ffffffffffffe0eb 		signo = SIGCHLD;
ffffffffffffe0f9 		err = 0;
ffffffffffffe0eb 		if (ru && copy_to_user(ru, &r, sizeof(struct rusage)))
0065     1f7a:	31 d2                	xor    %edx,%edx
0067     1f7c:	4d 85 e4             	test   %r12,%r12
006a     1f7f:	74 53                	je     1fd4 <__do_sys_waitid+0xbf>
ffffffffffffe0eb 
ffffffffffffe0eb static __always_inline bool
ffffffffffffe0f7 check_copy_size(const void *addr, size_t bytes, bool is_source)
ffffffffffffe0eb {
ffffffffffffe0eb 	int sz = __compiletime_object_size(addr);
ffffffffffffe0eb 	if (unlikely(sz >= 0 && sz < bytes)) {
006c     1f81:	31 f6                	xor    %esi,%esi
006e     1f83:	b9 01 00 00 00       	mov    $0x1,%ecx
0073     1f88:	48 c7 c7 00 00 00 00 	mov    $0x0,%rdi
0076 			1f8b: R_X86_64_32S	_ftrace_annotated_branch+0xcc0
007a     1f8f:	e8 00 00 00 00       	callq  1f94 <__do_sys_waitid+0x7f>
007b 			1f90: R_X86_64_PLT32	ftrace_likely_update-0x4
ffffffffffffe0eb }
ffffffffffffe0eb 
ffffffffffffe0eb static __always_inline unsigned long __must_check
ffffffffffffe0f7 copy_to_user(void __user *to, const void *from, unsigned long n)
ffffffffffffe0eb {
ffffffffffffe0eb 	if (likely(check_copy_size(from, n, true)))
007f     1f94:	31 c9                	xor    %ecx,%ecx
0081     1f96:	ba 01 00 00 00       	mov    $0x1,%edx
0086     1f9b:	be 01 00 00 00       	mov    $0x1,%esi
008b     1fa0:	48 c7 c7 00 00 00 00 	mov    $0x0,%rdi
008e 			1fa3: R_X86_64_32S	_ftrace_annotated_branch+0xae0
0092     1fa7:	48 ff 05 00 00 00 00 	incq   0x0(%rip)        # 1fae <__do_sys_waitid+0x99>
0095 			1faa: R_X86_64_PC32	_ftrace_branch+0x1fcc
0099     1fae:	e8 00 00 00 00       	callq  1fb3 <__do_sys_waitid+0x9e>
009a 			1faf: R_X86_64_PLT32	ftrace_likely_update-0x4
ffffffffffffe0eb 		n = _copy_to_user(to, from, n);
009e     1fb3:	ba 90 00 00 00       	mov    $0x90,%edx
00a3     1fb8:	4c 89 e7             	mov    %r12,%rdi
ffffffffffffe0eb 	if (likely(check_copy_size(from, n, true)))
00a6     1fbb:	48 ff 05 00 00 00 00 	incq   0x0(%rip)        # 1fc2 <__do_sys_waitid+0xad>
00a9 			1fbe: R_X86_64_PC32	_ftrace_branch+0x1d7c
ffffffffffffe0eb 		n = _copy_to_user(to, from, n);
00ad     1fc2:	48 8d 74 24 10       	lea    0x10(%rsp),%rsi
00b2     1fc7:	e8 00 00 00 00       	callq  1fcc <__do_sys_waitid+0xb7>
00b3 			1fc8: R_X86_64_PLT32	_copy_to_user-0x4
00b7     1fcc:	31 d2                	xor    %edx,%edx
00b9     1fce:	48 85 c0             	test   %rax,%rax
00bc     1fd1:	0f 95 c2             	setne  %dl
00bf     1fd4:	48 63 c2             	movslq %edx,%rax
ffffffffffffe0eb 		signo = SIGCHLD;
00c2     1fd7:	41 be 11 00 00 00    	mov    $0x11,%r14d
ffffffffffffe0f9 		err = 0;
00c8     1fdd:	45 31 ff             	xor    %r15d,%r15d
ffffffffffffe0eb 		if (ru && copy_to_user(ru, &r, sizeof(struct rusage)))
00cb     1fe0:	48 83 c0 02          	add    $0x2,%rax
00cf     1fe4:	48 ff 04 c5 00 00 00 	incq   0x0(,%rax,8)
00d6     1feb:	00 
00d3 			1fe8: R_X86_64_32S	_ftrace_branch+0x198
00d7     1fec:	85 d2                	test   %edx,%edx
00d9     1fee:	74 08                	je     1ff8 <__do_sys_waitid+0xe3>
00db     1ff0:	e9 33 01 00 00       	jmpq   2128 <__do_sys_waitid+0x213>
ffffffffffffe0eb 	int signo = 0;
00e0     1ff5:	45 31 f6             	xor    %r14d,%r14d
ffffffffffffe0eb 			return -EFAULT;
ffffffffffffe0eb 	}
ffffffffffffe0eb 	if (!infop)
00e3     1ff8:	31 c0                	xor    %eax,%eax
00e5     1ffa:	48 85 db             	test   %rbx,%rbx
00e8     1ffd:	0f 94 c0             	sete   %al
00eb     2000:	48 83 c0 02          	add    $0x2,%rax
00ef     2004:	48 ff 04 c5 00 00 00 	incq   0x0(,%rax,8)
00f6     200b:	00 
00f3 			2008: R_X86_64_32S	_ftrace_branch+0x170
00f7     200c:	48 85 db             	test   %rbx,%rbx
00fa     200f:	0f 84 1a 01 00 00    	je     212f <__do_sys_waitid+0x21a>
ffffffffffffe0eb 	return raw_cpu_read_4(__preempt_count) & ~PREEMPT_NEED_RESCHED;
0100     2015:	65 44 8b 25 00 00 00 	mov    %gs:0x0(%rip),%r12d        # 201d <__do_sys_waitid+0x108>
0107     201c:	00 
0104 			2019: R_X86_64_PC32	__preempt_count-0x4
ffffffffffffe0eb  * checking before using them, but you have to surround them with the
ffffffffffffe0eb  * user_access_begin/end() pair.
ffffffffffffe0eb  */
ffffffffffffe0eb static __must_check __always_inline bool user_access_begin(const void __user *ptr, size_t len)
ffffffffffffe0eb {
ffffffffffffe0eb 	if (unlikely(!access_ok(ptr,len)))
0108     201d:	45 31 ed             	xor    %r13d,%r13d
010b     2020:	41 81 e4 00 01 1f 00 	and    $0x1f0100,%r12d
0112     2027:	48 c7 c7 00 00 00 00 	mov    $0x0,%rdi
0115 			202a: R_X86_64_32S	_ftrace_annotated_branch+0xb70
0119     202e:	41 0f 95 c5          	setne  %r13b
011d     2032:	31 c9                	xor    %ecx,%ecx
011f     2034:	31 d2                	xor    %edx,%edx
0121     2036:	44 89 ee             	mov    %r13d,%esi
0124     2039:	e8 00 00 00 00       	callq  203e <__do_sys_waitid+0x129>
0125 			203a: R_X86_64_PLT32	ftrace_likely_update-0x4
0129     203e:	49 63 c5             	movslq %r13d,%rax
012c     2041:	48 83 c0 02          	add    $0x2,%rax
0130     2045:	48 ff 04 c5 00 00 00 	incq   0x0(,%rax,8)
0137     204c:	00 
0134 			2049: R_X86_64_32S	_ftrace_branch+0x1d90
0138     204d:	45 85 e4             	test   %r12d,%r12d
013b     2050:	74 02                	je     2054 <__do_sys_waitid+0x13f>
013d     2052:	0f 0b                	ud2    
013f     2054:	31 c9                	xor    %ecx,%ecx
0141     2056:	31 d2                	xor    %edx,%edx
0143     2058:	44 89 ee             	mov    %r13d,%esi
0146     205b:	48 c7 c7 00 00 00 00 	mov    $0x0,%rdi
0149 			205e: R_X86_64_32S	_ftrace_annotated_branch+0xb40
014d     2062:	e8 00 00 00 00       	callq  2067 <__do_sys_waitid+0x152>
014e 			2063: R_X86_64_PLT32	ftrace_likely_update-0x4
ffffffffffffe0eb 		return unlikely(addr > limit - size);
0152     2067:	45 31 e4             	xor    %r12d,%r12d
0155     206a:	48 c7 c7 00 00 00 00 	mov    $0x0,%rdi
0158 			206d: R_X86_64_32S	_ftrace_annotated_branch+0xbd0
015c     2071:	65 48 8b 04 25 00 00 	mov    %gs:0x0,%rax
0163     2078:	00 00 
0161 			2076: R_X86_64_32S	current_task
0165     207a:	4c 8b a8 d8 1d 00 00 	mov    0x1dd8(%rax),%r13
016c     2081:	49 83 c5 80          	add    $0xffffffffffffff80,%r13
0170     2085:	4c 39 eb             	cmp    %r13,%rbx
0173     2088:	41 0f 97 c4          	seta   %r12b
0177     208c:	31 c9                	xor    %ecx,%ecx
0179     208e:	31 d2                	xor    %edx,%edx
017b     2090:	44 89 e6             	mov    %r12d,%esi
017e     2093:	e8 00 00 00 00       	callq  2098 <__do_sys_waitid+0x183>
017f 			2094: R_X86_64_PLT32	ftrace_likely_update-0x4
ffffffffffffe0eb 	if (unlikely(!access_ok(ptr,len)))
0183     2098:	31 f6                	xor    %esi,%esi
0185     209a:	4c 39 eb             	cmp    %r13,%rbx
0188     209d:	ba 01 00 00 00       	mov    $0x1,%edx
018d     20a2:	40 0f 96 c6          	setbe  %sil
0191     20a6:	48 c7 c7 00 00 00 00 	mov    $0x0,%rdi
0194 			20a9: R_X86_64_32S	_ftrace_annotated_branch+0xb10
0198     20ad:	31 c9                	xor    %ecx,%ecx
019a     20af:	e8 00 00 00 00       	callq  20b4 <__do_sys_waitid+0x19f>
019b 			20b0: R_X86_64_PLT32	ftrace_likely_update-0x4
019f     20b4:	44 89 e6             	mov    %r12d,%esi
01a2     20b7:	31 c9                	xor    %ecx,%ecx
01a4     20b9:	31 d2                	xor    %edx,%edx
01a6     20bb:	48 c7 c7 00 00 00 00 	mov    $0x0,%rdi
01a9 			20be: R_X86_64_32S	_ftrace_annotated_branch+0xba0
01ad     20c2:	49 83 c4 02          	add    $0x2,%r12
01b1     20c6:	e8 00 00 00 00       	callq  20cb <__do_sys_waitid+0x1b6>
01b2 			20c7: R_X86_64_PLT32	ftrace_likely_update-0x4
01b6     20cb:	4a ff 04 e5 00 00 00 	incq   0x0(,%r12,8)
01bd     20d2:	00 
01ba 			20cf: R_X86_64_32S	_ftrace_branch+0x1db8
ffffffffffffe0eb 		return 0;
01be     20d3:	31 c0                	xor    %eax,%eax
ffffffffffffe0eb 	if (unlikely(!access_ok(ptr,len)))
01c0     20d5:	4c 39 eb             	cmp    %r13,%rbx
01c3     20d8:	77 08                	ja     20e2 <__do_sys_waitid+0x1cd>
ffffffffffffe0eb 	__uaccess_begin_nospec();
01c5     20da:	90                   	nop
01c6     20db:	90                   	nop
01c7     20dc:	90                   	nop
ffffffffffffe0eb }
ffffffffffffe0eb 
ffffffffffffe0eb static __always_inline void stac(void)
ffffffffffffe0eb {
ffffffffffffe0eb 	/* Note: a barrier is implicit in alternative() */
ffffffffffffe0f5 	alternative("", __stringify(__ASM_STAC), X86_FEATURE_SMAP);
01c8     20dd:	90                   	nop
01c9     20de:	90                   	nop
01ca     20df:	90                   	nop
ffffffffffffe0eb 	return 1;
01cb     20e0:	b0 01                	mov    $0x1,%al
ffffffffffffe0eb 		return err;
ffffffffffffe0eb 
ffffffffffffe0eb 	if (!user_access_begin(infop, sizeof(*infop)))
01cd     20e2:	83 f0 01             	xor    $0x1,%eax
01d0     20e5:	48 89 c2             	mov    %rax,%rdx
01d3     20e8:	83 e2 01             	and    $0x1,%edx
01d6     20eb:	48 83 c2 02          	add    $0x2,%rdx
01da     20ef:	48 ff 04 d5 00 00 00 	incq   0x0(,%rdx,8)
01e1     20f6:	00 
01de 			20f3: R_X86_64_32S	_ftrace_branch+0x148
01e2     20f7:	84 c0                	test   %al,%al
01e4     20f9:	75 2d                	jne    2128 <__do_sys_waitid+0x213>
ffffffffffffe0eb 		return -EFAULT;
ffffffffffffe0eb 
ffffffffffffe0eb 	unsafe_put_user(signo, &infop->si_signo, Efault);
01e6     20fb:	44 89 33             	mov    %r14d,(%rbx)
ffffffffffffe0eb 	unsafe_put_user(0, &infop->si_errno, Efault);
01e9     20fe:	c7 43 04 00 00 00 00 	movl   $0x0,0x4(%rbx)
ffffffffffffe0eb 	unsafe_put_user(info.cause, &infop->si_code, Efault);
01f0     2105:	8b 44 24 0c          	mov    0xc(%rsp),%eax
01f4     2109:	89 43 08             	mov    %eax,0x8(%rbx)
ffffffffffffe0eb 	unsafe_put_user(info.pid, &infop->si_pid, Efault);
01f7     210c:	8b 04 24             	mov    (%rsp),%eax
01fa     210f:	89 43 10             	mov    %eax,0x10(%rbx)
ffffffffffffe0eb 	unsafe_put_user(info.uid, &infop->si_uid, Efault);
01fd     2112:	8b 44 24 04          	mov    0x4(%rsp),%eax
0201     2116:	89 43 14             	mov    %eax,0x14(%rbx)
ffffffffffffe0eb 	unsafe_put_user(info.status, &infop->si_status, Efault);
0204     2119:	8b 44 24 08          	mov    0x8(%rsp),%eax
0208     211d:	89 43 18             	mov    %eax,0x18(%rbx)
ffffffffffffe0eb 	user_access_end();
020b     2120:	90                   	nop
020c     2121:	90                   	nop
020d     2122:	90                   	nop
ffffffffffffe0eb 	return err;
020e     2123:	eb 0a                	jmp    212f <__do_sys_waitid+0x21a>
ffffffffffffefe5 Efault:
ffffffffffffe0eb 	user_access_end();
0210     2125:	90                   	nop
0211     2126:	90                   	nop
0212     2127:	90                   	nop
ffffffffffffe0eb 	return -EFAULT;
0213     2128:	49 c7 c7 f2 ff ff ff 	mov    $0xfffffffffffffff2,%r15
ffffffffffffe0eb }
021a     212f:	48 8d 65 d8          	lea    -0x28(%rbp),%rsp
021e     2133:	4c 89 f8             	mov    %r15,%rax
0221     2136:	5b                   	pop    %rbx
0222     2137:	41 5c                	pop    %r12
0224     2139:	41 5d                	pop    %r13
0226     213b:	41 5e                	pop    %r14
0228     213d:	41 5f                	pop    %r15
022a     213f:	5d                   	pop    %rbp
022b     2140:	c3                   	retq   
ffffffffffffe0eb 

And then complains about:

$ tools/objtool/objtool check --no-fp --uaccess --backtrace randconfig-build/kernel/exit.o
randconfig-build/kernel/exit.o: warning: objtool: .altinstr_replacement+0xc: redundant UACCESS disable
randconfig-build/kernel/exit.o: warning: objtool:   __do_sys_waitid()+0x210: (alt)
randconfig-build/kernel/exit.o: warning: objtool:   __do_sys_waitid()+0x1e6: (alt)
randconfig-build/kernel/exit.o: warning: objtool:   __do_sys_waitid()+0x1c3: (branch)
randconfig-build/kernel/exit.o: warning: objtool:   __do_sys_waitid()+0x13b: (branch)
randconfig-build/kernel/exit.o: warning: objtool:   __do_sys_waitid()+0x63: (branch)
randconfig-build/kernel/exit.o: warning: objtool:   __do_sys_waitid()+0x0: <=== (func)

Which, afaict is correct given the asm, but is absolute nonsense given
the original C. If you follow that code path, it appears to do the
memops without STAC, and then complains it does CLAC. Which is of course
complete crap.

Maybe I've been staring at this too long and am (again) missing the
obvious :/

View attachment "randconfig-fail" of type "text/plain" (92010 bytes)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ