[<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