Join GitHub today
GitHub is home to over 36 million developers working together to host and review code, manage projects, and build software together.
Sign up__builtin_constant_p() does not work in deep inline functions #7
Comments
This comment has been minimized.
This comment has been minimized.
gburgessiv
commented
Mar 29, 2018
|
Is needing I ask because, while it's pretty terrible, you can make this work on a case-by-case basis with some clang-specific code:
...I'd like to note, however, that this is forcing the decision of "should I call |
This comment has been minimized.
This comment has been minimized.
|
I'm not sure how widely this assumption is used, but it's fairly central to a number of optimizations in usercopy code (not just the security hardening pieces)... |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
nickdesaulniers
added
[BUG] llvm
[PATCH] Exists
labels
Apr 12, 2018
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
@jyknight is there anything we need to communicate to or patch in the upstream kernel? |
dileks
referenced this issue
Jul 30, 2018
Open
clang validates extended assembly constraints even when -fno-integrated-as is set #3
This comment has been minimized.
This comment has been minimized.
dileks
commented
Jul 31, 2018
|
CONFIG_HARDENED_USERCOPY=n is a workaround to have a bootable Linux v4.18-rc7 here on Debian/testing AMD64. |
This comment has been minimized.
This comment has been minimized.
|
Here's another recent case, which miscompiles (for arm64) due to inline vs __builtin_constant_p(): net/core/filter.c:7292: undefined reference to `__compiletime_assert_7292' net/core/filter.c:7292: include/net/sock.h: include/linux/bitops.h: include/asm-generic/bitops/const_hweight.h: "w" passed into hweight_long() loses its __builtin_constant-ness, and the BUILD_BUG_ON starts always evaluating with a full function call instead of as a constant expression. |
This comment has been minimized.
This comment has been minimized.
|
workaround:
|
This comment has been minimized.
This comment has been minimized.
|
FWIW, the suggested Clang patch does not actually solve this issue for me. :( |
nathanchance
referenced this issue
Aug 23, 2018
Closed
failing BUILD_BUG_ON in sk_reuseport_convert_ctx_access #28
This comment has been minimized.
This comment has been minimized.
dileks
commented
Aug 27, 2018
•
|
@kees Your workaround helped me to fix this in Linux v4.19-rc1...
|
This comment has been minimized.
This comment has been minimized.
Does marking Edit: update: looks like no... |
This comment has been minimized.
This comment has been minimized.
|
It seems that even in very basic cases of one level function call, clang and gcc disagree on |
This comment has been minimized.
This comment has been minimized.
dileks
commented
Aug 29, 2018
|
The workaround of Kees is no more needed with the patch "bpf: fix build error with clang" pending in bpf Git. |
This comment has been minimized.
This comment has been minimized.
gwelymernans
commented
Aug 31, 2018
|
Attaching two patch files if anyone would like to tests them out. (The llvm patch is from https://reviews.llvm.org/D4276) |
This comment has been minimized.
This comment has been minimized.
|
These patches appear to solve at least the net/core/filter.c case! I'll need to double-check the runtime effects with HARDENED_USERCOPY on tuesday. (Note that I used my own forward-port of the LLVM patch based on D4276 -- I haven't compared that to the bcp-llvm.patch.txt above.) |
This comment has been minimized.
This comment has been minimized.
dileks
commented
Sep 3, 2018
|
@gwelymernans Your patches are against LLVM/Clang SVN revision 341155. Can you provide them against release_70 Git branch? So, I would like to test the case CONFIG_HARDENED_USERCOPY=y. |
This comment has been minimized.
This comment has been minimized.
|
New warning, which appears to be doing the wrong thing with "const u32 *", thinking it's a compile-time constant, when it's not:
|
This comment has been minimized.
This comment has been minimized.
dileks
commented
Sep 3, 2018
•
|
0001-Backport-bcp-llvm.patch-to-release_70-Git-branch.patch.txt I tried to backport the patches myself and have 8 failures when running
|
This comment has been minimized.
This comment has been minimized.
gwelymernans
commented
Sep 4, 2018
|
@dileks The patches are more on the hack side of things. Do any of the failures look like semantic issues? or are they just that the tests expect different output? |
This comment has been minimized.
This comment has been minimized.
dileks
commented
Sep 6, 2018
|
@gwelymernans You had a chance to look into my backported patches? Can you verify they are done correctly? Thanks. |
This comment has been minimized.
This comment has been minimized.
gwelymernans
commented
Sep 7, 2018
|
@dileks They look fine to me (at least they look similar to what I did). I'm not surprised that there are failures in the tests. (They were written with the original assumption in mind.) I also may have missed something important when I was hacking the front-end patch together. (I'm not as familiar with the front-end code as the middle and back end code.) |
nickdesaulniers
pushed a commit
that referenced
this issue
Sep 11, 2018
This comment has been minimized.
This comment has been minimized.
|
I found this, too: https://reviews.llvm.org/D35190 I wonder if we need this as part this work? |
This comment has been minimized.
This comment has been minimized.
gwelymernans
commented
Sep 12, 2018
|
@kees Could you add the |
This comment has been minimized.
This comment has been minimized.
gburgessiv
commented
Sep 12, 2018
Probably not. That patch is more for "when we're evaluating a From clang's perspective, if |
nathanchance
pushed a commit
that referenced
this issue
Dec 9, 2018
This comment has been minimized.
This comment has been minimized.
dileks
commented
Dec 19, 2018
•
|
@kees Your testcase requires CONFIG_LKDTM set. I had success with CONFIG_LKDTM=m and clang version 8.0.0-svn349540-1 |
nathanchance
pushed a commit
that referenced
this issue
Dec 20, 2018
nathanchance
pushed a commit
that referenced
this issue
Dec 21, 2018
nathanchance
pushed a commit
that referenced
this issue
Jan 21, 2019
nathanchance
pushed a commit
that referenced
this issue
Jan 21, 2019
This comment has been minimized.
This comment has been minimized.
|
reviewing old content for our talk this weekend at FOSDEM, looks like @behanw knew of this back in '13! See slide 27: https://events.static.linuxfound.org/images/stories/slides/abs2013_webster.pdf Edit: Ha! and extern inline! |
This comment has been minimized.
This comment has been minimized.
dileks
commented
Feb 1, 2019
•
|
It's a pity I am only on Saturday at FOSDEM and can not visit your talk "Compiling the Linux kernel with LLVM tools" :-(. |
kees commentedMar 27, 2018
•
edited
The hardened usercopy whitelisting (CONFIG_HARDENED_USERCOPY=y) depends on constant-sized arguments to copy_to_user()/copy_from_user() to be implicitly whitelisted. Without this, there is both a performance hit (for doing dynamic checking when none is needed) and failures (when an implicit whitelist is used with static sizes). For example, on x86, this happens under clang-5.0 but not gcc:
[ 1.628046] ------------[ cut here ]------------
[ 1.628524] Bad or missing usercopy whitelist? Kernel memory exposure attempt detected from SLUB object 'task_struct' (offset 1728, size 8)!
[ 1.629772] WARNING: CPU: 3 PID: 1208 at mm/usercopy.c:81 usercopy_warn+0x96/0xa0
[ 1.630514] Modules linked in:
[ 1.630519] CPU: 3 PID: 1208 Comm: sh Not tainted 4.16.0-rc5+ #64
[ 1.630520] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-1.8.2-1ubuntu1 04/01/2014
[ 1.630522] RIP: 0010:usercopy_warn+0x96/0xa0
[ 1.630523] RSP: 0018:ffff9c1781a73ce8 EFLAGS: 00010286
[ 1.630526] RAX: 947d865a0fb2e100 RBX: ffffffff96310daf RCX: ffffffff9665cdd0
[ 1.630527] RDX: ffffffff94edcfb7 RSI: ffffffff9665cd78 RDI: ffffffff94edcff8
[ 1.630528] RBP: ffff9c1781a73cf0 R08: 0000000000000000 R09: 0000000000000000
[ 1.630529] R10: 0000000000000002 R11: 0000000000000000 R12: ffff966a6bf6b3c8
[ 1.630530] R13: 0000000000000000 R14: 0000000000000008 R15: 0000000000000001
[ 1.630532] FS: 00007fc896687700(0000) GS:ffff966a7fd80000(0000) knlGS:0000000000000000
[ 1.630533] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 1.630534] CR2: 00007ffc730a5d1c CR3: 000000042a81c001 CR4: 00000000001606e0
[ 1.630537] Call Trace:
[ 1.630541] __check_object_size+0xc3/0x1c0
[ 1.646723] do_signal+0x48e/0x5f0
[ 1.647127] prepare_exit_to_usermode+0xeb/0x170
[ 1.647742] syscall_return_slowpath+0x5e/0x2b0
[ 1.648240] ? syscall_trace_enter+0x15d/0x350
[ 1.648730] entry_SYSCALL_64_after_hwframe+0x42/0xb7
[ 1.649305] RIP: 0033:0x7fc89618012a
[ 1.649694] RSP: 002b:00007ffe56f8ec58 EFLAGS: 00000246 ORIG_RAX: 000000000000003d
[ 1.650522] RAX: 00000000000004bf RBX: 0000000000000001 RCX: 00007fc89618012a
[ 1.651294] RDX: 0000000000000000 RSI: 00007ffe56f8ec7c RDI: 00000000ffffffff
[ 1.652067] RBP: 0000563ebd2f63e0 R08: 0000000000000000 R09: 00007fc896687700
[ 1.652827] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
[ 1.653586] R13: 00007ffe56f8ec7c R14: 00007ffe56f90fb3 R15: 0000000000000000
[ 1.654361] Code: 96 4c 0f 44 c0 4c 0f 44 c8 48 c7 c3 af 0d 31 96 48 0f 44 d8 48 c7 c7 31 0d 31 96 31 c0 41 52 41 53 53 e8 4e 2b e5 ff 48 83 c4 18 <0f> 0b 5b 5d c3 0f 1f 44 00 00 0f 1f 44 00 00 55 48 89 e5 53 4d
[ 1.656441] ---[ end trace aa26781ca73156e1 ]---
This is from arch/x86/kernel/signal.c do_signal+0x48e/0x5f0:
copy_user_generic at arch/x86/include/asm/uaccess_64.h:37
(inlined by) raw_copy_to_user at arch/x86/include/asm/uaccess_64.h:112
(inlined by) __copy_to_user at include/linux/uaccess.h:105
(inlined by) __setup_rt_frame at arch/x86/kernel/signal.c:493
(inlined by) setup_rt_frame at arch/x86/kernel/signal.c:699
(inlined by) handle_signal at arch/x86/kernel/signal.c:743
(inlined by) do_signal at arch/x86/kernel/signal.c:811
specifically __setup_rt_frame():
Last argument is sizeof(*set), which should be true for __builtin_constant_p() in __copy_to_user():
check_object_size()'s n is __copy_to_user()'s n is __setup_rt_frame()'s sizeof(*set).