Fix: lttng-snapshot: use after free of max size argument
[lttng-tools.git] / src / bin / lttng-consumerd / health-consumerd.cpp
1 /*
2 * Copyright (C) 2013 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8 #define _LGPL_SOURCE
9 #include <fcntl.h>
10 #include <getopt.h>
11 #include <grp.h>
12 #include <limits.h>
13 #include <pthread.h>
14 #include <signal.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <sys/ipc.h>
19 #include <sys/resource.h>
20 #include <sys/shm.h>
21 #include <sys/socket.h>
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <urcu/list.h>
25 #include <poll.h>
26 #include <unistd.h>
27 #include <sys/mman.h>
28 #include <urcu/compiler.h>
29 #include <ulimit.h>
30 #include <inttypes.h>
31
32 #include <common/defaults.h>
33 #include <common/common.h>
34 #include <common/consumer/consumer.h>
35 #include <common/consumer/consumer-timer.h>
36 #include <common/compat/poll.h>
37 #include <common/sessiond-comm/sessiond-comm.h>
38 #include <common/utils.h>
39
40 #include "lttng-consumerd.h"
41 #include "health-consumerd.h"
42
43 /* Global health check unix path */
44 static char health_unix_sock_path[PATH_MAX];
45
46 int health_quit_pipe[2];
47
48 /*
49 * Check if the thread quit pipe was triggered.
50 *
51 * Return 1 if it was triggered else 0;
52 */
53 static
54 int check_health_quit_pipe(int fd, uint32_t events)
55 {
56 if (fd == health_quit_pipe[0] && (events & LPOLLIN)) {
57 return 1;
58 }
59
60 return 0;
61 }
62
63 /*
64 * Send data on a unix socket using the liblttsessiondcomm API.
65 *
66 * Return lttcomm error code.
67 */
68 static int send_unix_sock(int sock, void *buf, size_t len)
69 {
70 /* Check valid length */
71 if (len == 0) {
72 return -1;
73 }
74
75 return lttcomm_send_unix_sock(sock, buf, len);
76 }
77
78 static
79 int setup_health_path(void)
80 {
81 int is_root, ret = 0;
82 enum lttng_consumer_type type;
83 const char *home_path;
84
85 type = lttng_consumer_get_type();
86 is_root = !getuid();
87
88 if (is_root) {
89 if (strlen(health_unix_sock_path) != 0) {
90 goto end;
91 }
92 switch (type) {
93 case LTTNG_CONSUMER_KERNEL:
94 snprintf(health_unix_sock_path, sizeof(health_unix_sock_path),
95 DEFAULT_GLOBAL_KCONSUMER_HEALTH_UNIX_SOCK);
96 break;
97 case LTTNG_CONSUMER64_UST:
98 snprintf(health_unix_sock_path, sizeof(health_unix_sock_path),
99 DEFAULT_GLOBAL_USTCONSUMER64_HEALTH_UNIX_SOCK);
100 break;
101 case LTTNG_CONSUMER32_UST:
102 snprintf(health_unix_sock_path, sizeof(health_unix_sock_path),
103 DEFAULT_GLOBAL_USTCONSUMER32_HEALTH_UNIX_SOCK);
104 break;
105 default:
106 ret = -EINVAL;
107 goto end;
108 }
109 } else {
110 home_path = utils_get_home_dir();
111 if (home_path == NULL) {
112 /* TODO: Add --socket PATH option */
113 ERR("Can't get HOME directory for sockets creation.");
114 ret = -EPERM;
115 goto end;
116 }
117
118 /* Set health check Unix path */
119 if (strlen(health_unix_sock_path) != 0) {
120 goto end;
121 }
122 switch (type) {
123 case LTTNG_CONSUMER_KERNEL:
124 snprintf(health_unix_sock_path, sizeof(health_unix_sock_path),
125 DEFAULT_HOME_KCONSUMER_HEALTH_UNIX_SOCK, home_path);
126 break;
127 case LTTNG_CONSUMER64_UST:
128 snprintf(health_unix_sock_path, sizeof(health_unix_sock_path),
129 DEFAULT_HOME_USTCONSUMER64_HEALTH_UNIX_SOCK, home_path);
130 break;
131 case LTTNG_CONSUMER32_UST:
132 snprintf(health_unix_sock_path, sizeof(health_unix_sock_path),
133 DEFAULT_HOME_USTCONSUMER32_HEALTH_UNIX_SOCK, home_path);
134 break;
135 default:
136 ret = -EINVAL;
137 goto end;
138 }
139 }
140 end:
141 return ret;
142 }
143
144 /*
145 * Thread managing health check socket.
146 */
147 void *thread_manage_health(void *data)
148 {
149 int sock = -1, new_sock = -1, ret, i, pollfd, err = -1;
150 uint32_t revents, nb_fd;
151 struct lttng_poll_event events;
152 struct health_comm_msg msg;
153 struct health_comm_reply reply;
154 int is_root;
155
156 DBG("[thread] Manage health check started");
157
158 setup_health_path();
159
160 rcu_register_thread();
161
162 /* We might hit an error path before this is created. */
163 lttng_poll_init(&events);
164
165 /* Create unix socket */
166 sock = lttcomm_create_unix_sock(health_unix_sock_path);
167 if (sock < 0) {
168 ERR("Unable to create health check Unix socket");
169 err = -1;
170 goto error;
171 }
172
173 is_root = !getuid();
174 if (is_root) {
175 /* lttng health client socket path permissions */
176 gid_t gid;
177
178 ret = utils_get_group_id(tracing_group_name, true, &gid);
179 if (ret) {
180 /* Default to root group. */
181 gid = 0;
182 }
183
184 ret = chown(health_unix_sock_path, 0, gid);
185 if (ret < 0) {
186 ERR("Unable to set group on %s", health_unix_sock_path);
187 PERROR("chown");
188 err = -1;
189 goto error;
190 }
191
192 ret = chmod(health_unix_sock_path,
193 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
194 if (ret < 0) {
195 ERR("Unable to set permissions on %s", health_unix_sock_path);
196 PERROR("chmod");
197 err = -1;
198 goto error;
199 }
200 }
201
202 /*
203 * Set the CLOEXEC flag. Return code is useless because either way, the
204 * show must go on.
205 */
206 (void) utils_set_fd_cloexec(sock);
207
208 ret = lttcomm_listen_unix_sock(sock);
209 if (ret < 0) {
210 goto error;
211 }
212
213 /* Size is set to 1 for the consumer_channel pipe */
214 ret = lttng_poll_create(&events, 2, LTTNG_CLOEXEC);
215 if (ret < 0) {
216 ERR("Poll set creation failed");
217 goto error;
218 }
219
220 ret = lttng_poll_add(&events, health_quit_pipe[0], LPOLLIN);
221 if (ret < 0) {
222 goto error;
223 }
224
225 /* Add the application registration socket */
226 ret = lttng_poll_add(&events, sock, LPOLLIN | LPOLLPRI);
227 if (ret < 0) {
228 goto error;
229 }
230
231 /* Perform prior memory accesses before decrementing ready */
232 cmm_smp_mb__before_uatomic_dec();
233 uatomic_dec(&lttng_consumer_ready);
234
235 while (1) {
236 DBG("Health check ready");
237
238 /* Inifinite blocking call, waiting for transmission */
239 restart:
240 ret = lttng_poll_wait(&events, -1);
241 if (ret < 0) {
242 /*
243 * Restart interrupted system call.
244 */
245 if (errno == EINTR) {
246 goto restart;
247 }
248 goto error;
249 }
250
251 nb_fd = ret;
252
253 for (i = 0; i < nb_fd; i++) {
254 /* Fetch once the poll data */
255 revents = LTTNG_POLL_GETEV(&events, i);
256 pollfd = LTTNG_POLL_GETFD(&events, i);
257
258 /* Thread quit pipe has been closed. Killing thread. */
259 ret = check_health_quit_pipe(pollfd, revents);
260 if (ret) {
261 err = 0;
262 goto exit;
263 }
264
265 /* Event on the registration socket */
266 if (pollfd == sock) {
267 if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)
268 && !(revents & LPOLLIN)) {
269 ERR("Health socket poll error");
270 goto error;
271 }
272 }
273 }
274
275 new_sock = lttcomm_accept_unix_sock(sock);
276 if (new_sock < 0) {
277 goto error;
278 }
279
280 /*
281 * Set the CLOEXEC flag. Return code is useless because either way, the
282 * show must go on.
283 */
284 (void) utils_set_fd_cloexec(new_sock);
285
286 DBG("Receiving data from client for health...");
287 ret = lttcomm_recv_unix_sock(new_sock, (void *)&msg, sizeof(msg));
288 if (ret <= 0) {
289 DBG("Nothing recv() from client... continuing");
290 ret = close(new_sock);
291 if (ret) {
292 PERROR("close");
293 }
294 new_sock = -1;
295 continue;
296 }
297
298 rcu_thread_online();
299
300 LTTNG_ASSERT(msg.cmd == HEALTH_CMD_CHECK);
301
302 memset(&reply, 0, sizeof(reply));
303 for (i = 0; i < NR_HEALTH_CONSUMERD_TYPES; i++) {
304 /*
305 * health_check_state return 0 if thread is in
306 * error.
307 */
308 if (!health_check_state(health_consumerd, i)) {
309 reply.ret_code |= 1ULL << i;
310 }
311 }
312
313 DBG("Health check return value %" PRIx64, reply.ret_code);
314
315 ret = send_unix_sock(new_sock, (void *) &reply, sizeof(reply));
316 if (ret < 0) {
317 ERR("Failed to send health data back to client");
318 }
319
320 /* End of transmission */
321 ret = close(new_sock);
322 if (ret) {
323 PERROR("close");
324 }
325 new_sock = -1;
326 }
327
328 exit:
329 error:
330 if (err) {
331 ERR("Health error occurred in %s", __func__);
332 }
333 DBG("Health check thread dying");
334 unlink(health_unix_sock_path);
335 if (sock >= 0) {
336 ret = close(sock);
337 if (ret) {
338 PERROR("close");
339 }
340 }
341
342 lttng_poll_clean(&events);
343
344 rcu_unregister_thread();
345 return NULL;
346 }
This page took 0.053883 seconds and 4 git commands to generate.