aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-kernel/lttng/lttng-modules/0003-Fix-Sleeping-function-called-from-invalid-context.patch
blob: d444a0728a08f242f9a39b52488b78e57bb20c4b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
From c1af5643e0df56b92481f7a7bc4110a58e4e5abb Mon Sep 17 00:00:00 2001
From: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Date: Fri, 21 Jul 2017 08:22:04 -0400
Subject: [PATCH 3/8] Fix: Sleeping function called from invalid context
Organization: O.S. Systems Software LTDA.

It affects system call instrumentation for accept, accept4 and connect,
only on the x86-64 architecture.

We need to use the LTTng accessing functions to touch user-space memory,
which take care of disabling the page fault handler, so we don't preempt
while in preempt-off context (tracepoints disable preemption).

Fixes #1111

Upstream-Status: Backport [2.9.4]

Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
---
 .../x86-64-syscalls-3.10.0-rc7_pointers_override.h | 47 ++++++++++++++--------
 1 file changed, 31 insertions(+), 16 deletions(-)

diff --git a/instrumentation/syscalls/headers/x86-64-syscalls-3.10.0-rc7_pointers_override.h b/instrumentation/syscalls/headers/x86-64-syscalls-3.10.0-rc7_pointers_override.h
index 5e91004..6bf5291 100644
--- a/instrumentation/syscalls/headers/x86-64-syscalls-3.10.0-rc7_pointers_override.h
+++ b/instrumentation/syscalls/headers/x86-64-syscalls-3.10.0-rc7_pointers_override.h
@@ -2,7 +2,7 @@
 
 #define OVERRIDE_64_connect
 SC_LTTNG_TRACEPOINT_EVENT_CODE(connect,
-	TP_PROTO(sc_exit(long ret,) int fd, struct sockaddr * uservaddr, int addrlen),
+	TP_PROTO(sc_exit(long ret,) int fd, struct sockaddr __user * uservaddr, int addrlen),
 	TP_ARGS(sc_exit(ret,) fd, uservaddr, addrlen),
 	TP_locvar(
 		__typeof__(uservaddr->sa_family) sa_family;
@@ -16,21 +16,28 @@ SC_LTTNG_TRACEPOINT_EVENT_CODE(connect,
 			memset(tp_locvar, 0, sizeof(*tp_locvar));
 			if (addrlen < sizeof(tp_locvar->sa_family))
 				goto skip_code;
-			(void) get_user(tp_locvar->sa_family, &uservaddr->sa_family);
+			(void) lib_ring_buffer_copy_from_user_check_nofault(&tp_locvar->sa_family,
+					&uservaddr->sa_family, sizeof(tp_locvar->sa_family));
 			switch (tp_locvar->sa_family) {
 			case AF_INET:
 				if (addrlen < sizeof(struct sockaddr_in))
 					goto skip_code;
-				(void) get_user(tp_locvar->dport, &((struct sockaddr_in *) uservaddr)->sin_port);
-				(void) get_user(tp_locvar->v4addr, &((struct sockaddr_in *) uservaddr)->sin_addr.s_addr);
+				(void) lib_ring_buffer_copy_from_user_check_nofault(&tp_locvar->dport,
+						&((struct sockaddr_in __user *) uservaddr)->sin_port,
+						sizeof(tp_locvar->dport));
+				(void) lib_ring_buffer_copy_from_user_check_nofault(&tp_locvar->v4addr,
+						&((struct sockaddr_in __user *) uservaddr)->sin_addr.s_addr,
+						sizeof(tp_locvar->v4addr));
 				tp_locvar->v4addr_len = 4;
 				break;
 			case AF_INET6:
 				if (addrlen < sizeof(struct sockaddr_in6))
 					goto skip_code;
-				(void) get_user(tp_locvar->dport, &((struct sockaddr_in6 *) uservaddr)->sin6_port);
-				if (copy_from_user(tp_locvar->v6addr,
-						&((struct sockaddr_in6 *) uservaddr)->sin6_addr.in6_u.u6_addr8,
+				(void) lib_ring_buffer_copy_from_user_check_nofault(&tp_locvar->dport,
+						&((struct sockaddr_in6 __user *) uservaddr)->sin6_port,
+						sizeof(tp_locvar->dport));
+				if (lib_ring_buffer_copy_from_user_check_nofault(tp_locvar->v6addr,
+						&((struct sockaddr_in6 __user *) uservaddr)->sin6_addr.in6_u.u6_addr8,
 						sizeof(tp_locvar->v6addr)))
 					memset(tp_locvar->v6addr, 0, sizeof(tp_locvar->v6addr));
 				tp_locvar->v6addr_len = 8;
@@ -63,26 +70,34 @@ SC_LTTNG_TRACEPOINT_EVENT_CODE(connect,
 #define LTTNG_SYSCALL_ACCEPT_code_pre											\
 	sc_inout(													\
 		memset(tp_locvar, 0, sizeof(*tp_locvar));								\
-		(void) get_user(tp_locvar->uaddr_len, upeer_addrlen);							\
+		(void) lib_ring_buffer_copy_from_user_check_nofault(&tp_locvar->uaddr_len,				\
+				upeer_addrlen, sizeof(tp_locvar->uaddr_len));						\
 	)														\
 	sc_out(														\
 		if (tp_locvar->uaddr_len < sizeof(tp_locvar->sa_family))						\
 			goto skip_code;											\
-		(void) get_user(tp_locvar->sa_family, &upeer_sockaddr->sa_family);					\
+		(void) lib_ring_buffer_copy_from_user_check_nofault(&tp_locvar->sa_family,				\
+				&upeer_sockaddr->sa_family, sizeof(tp_locvar->sa_family));				\
 		switch (tp_locvar->sa_family) {										\
 		case AF_INET:												\
 			if (tp_locvar->uaddr_len < sizeof(struct sockaddr_in))						\
 				goto skip_code;										\
-			(void) get_user(tp_locvar->sport, &((struct sockaddr_in *) upeer_sockaddr)->sin_port);		\
-			(void) get_user(tp_locvar->v4addr, &((struct sockaddr_in *) upeer_sockaddr)->sin_addr.s_addr);	\
+			(void) lib_ring_buffer_copy_from_user_check_nofault(&tp_locvar->sport,				\
+					&((struct sockaddr_in __user *) upeer_sockaddr)->sin_port,			\
+					sizeof(tp_locvar->sport));							\
+			(void) lib_ring_buffer_copy_from_user_check_nofault(&tp_locvar->v4addr,				\
+					&((struct sockaddr_in __user *) upeer_sockaddr)->sin_addr.s_addr,		\
+					sizeof(tp_locvar->v4addr));							\
 			tp_locvar->v4addr_len = 4;									\
 			break;												\
 		case AF_INET6:												\
 			if (tp_locvar->uaddr_len < sizeof(struct sockaddr_in6))						\
 				goto skip_code;										\
-			(void) get_user(tp_locvar->sport, &((struct sockaddr_in6 *) upeer_sockaddr)->sin6_port);	\
-			if (copy_from_user(tp_locvar->v6addr,								\
-					&((struct sockaddr_in6 *) upeer_sockaddr)->sin6_addr.in6_u.u6_addr8,		\
+			(void) lib_ring_buffer_copy_from_user_check_nofault(&tp_locvar->sport,				\
+					&((struct sockaddr_in6 __user *) upeer_sockaddr)->sin6_port,			\
+					sizeof(tp_locvar->sport));							\
+			if (lib_ring_buffer_copy_from_user_check_nofault(tp_locvar->v6addr,				\
+					&((struct sockaddr_in6 __user *) upeer_sockaddr)->sin6_addr.in6_u.u6_addr8,	\
 					sizeof(tp_locvar->v6addr)))							\
 				memset(tp_locvar->v6addr, 0, sizeof(tp_locvar->v6addr));				\
 			tp_locvar->v6addr_len = 8;									\
@@ -93,7 +108,7 @@ SC_LTTNG_TRACEPOINT_EVENT_CODE(connect,
 
 #define OVERRIDE_64_accept
 SC_LTTNG_TRACEPOINT_EVENT_CODE(accept,
-	TP_PROTO(sc_exit(long ret,) int fd, struct sockaddr * upeer_sockaddr, int * upeer_addrlen),
+	TP_PROTO(sc_exit(long ret,) int fd, struct sockaddr __user * upeer_sockaddr, int __user * upeer_addrlen),
 	TP_ARGS(sc_exit(ret,) fd, upeer_sockaddr, upeer_addrlen),
 	TP_locvar(
 		LTTNG_SYSCALL_ACCEPT_locvar
@@ -116,7 +131,7 @@ SC_LTTNG_TRACEPOINT_EVENT_CODE(accept,
 
 #define OVERRIDE_64_accept4
 SC_LTTNG_TRACEPOINT_EVENT_CODE(accept4,
-	TP_PROTO(sc_exit(long ret,) int fd, struct sockaddr * upeer_sockaddr, int * upeer_addrlen, int flags),
+	TP_PROTO(sc_exit(long ret,) int fd, struct sockaddr __user * upeer_sockaddr, int __user * upeer_addrlen, int flags),
 	TP_ARGS(sc_exit(ret,) fd, upeer_sockaddr, upeer_addrlen, flags),
 	TP_locvar(
 		LTTNG_SYSCALL_ACCEPT_locvar
-- 
2.14.1