aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2016-05-05 02:35:00 -0400
committerIngo Molnar <mingo@kernel.org>2016-05-05 02:35:00 -0400
commit1fb48f8e54e5ed4d3d8599ba7e83f1f60530c81c (patch)
tree6b8c1ccdd461e211f72c674d183f5129f5fe4a5b /tools
parent778843f934e362ed4ed734520f60a44a78a074b4 (diff)
parent04974df8049fc4240d22759a91e035082ccd18b4 (diff)
Merge tag 'v4.6-rc6' into x86/asm, to refresh the tree
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/objtool/Documentation/stack-validation.txt38
-rw-r--r--tools/objtool/builtin-check.c97
-rw-r--r--tools/perf/util/intel-pt.c2
-rw-r--r--tools/testing/selftests/net/.gitignore1
-rw-r--r--tools/testing/selftests/net/Makefile2
-rw-r--r--tools/testing/selftests/net/reuseport_dualstack.c208
6 files changed, 312 insertions, 36 deletions
diff --git a/tools/objtool/Documentation/stack-validation.txt b/tools/objtool/Documentation/stack-validation.txt
index 5a95896105bc..55a60d331f47 100644
--- a/tools/objtool/Documentation/stack-validation.txt
+++ b/tools/objtool/Documentation/stack-validation.txt
@@ -299,18 +299,38 @@ they mean, and suggestions for how to fix them.
299Errors in .c files 299Errors in .c files
300------------------ 300------------------
301 301
302If you're getting an objtool error in a compiled .c file, chances are 3021. c_file.o: warning: objtool: funcA() falls through to next function funcB()
303the file uses an asm() statement which has a "call" instruction. An
304asm() statement with a call instruction must declare the use of the
305stack pointer in its output operand. For example, on x86_64:
306 303
307 register void *__sp asm("rsp"); 304 This means that funcA() doesn't end with a return instruction or an
308 asm volatile("call func" : "+r" (__sp)); 305 unconditional jump, and that objtool has determined that the function
306 can fall through into the next function. There could be different
307 reasons for this:
309 308
310Otherwise the stack frame may not get created before the call. 309 1) funcA()'s last instruction is a call to a "noreturn" function like
310 panic(). In this case the noreturn function needs to be added to
311 objtool's hard-coded global_noreturns array. Feel free to bug the
312 objtool maintainer, or you can submit a patch.
311 313
312Another possible cause for errors in C code is if the Makefile removes 314 2) funcA() uses the unreachable() annotation in a section of code
313-fno-omit-frame-pointer or adds -fomit-frame-pointer to the gcc options. 315 that is actually reachable.
316
317 3) If funcA() calls an inline function, the object code for funcA()
318 might be corrupt due to a gcc bug. For more details, see:
319 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70646
320
3212. If you're getting any other objtool error in a compiled .c file, it
322 may be because the file uses an asm() statement which has a "call"
323 instruction. An asm() statement with a call instruction must declare
324 the use of the stack pointer in its output operand. For example, on
325 x86_64:
326
327 register void *__sp asm("rsp");
328 asm volatile("call func" : "+r" (__sp));
329
330 Otherwise the stack frame may not get created before the call.
331
3323. Another possible cause for errors in C code is if the Makefile removes
333 -fno-omit-frame-pointer or adds -fomit-frame-pointer to the gcc options.
314 334
315Also see the above section for .S file errors for more information what 335Also see the above section for .S file errors for more information what
316the individual error messages mean. 336the individual error messages mean.
diff --git a/tools/objtool/builtin-check.c b/tools/objtool/builtin-check.c
index 7515cb2e879a..e8a1e69eb92c 100644
--- a/tools/objtool/builtin-check.c
+++ b/tools/objtool/builtin-check.c
@@ -54,6 +54,7 @@ struct instruction {
54 struct symbol *call_dest; 54 struct symbol *call_dest;
55 struct instruction *jump_dest; 55 struct instruction *jump_dest;
56 struct list_head alts; 56 struct list_head alts;
57 struct symbol *func;
57}; 58};
58 59
59struct alternative { 60struct alternative {
@@ -66,6 +67,7 @@ struct objtool_file {
66 struct list_head insn_list; 67 struct list_head insn_list;
67 DECLARE_HASHTABLE(insn_hash, 16); 68 DECLARE_HASHTABLE(insn_hash, 16);
68 struct section *rodata, *whitelist; 69 struct section *rodata, *whitelist;
70 bool ignore_unreachables, c_file;
69}; 71};
70 72
71const char *objname; 73const char *objname;
@@ -228,7 +230,7 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func,
228 } 230 }
229 } 231 }
230 232
231 if (insn->type == INSN_JUMP_DYNAMIC) 233 if (insn->type == INSN_JUMP_DYNAMIC && list_empty(&insn->alts))
232 /* sibling call */ 234 /* sibling call */
233 return 0; 235 return 0;
234 } 236 }
@@ -248,6 +250,7 @@ static int dead_end_function(struct objtool_file *file, struct symbol *func)
248static int decode_instructions(struct objtool_file *file) 250static int decode_instructions(struct objtool_file *file)
249{ 251{
250 struct section *sec; 252 struct section *sec;
253 struct symbol *func;
251 unsigned long offset; 254 unsigned long offset;
252 struct instruction *insn; 255 struct instruction *insn;
253 int ret; 256 int ret;
@@ -281,6 +284,21 @@ static int decode_instructions(struct objtool_file *file)
281 hash_add(file->insn_hash, &insn->hash, insn->offset); 284 hash_add(file->insn_hash, &insn->hash, insn->offset);
282 list_add_tail(&insn->list, &file->insn_list); 285 list_add_tail(&insn->list, &file->insn_list);
283 } 286 }
287
288 list_for_each_entry(func, &sec->symbol_list, list) {
289 if (func->type != STT_FUNC)
290 continue;
291
292 if (!find_insn(file, sec, func->offset)) {
293 WARN("%s(): can't find starting instruction",
294 func->name);
295 return -1;
296 }
297
298 func_for_each_insn(file, func, insn)
299 if (!insn->func)
300 insn->func = func;
301 }
284 } 302 }
285 303
286 return 0; 304 return 0;
@@ -664,13 +682,40 @@ static int add_func_switch_tables(struct objtool_file *file,
664 text_rela->addend); 682 text_rela->addend);
665 683
666 /* 684 /*
667 * TODO: Document where this is needed, or get rid of it.
668 *
669 * rare case: jmpq *[addr](%rip) 685 * rare case: jmpq *[addr](%rip)
686 *
687 * This check is for a rare gcc quirk, currently only seen in
688 * three driver functions in the kernel, only with certain
689 * obscure non-distro configs.
690 *
691 * As part of an optimization, gcc makes a copy of an existing
692 * switch jump table, modifies it, and then hard-codes the jump
693 * (albeit with an indirect jump) to use a single entry in the
694 * table. The rest of the jump table and some of its jump
695 * targets remain as dead code.
696 *
697 * In such a case we can just crudely ignore all unreachable
698 * instruction warnings for the entire object file. Ideally we
699 * would just ignore them for the function, but that would
700 * require redesigning the code quite a bit. And honestly
701 * that's just not worth doing: unreachable instruction
702 * warnings are of questionable value anyway, and this is such
703 * a rare issue.
704 *
705 * kbuild reports:
706 * - https://lkml.kernel.org/r/201603231906.LWcVUpxm%25fengguang.wu@intel.com
707 * - https://lkml.kernel.org/r/201603271114.K9i45biy%25fengguang.wu@intel.com
708 * - https://lkml.kernel.org/r/201603291058.zuJ6ben1%25fengguang.wu@intel.com
709 *
710 * gcc bug:
711 * - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70604
670 */ 712 */
671 if (!rodata_rela) 713 if (!rodata_rela) {
672 rodata_rela = find_rela_by_dest(file->rodata, 714 rodata_rela = find_rela_by_dest(file->rodata,
673 text_rela->addend + 4); 715 text_rela->addend + 4);
716 if (rodata_rela)
717 file->ignore_unreachables = true;
718 }
674 719
675 if (!rodata_rela) 720 if (!rodata_rela)
676 continue; 721 continue;
@@ -732,9 +777,6 @@ static int decode_sections(struct objtool_file *file)
732{ 777{
733 int ret; 778 int ret;
734 779
735 file->whitelist = find_section_by_name(file->elf, "__func_stack_frame_non_standard");
736 file->rodata = find_section_by_name(file->elf, ".rodata");
737
738 ret = decode_instructions(file); 780 ret = decode_instructions(file);
739 if (ret) 781 if (ret)
740 return ret; 782 return ret;
@@ -799,6 +841,7 @@ static int validate_branch(struct objtool_file *file,
799 struct alternative *alt; 841 struct alternative *alt;
800 struct instruction *insn; 842 struct instruction *insn;
801 struct section *sec; 843 struct section *sec;
844 struct symbol *func = NULL;
802 unsigned char state; 845 unsigned char state;
803 int ret; 846 int ret;
804 847
@@ -813,6 +856,16 @@ static int validate_branch(struct objtool_file *file,
813 } 856 }
814 857
815 while (1) { 858 while (1) {
859 if (file->c_file && insn->func) {
860 if (func && func != insn->func) {
861 WARN("%s() falls through to next function %s()",
862 func->name, insn->func->name);
863 return 1;
864 }
865
866 func = insn->func;
867 }
868
816 if (insn->visited) { 869 if (insn->visited) {
817 if (frame_state(insn->state) != frame_state(state)) { 870 if (frame_state(insn->state) != frame_state(state)) {
818 WARN_FUNC("frame pointer state mismatch", 871 WARN_FUNC("frame pointer state mismatch",
@@ -823,13 +876,6 @@ static int validate_branch(struct objtool_file *file,
823 return 0; 876 return 0;
824 } 877 }
825 878
826 /*
827 * Catch a rare case where a noreturn function falls through to
828 * the next function.
829 */
830 if (is_fentry_call(insn) && (state & STATE_FENTRY))
831 return 0;
832
833 insn->visited = true; 879 insn->visited = true;
834 insn->state = state; 880 insn->state = state;
835 881
@@ -1035,12 +1081,8 @@ static int validate_functions(struct objtool_file *file)
1035 continue; 1081 continue;
1036 1082
1037 insn = find_insn(file, sec, func->offset); 1083 insn = find_insn(file, sec, func->offset);
1038 if (!insn) { 1084 if (!insn)
1039 WARN("%s(): can't find starting instruction",
1040 func->name);
1041 warnings++;
1042 continue; 1085 continue;
1043 }
1044 1086
1045 ret = validate_branch(file, insn, 0); 1087 ret = validate_branch(file, insn, 0);
1046 warnings += ret; 1088 warnings += ret;
@@ -1056,13 +1098,14 @@ static int validate_functions(struct objtool_file *file)
1056 if (insn->visited) 1098 if (insn->visited)
1057 continue; 1099 continue;
1058 1100
1059 if (!ignore_unreachable_insn(func, insn) &&
1060 !warnings) {
1061 WARN_FUNC("function has unreachable instruction", insn->sec, insn->offset);
1062 warnings++;
1063 }
1064
1065 insn->visited = true; 1101 insn->visited = true;
1102
1103 if (file->ignore_unreachables || warnings ||
1104 ignore_unreachable_insn(func, insn))
1105 continue;
1106
1107 WARN_FUNC("function has unreachable instruction", insn->sec, insn->offset);
1108 warnings++;
1066 } 1109 }
1067 } 1110 }
1068 } 1111 }
@@ -1133,6 +1176,10 @@ int cmd_check(int argc, const char **argv)
1133 1176
1134 INIT_LIST_HEAD(&file.insn_list); 1177 INIT_LIST_HEAD(&file.insn_list);
1135 hash_init(file.insn_hash); 1178 hash_init(file.insn_hash);
1179 file.whitelist = find_section_by_name(file.elf, "__func_stack_frame_non_standard");
1180 file.rodata = find_section_by_name(file.elf, ".rodata");
1181 file.ignore_unreachables = false;
1182 file.c_file = find_section_by_name(file.elf, ".comment");
1136 1183
1137 ret = decode_sections(&file); 1184 ret = decode_sections(&file);
1138 if (ret < 0) 1185 if (ret < 0)
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 407f11b97c8d..617578440989 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -1130,7 +1130,7 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
1130 pr_err("Intel Processor Trace: failed to deliver transaction event, error %d\n", 1130 pr_err("Intel Processor Trace: failed to deliver transaction event, error %d\n",
1131 ret); 1131 ret);
1132 1132
1133 if (pt->synth_opts.callchain) 1133 if (pt->synth_opts.last_branch)
1134 intel_pt_reset_last_branch_rb(ptq); 1134 intel_pt_reset_last_branch_rb(ptq);
1135 1135
1136 return ret; 1136 return ret;
diff --git a/tools/testing/selftests/net/.gitignore b/tools/testing/selftests/net/.gitignore
index 69bb3fc38fb2..0840684deb7d 100644
--- a/tools/testing/selftests/net/.gitignore
+++ b/tools/testing/selftests/net/.gitignore
@@ -3,3 +3,4 @@ psock_fanout
3psock_tpacket 3psock_tpacket
4reuseport_bpf 4reuseport_bpf
5reuseport_bpf_cpu 5reuseport_bpf_cpu
6reuseport_dualstack
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index c658792d47b4..0e5340742620 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -4,7 +4,7 @@ CFLAGS = -Wall -O2 -g
4 4
5CFLAGS += -I../../../../usr/include/ 5CFLAGS += -I../../../../usr/include/
6 6
7NET_PROGS = socket psock_fanout psock_tpacket reuseport_bpf reuseport_bpf_cpu 7NET_PROGS = socket psock_fanout psock_tpacket reuseport_bpf reuseport_bpf_cpu reuseport_dualstack
8 8
9all: $(NET_PROGS) 9all: $(NET_PROGS)
10%: %.c 10%: %.c
diff --git a/tools/testing/selftests/net/reuseport_dualstack.c b/tools/testing/selftests/net/reuseport_dualstack.c
new file mode 100644
index 000000000000..90958aaaafb9
--- /dev/null
+++ b/tools/testing/selftests/net/reuseport_dualstack.c
@@ -0,0 +1,208 @@
1/*
2 * It is possible to use SO_REUSEPORT to open multiple sockets bound to
3 * equivalent local addresses using AF_INET and AF_INET6 at the same time. If
4 * the AF_INET6 socket has IPV6_V6ONLY set, it's clear which socket should
5 * receive a given incoming packet. However, when it is not set, incoming v4
6 * packets should prefer the AF_INET socket(s). This behavior was defined with
7 * the original SO_REUSEPORT implementation, but broke with
8 * e32ea7e74727 ("soreuseport: fast reuseport UDP socket selection")
9 * This test creates these mixed AF_INET/AF_INET6 sockets and asserts the
10 * AF_INET preference for v4 packets.
11 */
12
13#define _GNU_SOURCE
14
15#include <arpa/inet.h>
16#include <errno.h>
17#include <error.h>
18#include <linux/in.h>
19#include <linux/unistd.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <sys/epoll.h>
24#include <sys/types.h>
25#include <sys/socket.h>
26#include <unistd.h>
27
28static const int PORT = 8888;
29
30static void build_rcv_fd(int family, int proto, int *rcv_fds, int count)
31{
32 struct sockaddr_storage addr;
33 struct sockaddr_in *addr4;
34 struct sockaddr_in6 *addr6;
35 int opt, i;
36
37 switch (family) {
38 case AF_INET:
39 addr4 = (struct sockaddr_in *)&addr;
40 addr4->sin_family = AF_INET;
41 addr4->sin_addr.s_addr = htonl(INADDR_ANY);
42 addr4->sin_port = htons(PORT);
43 break;
44 case AF_INET6:
45 addr6 = (struct sockaddr_in6 *)&addr;
46 addr6->sin6_family = AF_INET6;
47 addr6->sin6_addr = in6addr_any;
48 addr6->sin6_port = htons(PORT);
49 break;
50 default:
51 error(1, 0, "Unsupported family %d", family);
52 }
53
54 for (i = 0; i < count; ++i) {
55 rcv_fds[i] = socket(family, proto, 0);
56 if (rcv_fds[i] < 0)
57 error(1, errno, "failed to create receive socket");
58
59 opt = 1;
60 if (setsockopt(rcv_fds[i], SOL_SOCKET, SO_REUSEPORT, &opt,
61 sizeof(opt)))
62 error(1, errno, "failed to set SO_REUSEPORT");
63
64 if (bind(rcv_fds[i], (struct sockaddr *)&addr, sizeof(addr)))
65 error(1, errno, "failed to bind receive socket");
66
67 if (proto == SOCK_STREAM && listen(rcv_fds[i], 10))
68 error(1, errno, "failed to listen on receive port");
69 }
70}
71
72static void send_from_v4(int proto)
73{
74 struct sockaddr_in saddr, daddr;
75 int fd;
76
77 saddr.sin_family = AF_INET;
78 saddr.sin_addr.s_addr = htonl(INADDR_ANY);
79 saddr.sin_port = 0;
80
81 daddr.sin_family = AF_INET;
82 daddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
83 daddr.sin_port = htons(PORT);
84
85 fd = socket(AF_INET, proto, 0);
86 if (fd < 0)
87 error(1, errno, "failed to create send socket");
88
89 if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)))
90 error(1, errno, "failed to bind send socket");
91
92 if (connect(fd, (struct sockaddr *)&daddr, sizeof(daddr)))
93 error(1, errno, "failed to connect send socket");
94
95 if (send(fd, "a", 1, 0) < 0)
96 error(1, errno, "failed to send message");
97
98 close(fd);
99}
100
101static int receive_once(int epfd, int proto)
102{
103 struct epoll_event ev;
104 int i, fd;
105 char buf[8];
106
107 i = epoll_wait(epfd, &ev, 1, -1);
108 if (i < 0)
109 error(1, errno, "epoll_wait failed");
110
111 if (proto == SOCK_STREAM) {
112 fd = accept(ev.data.fd, NULL, NULL);
113 if (fd < 0)
114 error(1, errno, "failed to accept");
115 i = recv(fd, buf, sizeof(buf), 0);
116 close(fd);
117 } else {
118 i = recv(ev.data.fd, buf, sizeof(buf), 0);
119 }
120
121 if (i < 0)
122 error(1, errno, "failed to recv");
123
124 return ev.data.fd;
125}
126
127static void test(int *rcv_fds, int count, int proto)
128{
129 struct epoll_event ev;
130 int epfd, i, test_fd;
131 uint16_t test_family;
132 socklen_t len;
133
134 epfd = epoll_create(1);
135 if (epfd < 0)
136 error(1, errno, "failed to create epoll");
137
138 ev.events = EPOLLIN;
139 for (i = 0; i < count; ++i) {
140 ev.data.fd = rcv_fds[i];
141 if (epoll_ctl(epfd, EPOLL_CTL_ADD, rcv_fds[i], &ev))
142 error(1, errno, "failed to register sock epoll");
143 }
144
145 send_from_v4(proto);
146
147 test_fd = receive_once(epfd, proto);
148 if (getsockopt(test_fd, SOL_SOCKET, SO_DOMAIN, &test_family, &len))
149 error(1, errno, "failed to read socket domain");
150 if (test_family != AF_INET)
151 error(1, 0, "expected to receive on v4 socket but got v6 (%d)",
152 test_family);
153
154 close(epfd);
155}
156
157int main(void)
158{
159 int rcv_fds[32], i;
160
161 fprintf(stderr, "---- UDP IPv4 created before IPv6 ----\n");
162 build_rcv_fd(AF_INET, SOCK_DGRAM, rcv_fds, 5);
163 build_rcv_fd(AF_INET6, SOCK_DGRAM, &(rcv_fds[5]), 5);
164 test(rcv_fds, 10, SOCK_DGRAM);
165 for (i = 0; i < 10; ++i)
166 close(rcv_fds[i]);
167
168 fprintf(stderr, "---- UDP IPv6 created before IPv4 ----\n");
169 build_rcv_fd(AF_INET6, SOCK_DGRAM, rcv_fds, 5);
170 build_rcv_fd(AF_INET, SOCK_DGRAM, &(rcv_fds[5]), 5);
171 test(rcv_fds, 10, SOCK_DGRAM);
172 for (i = 0; i < 10; ++i)
173 close(rcv_fds[i]);
174
175 /* NOTE: UDP socket lookups traverse a different code path when there
176 * are > 10 sockets in a group.
177 */
178 fprintf(stderr, "---- UDP IPv4 created before IPv6 (large) ----\n");
179 build_rcv_fd(AF_INET, SOCK_DGRAM, rcv_fds, 16);
180 build_rcv_fd(AF_INET6, SOCK_DGRAM, &(rcv_fds[16]), 16);
181 test(rcv_fds, 32, SOCK_DGRAM);
182 for (i = 0; i < 32; ++i)
183 close(rcv_fds[i]);
184
185 fprintf(stderr, "---- UDP IPv6 created before IPv4 (large) ----\n");
186 build_rcv_fd(AF_INET6, SOCK_DGRAM, rcv_fds, 16);
187 build_rcv_fd(AF_INET, SOCK_DGRAM, &(rcv_fds[16]), 16);
188 test(rcv_fds, 32, SOCK_DGRAM);
189 for (i = 0; i < 32; ++i)
190 close(rcv_fds[i]);
191
192 fprintf(stderr, "---- TCP IPv4 created before IPv6 ----\n");
193 build_rcv_fd(AF_INET, SOCK_STREAM, rcv_fds, 5);
194 build_rcv_fd(AF_INET6, SOCK_STREAM, &(rcv_fds[5]), 5);
195 test(rcv_fds, 10, SOCK_STREAM);
196 for (i = 0; i < 10; ++i)
197 close(rcv_fds[i]);
198
199 fprintf(stderr, "---- TCP IPv6 created before IPv4 ----\n");
200 build_rcv_fd(AF_INET6, SOCK_STREAM, rcv_fds, 5);
201 build_rcv_fd(AF_INET, SOCK_STREAM, &(rcv_fds[5]), 5);
202 test(rcv_fds, 10, SOCK_STREAM);
203 for (i = 0; i < 10; ++i)
204 close(rcv_fds[i]);
205
206 fprintf(stderr, "SUCCESS\n");
207 return 0;
208}