]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/commands.c
Merge pull request #3617 from motiejus/lxc-net-dnsmasq
[mirror_lxc.git] / src / lxc / commands.c
CommitLineData
cc73685d 1/* SPDX-License-Identifier: LGPL-2.1+ */
724e753c 2
d38dd64a
CB
3#ifndef _GNU_SOURCE
4#define _GNU_SOURCE 1
5#endif
cf685555 6#include <caps.h>
724e753c 7#include <errno.h>
91480a0f 8#include <fcntl.h>
fe84a562 9#include <malloc.h>
37515ebd 10#include <poll.h>
fe84a562
CB
11#include <signal.h>
12#include <stdio.h>
13#include <stdlib.h>
fe84a562 14#include <sys/param.h>
724e753c
MN
15#include <sys/socket.h>
16#include <sys/un.h>
d38dd64a 17#include <unistd.h>
724e753c 18
fe84a562 19#include "af_unix.h"
f2363e38 20#include "cgroup.h"
2a63b5cb 21#include "cgroups/cgroup2_devices.h"
724e753c 22#include "commands.h"
bbf5cf35 23#include "commands_utils.h"
fe84a562 24#include "conf.h"
d38dd64a 25#include "config.h"
ef6e34ee 26#include "confile.h"
fe84a562
CB
27#include "log.h"
28#include "lxc.h"
dbc9832d 29#include "lxclock.h"
cdb2a47f 30#include "lxcseccomp.h"
724e753c 31#include "mainloop.h"
5265a60c 32#include "memory_utils.h"
dbc9832d 33#include "monitor.h"
fe84a562 34#include "start.h"
0ed9b1bc 35#include "terminal.h"
fe84a562 36#include "utils.h"
724e753c 37
ded1d23f 38/*
fe84a562
CB
39 * This file provides the different functions for clients to query/command the
40 * server. The client is typically some lxc tool and the server is typically the
41 * container (ie. lxc-start).
ded1d23f 42 *
fe84a562
CB
43 * Each command is transactional, the clients send a request to the server and
44 * the server answers the request with a message giving the request's status
45 * (zero or a negative errno value). Both the request and response may contain
46 * additional data.
ded1d23f 47 *
fe84a562
CB
48 * Each command is wrapped in a ancillary message in order to pass a credential
49 * making possible to the server to check if the client is allowed to ask for
50 * this command or not.
80bcb053 51 *
fe84a562
CB
52 * IMPORTANTLY: Note that semantics for current commands are fixed. If you wish
53 * to make any changes to how, say, LXC_CMD_GET_CONFIG_ITEM works by adding
54 * information to the end of cmd.data, then you must introduce a new
55 * LXC_CMD_GET_CONFIG_ITEM_V2 define with a new number. You may wish to also
56 * mark LXC_CMD_GET_CONFIG_ITEM deprecated in commands.h.
80bcb053
SH
57 *
58 * This is necessary in order to avoid having a newly compiled lxc command
59 * communicating with a running (old) monitor from crashing the running
60 * container.
ded1d23f
DL
61 */
62
ac2cecc4 63lxc_log_define(commands, lxc);
724e753c 64
ef6e34ee 65static const char *lxc_cmd_str(lxc_cmd_t cmd)
724e753c 66{
fe84a562 67 static const char *const cmdname[LXC_CMD_MAX] = {
2a63b5cb
CB
68 [LXC_CMD_CONSOLE] = "console",
69 [LXC_CMD_TERMINAL_WINCH] = "terminal_winch",
70 [LXC_CMD_STOP] = "stop",
71 [LXC_CMD_GET_STATE] = "get_state",
72 [LXC_CMD_GET_INIT_PID] = "get_init_pid",
73 [LXC_CMD_GET_CLONE_FLAGS] = "get_clone_flags",
74 [LXC_CMD_GET_CGROUP] = "get_cgroup",
75 [LXC_CMD_GET_CONFIG_ITEM] = "get_config_item",
76 [LXC_CMD_GET_NAME] = "get_name",
77 [LXC_CMD_GET_LXCPATH] = "get_lxcpath",
78 [LXC_CMD_ADD_STATE_CLIENT] = "add_state_client",
79 [LXC_CMD_CONSOLE_LOG] = "console_log",
80 [LXC_CMD_SERVE_STATE_CLIENTS] = "serve_state_clients",
81 [LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER] = "seccomp_notify_add_listener",
82 [LXC_CMD_ADD_BPF_DEVICE_CGROUP] = "add_bpf_device_cgroup",
018051e3
CB
83 [LXC_CMD_FREEZE] = "freeze",
84 [LXC_CMD_UNFREEZE] = "unfreeze",
bad788b0 85 [LXC_CMD_GET_CGROUP2_FD] = "get_cgroup2_fd",
746aab51 86 [LXC_CMD_GET_INIT_PIDFD] = "get_init_pidfd",
a900cbaf
WB
87 [LXC_CMD_GET_LIMITING_CGROUP] = "get_limiting_cgroup",
88 [LXC_CMD_GET_LIMITING_CGROUP2_FD] = "get_limiting_cgroup2_fd",
f797f05e 89 [LXC_CMD_GET_DEVPTS_FD] = "get_devpts_fd",
21405769 90 [LXC_CMD_GET_SECCOMP_NOTIFY_FD] = "get_seccomp_notify_fd",
ef6e34ee 91 };
724e753c 92
f371aca9 93 if (cmd >= LXC_CMD_MAX)
a8007512 94 return "Invalid request";
fe84a562 95
ef6e34ee
DE
96 return cmdname[cmd];
97}
98
99/*
100 * lxc_cmd_rsp_recv: Receive a response to a command
101 *
102 * @sock : the socket connected to the container
103 * @cmd : command to put response in
104 *
105 * Returns the size of the response message or < 0 on failure
106 *
107 * Note that if the command response datalen > 0, then data is
108 * a malloc()ed buffer and should be free()ed by the caller. If
109 * the response data is <= a void * worth of data, it will be
110 * stored directly in data and datalen will be 0.
111 *
112 * As a special case, the response for LXC_CMD_CONSOLE is created
36a94ce8 113 * here as it contains an fd for the ptx pty passed through the
0115f8fd 114 * unix socket.
ef6e34ee
DE
115 */
116static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
117{
f62cf1d4 118 __do_close int fd_rsp = -EBADF;
23a917e5 119 int ret;
ef6e34ee
DE
120 struct lxc_cmd_rsp *rsp = &cmd->rsp;
121
23a917e5
CB
122 ret = lxc_abstract_unix_recv_fds(sock, &fd_rsp, 1, rsp, sizeof(*rsp));
123 if (ret < 0)
124 return log_warn_errno(-1,
125 errno, "Failed to receive response for command \"%s\"",
126 lxc_cmd_str(cmd->req.cmd));
fe84a562 127 TRACE("Command \"%s\" received response", lxc_cmd_str(cmd->req.cmd));
ef6e34ee
DE
128
129 if (cmd->req.cmd == LXC_CMD_CONSOLE) {
130 struct lxc_cmd_console_rsp_data *rspdata;
131
0115f8fd
DE
132 /* recv() returns 0 bytes when a tty cannot be allocated,
133 * rsp->ret is < 0 when the peer permission check failed
134 */
135 if (ret == 0 || rsp->ret < 0)
136 return 0;
137
ef6e34ee 138 rspdata = malloc(sizeof(*rspdata));
23a917e5
CB
139 if (!rspdata)
140 return log_warn_errno(-1,
141 ENOMEM, "Failed to receive response for command \"%s\"",
142 lxc_cmd_str(cmd->req.cmd));
2a850b2c 143
36a94ce8 144 rspdata->ptxfd = move_fd(fd_rsp);
ef6e34ee
DE
145 rspdata->ttynum = PTR_TO_INT(rsp->data);
146 rsp->data = rspdata;
147 }
148
a900cbaf
WB
149 if (cmd->req.cmd == LXC_CMD_GET_CGROUP2_FD ||
150 cmd->req.cmd == LXC_CMD_GET_LIMITING_CGROUP2_FD)
151 {
23a917e5
CB
152 int cgroup2_fd = move_fd(fd_rsp);
153 rsp->data = INT_TO_PTR(cgroup2_fd);
860e7c43 154 }
fe84a562 155
746aab51
CB
156 if (cmd->req.cmd == LXC_CMD_GET_INIT_PIDFD) {
157 int init_pidfd = move_fd(fd_rsp);
158 rsp->data = INT_TO_PTR(init_pidfd);
159 }
160
f797f05e
CB
161 if (cmd->req.cmd == LXC_CMD_GET_DEVPTS_FD) {
162 int devpts_fd = move_fd(fd_rsp);
163 rsp->data = INT_TO_PTR(devpts_fd);
164 }
165
21405769
CB
166 if (cmd->req.cmd == LXC_CMD_GET_SECCOMP_NOTIFY_FD) {
167 int seccomp_notify_fd = move_fd(fd_rsp);
168 rsp->data = INT_TO_PTR(seccomp_notify_fd);
169 }
170
23a917e5
CB
171 if (rsp->datalen == 0)
172 return log_debug(ret,
173 "Response data length for command \"%s\" is 0",
174 lxc_cmd_str(cmd->req.cmd));
175
191d43cc 176 if ((rsp->datalen > LXC_CMD_DATA_MAX) &&
23a917e5
CB
177 (cmd->req.cmd != LXC_CMD_CONSOLE_LOG))
178 return log_error(-1, "Response data for command \"%s\" is too long: %d bytes > %d",
179 lxc_cmd_str(cmd->req.cmd), rsp->datalen,
180 LXC_CMD_DATA_MAX);
ef6e34ee 181
191d43cc
CB
182 if (cmd->req.cmd == LXC_CMD_CONSOLE_LOG) {
183 rsp->data = malloc(rsp->datalen + 1);
184 ((char *)rsp->data)[rsp->datalen] = '\0';
185 } else {
186 rsp->data = malloc(rsp->datalen);
187 }
23a917e5
CB
188 if (!rsp->data)
189 return log_error_errno(-1,
190 ENOMEM, "Failed to allocate response buffer for command \"%s\"",
191 lxc_cmd_str(cmd->req.cmd));
fe84a562 192
2a850b2c 193 ret = lxc_recv_nointr(sock, rsp->data, rsp->datalen, 0);
23a917e5
CB
194 if (ret != rsp->datalen)
195 return log_error_errno(-1,
196 errno, "Failed to receive response data for command \"%s\"",
197 lxc_cmd_str(cmd->req.cmd));
724e753c
MN
198
199 return ret;
200}
201
ef6e34ee
DE
202/*
203 * lxc_cmd_rsp_send: Send a command response
204 *
205 * @fd : file descriptor of socket to send response on
206 * @rsp : response to send
207 *
208 * Returns 0 on success, < 0 on failure
209 */
210static int lxc_cmd_rsp_send(int fd, struct lxc_cmd_rsp *rsp)
211{
fe84a562 212 ssize_t ret;
ef6e34ee 213
7fbb15ec
CB
214 errno = EMSGSIZE;
215 ret = lxc_send_nointr(fd, rsp, sizeof(*rsp), MSG_NOSIGNAL);
6c6497ea
CB
216 if (ret < 0 || (size_t)ret != sizeof(*rsp))
217 return log_error_errno(-1, errno, "Failed to send command response %zd", ret);
ef6e34ee 218
a674dfe1 219 if (!rsp->data || rsp->datalen <= 0)
fe84a562
CB
220 return 0;
221
7fbb15ec
CB
222 errno = EMSGSIZE;
223 ret = lxc_send_nointr(fd, rsp->data, rsp->datalen, MSG_NOSIGNAL);
6c6497ea
CB
224 if (ret < 0 || ret != (ssize_t)rsp->datalen)
225 return log_warn_errno(-1, errno, "Failed to send command response data %zd", ret);
fe84a562 226
ef6e34ee
DE
227 return 0;
228}
229
c01c2be6 230static int lxc_cmd_send(const char *name, struct lxc_cmd_rr *cmd,
fe84a562 231 const char *lxcpath, const char *hashed_sock_name)
c01c2be6 232{
f62cf1d4 233 __do_close int client_fd = -EBADF;
fe84a562 234 ssize_t ret = -1;
c01c2be6 235
9dfa4041 236 client_fd = lxc_cmd_connect(name, lxcpath, hashed_sock_name, "command");
2a850b2c 237 if (client_fd < 0)
fe84a562 238 return -1;
c01c2be6 239
fe84a562
CB
240 ret = lxc_abstract_unix_send_credential(client_fd, &cmd->req,
241 sizeof(cmd->req));
2a850b2c 242 if (ret < 0 || (size_t)ret != sizeof(cmd->req))
e96f9291 243 return -1;
9044b79e 244
cdb2a47f
CB
245 if (cmd->req.cmd == LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER) {
246 int notify_fd = PTR_TO_INT(cmd->req.data);
247 ret = lxc_abstract_unix_send_fds(client_fd, &notify_fd, 1, NULL, 0);
248 if (ret <= 0)
249 return -1;
250 } else {
251 if (cmd->req.datalen <= 0)
252 return move_fd(client_fd);
c01c2be6 253
cdb2a47f
CB
254 errno = EMSGSIZE;
255 ret = lxc_send_nointr(client_fd, (void *)cmd->req.data,
256 cmd->req.datalen, MSG_NOSIGNAL);
257 if (ret < 0 || ret != (ssize_t)cmd->req.datalen)
258 return -1;
259 }
c01c2be6 260
240fecd0 261 return move_fd(client_fd);
c01c2be6
CB
262}
263
ef6e34ee
DE
264/*
265 * lxc_cmd: Connect to the specified running container, send it a command
266 * request and collect the response
267 *
268 * @name : name of container to connect to
1e8cfdf6 269 * @cmd : command with initialized request to send
ef6e34ee
DE
270 * @stopped : output indicator if the container was not running
271 * @lxcpath : the lxcpath in which the container is running
272 *
273 * Returns the size of the response message on success, < 0 on failure
274 *
275 * Note that there is a special case for LXC_CMD_CONSOLE. For this command
276 * the fd cannot be closed because it is used as a placeholder to indicate
277 * that a particular tty slot is in use. The fd is also used as a signal to
278 * the container that when the caller dies or closes the fd, the container
0115f8fd
DE
279 * will notice the fd on its side of the socket in its mainloop select and
280 * then free the slot with lxc_cmd_fd_cleanup(). The socket fd will be
281 * returned in the cmd response structure.
ef6e34ee
DE
282 */
283static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
88556fd7 284 const char *lxcpath, const char *hashed_sock_name)
724e753c 285{
f62cf1d4 286 __do_close int client_fd = -EBADF;
fe84a562 287 int ret = -1;
dbc9832d
CB
288 bool stay_connected = false;
289
290 if (cmd->req.cmd == LXC_CMD_CONSOLE ||
54446942 291 cmd->req.cmd == LXC_CMD_ADD_STATE_CLIENT)
dbc9832d 292 stay_connected = true;
724e753c 293
0ecf64b5
SH
294 *stopped = 0;
295
c01c2be6
CB
296 client_fd = lxc_cmd_send(name, cmd, lxcpath, hashed_sock_name);
297 if (client_fd < 0) {
00e5ca13 298 if (errno == ECONNREFUSED || errno == EPIPE)
ef6e34ee 299 *stopped = 1;
3f903c04 300
6c6497ea
CB
301 return log_trace_errno(-1, errno, "Command \"%s\" failed to connect command socket",
302 lxc_cmd_str(cmd->req.cmd));
724e753c
MN
303 }
304
c01c2be6 305 ret = lxc_cmd_rsp_recv(client_fd, cmd);
2a850b2c 306 if (ret < 0 && errno == ECONNRESET)
6b7f85cb 307 *stopped = 1;
6a93ae77 308
ea2a070b
CB
309 TRACE("Opened new command socket connection fd %d for command \"%s\"",
310 client_fd, lxc_cmd_str(cmd->req.cmd));
311
c34ff119 312 if (stay_connected && ret > 0)
240fecd0 313 cmd->rsp.ret = move_fd(client_fd);
43eb6f29 314
1362f2eb 315 return ret;
724e753c
MN
316}
317
b494d2dd
SH
318int lxc_try_cmd(const char *name, const char *lxcpath)
319{
0ecf64b5 320 int stopped, ret;
b494d2dd
SH
321 struct lxc_cmd_rr cmd = {
322 .req = { .cmd = LXC_CMD_GET_INIT_PID },
323 };
324
88556fd7 325 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
b494d2dd
SH
326 if (stopped)
327 return 0;
328 if (ret > 0 && cmd.rsp.ret < 0) {
329 errno = cmd.rsp.ret;
330 return -1;
331 }
332 if (ret > 0)
333 return 0;
334
fe84a562
CB
335 /* At this point we weren't denied access, and the container *was*
336 * started. There was some inexplicable error in the protocol. I'm not
337 * clear on whether we should return -1 here, but we didn't receive a
338 * -EACCES, so technically it's not that we're not allowed to control
339 * the container - it's just not behaving.
b494d2dd
SH
340 */
341 return 0;
342}
343
e6bc68d6
WB
344/*
345 * Validate that the input is a proper string parameter. If not,
346 * send an EINVAL response and return -1.
347 *
348 * Precondition: there is non-zero-length data available.
349 */
350static int validate_string_request(int fd, const struct lxc_cmd_req *req)
351{
352 int ret;
353 size_t maxlen = req->datalen - 1;
354 const char *data = req->data;
355
356 if (data[maxlen] == 0 && strnlen(data, maxlen) == maxlen)
357 return 0;
358
359 struct lxc_cmd_rsp rsp = {
360 .ret = -EINVAL,
361 .datalen = 0,
362 .data = NULL,
363 };
364
365 ret = lxc_cmd_rsp_send(fd, &rsp);
366 if (ret < 0)
367 return LXC_CMD_REAP_CLIENT_FD;
368
369 return -1;
370}
371
cc4c0832 372/* Implementations of the commands and their callbacks */
ef6e34ee
DE
373
374/*
375 * lxc_cmd_get_init_pid: Get pid of the container's init process
376 *
377 * @name : name of container to connect to
378 * @lxcpath : the lxcpath in which the container is running
379 *
380 * Returns the pid on success, < 0 on failure
381 */
382pid_t lxc_cmd_get_init_pid(const char *name, const char *lxcpath)
43eb6f29 383{
0ecf64b5 384 int ret, stopped;
565eb353 385 pid_t pid = -1;
ef6e34ee 386 struct lxc_cmd_rr cmd = {
e8cd1208
CB
387 .req = {
388 .cmd = LXC_CMD_GET_INIT_PID
389 },
390 .rsp = {
565eb353 391 .data = PID_TO_PTR(pid)
e8cd1208 392 }
ef6e34ee
DE
393 };
394
88556fd7 395 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ef6e34ee 396 if (ret < 0)
8ed8a626 397 return -1;
ef6e34ee 398
565eb353 399 pid = PTR_TO_PID(cmd.rsp.data);
9234406b
CB
400 if (pid < 0)
401 return -1;
402
403 /* We need to assume that pid_t can actually hold any pid given to us
404 * by the kernel. If it can't it's a libc bug.
405 */
406 return (pid_t)pid;
43eb6f29
DL
407}
408
ef6e34ee 409static int lxc_cmd_get_init_pid_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
410 struct lxc_handler *handler,
411 struct lxc_epoll_descr *descr)
43eb6f29 412{
ea2a070b 413 int ret;
9234406b 414 struct lxc_cmd_rsp rsp = {
565eb353 415 .data = PID_TO_PTR(handler->pid)
9234406b 416 };
ef6e34ee 417
ea2a070b
CB
418 ret = lxc_cmd_rsp_send(fd, &rsp);
419 if (ret < 0)
420 return LXC_CMD_REAP_CLIENT_FD;
421
422 return 0;
43eb6f29
DL
423}
424
746aab51
CB
425int lxc_cmd_get_init_pidfd(const char *name, const char *lxcpath)
426{
427 int ret, stopped;
428 struct lxc_cmd_rr cmd = {
429 .req = {
430 .cmd = LXC_CMD_GET_INIT_PIDFD,
431 },
432 };
433
434 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
435 if (ret < 0)
436 return log_debug_errno(-1, errno, "Failed to process init pidfd command");
437
438 if (cmd.rsp.ret < 0)
439 return log_debug_errno(-EBADF, errno, "Failed to receive init pidfd");
440
441 return PTR_TO_INT(cmd.rsp.data);
442}
443
444static int lxc_cmd_get_init_pidfd_callback(int fd, struct lxc_cmd_req *req,
445 struct lxc_handler *handler,
446 struct lxc_epoll_descr *descr)
447{
448 struct lxc_cmd_rsp rsp = {
449 .ret = 0,
450 };
451 int ret;
452
453 if (handler->pidfd < 0)
454 rsp.ret = -EBADF;
455 ret = lxc_abstract_unix_send_fds(fd, &handler->pidfd, 1, &rsp, sizeof(rsp));
456 if (ret < 0)
457 return log_error(LXC_CMD_REAP_CLIENT_FD, "Failed to send init pidfd");
458
459 return 0;
460}
461
f797f05e
CB
462int lxc_cmd_get_devpts_fd(const char *name, const char *lxcpath)
463{
464 int ret, stopped;
465 struct lxc_cmd_rr cmd = {
466 .req = {
467 .cmd = LXC_CMD_GET_DEVPTS_FD,
468 },
469 };
470
471 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
472 if (ret < 0)
473 return log_debug_errno(-1, errno, "Failed to process devpts fd command");
474
475 if (cmd.rsp.ret < 0)
476 return log_debug_errno(-EBADF, errno, "Failed to receive devpts fd");
477
478 return PTR_TO_INT(cmd.rsp.data);
479}
480
481static int lxc_cmd_get_devpts_fd_callback(int fd, struct lxc_cmd_req *req,
482 struct lxc_handler *handler,
483 struct lxc_epoll_descr *descr)
484{
485 struct lxc_cmd_rsp rsp = {
486 .ret = 0,
487 };
488 int ret;
489
ec0befee 490 if (!handler->conf || handler->conf->devpts_fd < 0) {
f797f05e 491 rsp.ret = -EBADF;
ec0befee
CB
492 ret = lxc_abstract_unix_send_fds(fd, NULL, 0, &rsp, sizeof(rsp));
493 } else {
494 ret = lxc_abstract_unix_send_fds(fd, &handler->conf->devpts_fd, 1, &rsp, sizeof(rsp));
495 }
f797f05e
CB
496 if (ret < 0)
497 return log_error(LXC_CMD_REAP_CLIENT_FD, "Failed to send devpts fd");
498
499 return 0;
500}
501
21405769
CB
502int lxc_cmd_get_seccomp_notify_fd(const char *name, const char *lxcpath)
503{
504#if HAVE_DECL_SECCOMP_NOTIFY_FD
505 int ret, stopped;
506 struct lxc_cmd_rr cmd = {
507 .req = {
508 .cmd = LXC_CMD_GET_SECCOMP_NOTIFY_FD,
509 },
510 };
511
512 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
513 if (ret < 0)
514 return log_debug_errno(-1, errno, "Failed to process seccomp notify fd command");
515
516 if (cmd.rsp.ret < 0)
517 return log_debug_errno(-EBADF, errno, "Failed to receive seccomp notify fd");
518
519 return PTR_TO_INT(cmd.rsp.data);
520#else
521 return ret_errno(EOPNOTSUPP);
522#endif
523}
524
525static int lxc_cmd_get_seccomp_notify_fd_callback(int fd, struct lxc_cmd_req *req,
526 struct lxc_handler *handler,
527 struct lxc_epoll_descr *descr)
528{
529#if HAVE_DECL_SECCOMP_NOTIFY_FD
530 struct lxc_cmd_rsp rsp = {
531 .ret = 0,
532 };
533 int ret;
534
535 if (!handler->conf || handler->conf->seccomp.notifier.notify_fd < 0)
536 rsp.ret = -EBADF;
537 ret = lxc_abstract_unix_send_fds(fd, &handler->conf->seccomp.notifier.notify_fd, 1, &rsp, sizeof(rsp));
538 if (ret < 0)
539 return log_error(LXC_CMD_REAP_CLIENT_FD, "Failed to send seccomp notify fd");
540
541 return 0;
542#else
543 return ret_errno(EOPNOTSUPP);
544#endif
545}
546
ef6e34ee
DE
547/*
548 * lxc_cmd_get_clone_flags: Get clone flags container was spawned with
549 *
550 * @name : name of container to connect to
551 * @lxcpath : the lxcpath in which the container is running
552 *
553 * Returns the clone flags on success, < 0 on failure
554 */
555int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath)
556{
0ecf64b5 557 int ret, stopped;
ef6e34ee 558 struct lxc_cmd_rr cmd = {
6c6497ea
CB
559 .req = {
560 .cmd = LXC_CMD_GET_CLONE_FLAGS,
561 },
ef6e34ee
DE
562 };
563
88556fd7 564 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ef6e34ee
DE
565 if (ret < 0)
566 return ret;
43eb6f29 567
ef6e34ee
DE
568 return PTR_TO_INT(cmd.rsp.data);
569}
570
571static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
572 struct lxc_handler *handler,
573 struct lxc_epoll_descr *descr)
26b2d152 574{
ea2a070b 575 int ret;
6c6497ea
CB
576 struct lxc_cmd_rsp rsp = {
577 .data = INT_TO_PTR(handler->ns_clone_flags),
578 };
ef6e34ee 579
ea2a070b
CB
580 ret = lxc_cmd_rsp_send(fd, &rsp);
581 if (ret < 0)
582 return LXC_CMD_REAP_CLIENT_FD;
583
584 return 0;
ef6e34ee
DE
585}
586
a900cbaf
WB
587static char *lxc_cmd_get_cgroup_path_do(const char *name, const char *lxcpath,
588 const char *subsystem,
589 lxc_cmd_t command)
ef6e34ee 590{
0ecf64b5 591 int ret, stopped;
ef6e34ee 592 struct lxc_cmd_rr cmd = {
b98f7d6e 593 .req = {
a900cbaf 594 .cmd = command,
b98f7d6e 595 .data = subsystem,
c2aed66d 596 .datalen = 0,
b98f7d6e 597 },
26b2d152
MN
598 };
599
c2aed66d
CB
600 cmd.req.data = subsystem;
601 cmd.req.datalen = 0;
602 if (subsystem)
603 cmd.req.datalen = strlen(subsystem) + 1;
604
88556fd7 605 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
fe84a562 606 if (ret < 0)
ef6e34ee
DE
607 return NULL;
608
400d579e
WB
609 if (ret == 0) {
610 if (command == LXC_CMD_GET_LIMITING_CGROUP) {
611 /*
612 * This may indicate that the container was started
613 * under an ealier version before
614 * `cgroup_advanced_isolation` as implemented, there
615 * it sees an unknown command and just closes the
616 * socket, sending us an EOF.
617 */
618 return lxc_cmd_get_cgroup_path_do(name, lxcpath,
619 subsystem,
620 LXC_CMD_GET_CGROUP);
621 }
ef6e34ee 622 return NULL;
400d579e 623 }
ef6e34ee 624
fe84a562 625 if (cmd.rsp.ret < 0 || cmd.rsp.datalen < 0)
ef6e34ee 626 return NULL;
3f903c04 627
ef6e34ee
DE
628 return cmd.rsp.data;
629}
630
a900cbaf
WB
631/*
632 * lxc_cmd_get_cgroup_path: Calculate a container's cgroup path for a
633 * particular subsystem. This is the cgroup path relative to the root
634 * of the cgroup filesystem.
635 *
636 * @name : name of container to connect to
637 * @lxcpath : the lxcpath in which the container is running
638 * @subsystem : the subsystem being asked about
639 *
640 * Returns the path on success, NULL on failure. The caller must free() the
641 * returned path.
642 */
643char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
644 const char *subsystem)
645{
646 return lxc_cmd_get_cgroup_path_do(name, lxcpath, subsystem,
647 LXC_CMD_GET_CGROUP);
648}
649
650/*
651 * lxc_cmd_get_limiting_cgroup_path: Calculate a container's limiting cgroup
652 * path for a particular subsystem. This is the cgroup path relative to the
653 * root of the cgroup filesystem. This may be the same as the path returned by
654 * lxc_cmd_get_cgroup_path if the container doesn't have a limiting path prefix
655 * set.
656 *
657 * @name : name of container to connect to
658 * @lxcpath : the lxcpath in which the container is running
659 * @subsystem : the subsystem being asked about
660 *
661 * Returns the path on success, NULL on failure. The caller must free() the
662 * returned path.
663 */
664char *lxc_cmd_get_limiting_cgroup_path(const char *name, const char *lxcpath,
665 const char *subsystem)
666{
667 return lxc_cmd_get_cgroup_path_do(name, lxcpath, subsystem,
668 LXC_CMD_GET_LIMITING_CGROUP);
669}
670
671static int lxc_cmd_get_cgroup_callback_do(int fd, struct lxc_cmd_req *req,
672 struct lxc_handler *handler,
673 struct lxc_epoll_descr *descr,
674 bool limiting_cgroup)
ef6e34ee 675{
ea2a070b 676 int ret;
4fb3cba5 677 const char *path;
a900cbaf 678 const void *reqdata;
fe84a562 679 struct lxc_cmd_rsp rsp;
2202afc9 680 struct cgroup_ops *cgroup_ops = handler->cgroup_ops;
a900cbaf 681 const char *(*get_fn)(struct cgroup_ops *ops, const char *controller);
b98f7d6e 682
e6bc68d6
WB
683 if (req->datalen > 0) {
684 ret = validate_string_request(fd, req);
685 if (ret != 0)
686 return ret;
a900cbaf 687 reqdata = req->data;
e6bc68d6 688 } else {
a900cbaf 689 reqdata = NULL;
e6bc68d6 690 }
a900cbaf 691
29d652a9
WB
692 get_fn = (limiting_cgroup ? cgroup_ops->get_limiting_cgroup
693 : cgroup_ops->get_cgroup);
a900cbaf
WB
694
695 path = get_fn(cgroup_ops, reqdata);
696
b98f7d6e
SH
697 if (!path)
698 return -1;
fe84a562 699
4f17323e 700 rsp.ret = 0;
fe84a562
CB
701 rsp.datalen = strlen(path) + 1;
702 rsp.data = (char *)path;
ef6e34ee 703
ea2a070b
CB
704 ret = lxc_cmd_rsp_send(fd, &rsp);
705 if (ret < 0)
706 return LXC_CMD_REAP_CLIENT_FD;
707
708 return 0;
ef6e34ee
DE
709}
710
a900cbaf
WB
711static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
712 struct lxc_handler *handler,
713 struct lxc_epoll_descr *descr)
714{
715 return lxc_cmd_get_cgroup_callback_do(fd, req, handler, descr, false);
716}
717
718static int lxc_cmd_get_limiting_cgroup_callback(int fd, struct lxc_cmd_req *req,
719 struct lxc_handler *handler,
720 struct lxc_epoll_descr *descr)
721{
722 return lxc_cmd_get_cgroup_callback_do(fd, req, handler, descr, true);
723}
724
ef6e34ee
DE
725/*
726 * lxc_cmd_get_config_item: Get config item the running container
727 *
728 * @name : name of container to connect to
7fa3f2e9 729 * @item : the configuration item to retrieve (ex: lxc.net.0.veth.pair)
ef6e34ee
DE
730 * @lxcpath : the lxcpath in which the container is running
731 *
732 * Returns the item on success, NULL on failure. The caller must free() the
733 * returned item.
734 */
735char *lxc_cmd_get_config_item(const char *name, const char *item,
736 const char *lxcpath)
737{
0ecf64b5 738 int ret, stopped;
ef6e34ee
DE
739 struct lxc_cmd_rr cmd = {
740 .req = { .cmd = LXC_CMD_GET_CONFIG_ITEM,
741 .data = item,
fe84a562 742 .datalen = strlen(item) + 1,
ef6e34ee
DE
743 },
744 };
745
88556fd7 746 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ef6e34ee
DE
747 if (ret < 0)
748 return NULL;
749
750 if (cmd.rsp.ret == 0)
751 return cmd.rsp.data;
fe84a562 752
ef6e34ee
DE
753 return NULL;
754}
755
756static int lxc_cmd_get_config_item_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
757 struct lxc_handler *handler,
758 struct lxc_epoll_descr *descr)
ef6e34ee 759{
5265a60c 760 __do_free char *cidata = NULL;
ef6e34ee 761 int cilen;
30aec088 762 struct lxc_config_t *item;
fe84a562 763 struct lxc_cmd_rsp rsp;
ef6e34ee
DE
764
765 memset(&rsp, 0, sizeof(rsp));
300df83e 766 item = lxc_get_config(req->data);
30aec088
CB
767 if (!item)
768 goto err1;
fe84a562 769
cccd2219 770 cilen = item->get(req->data, NULL, 0, handler->conf, NULL);
ef6e34ee
DE
771 if (cilen <= 0)
772 goto err1;
773
5265a60c 774 cidata = must_realloc(NULL, cilen + 1);
cccd2219 775 if (item->get(req->data, cidata, cilen + 1, handler->conf, NULL) != cilen)
ef6e34ee 776 goto err1;
fe84a562 777
ef6e34ee
DE
778 cidata[cilen] = '\0';
779 rsp.data = cidata;
780 rsp.datalen = cilen + 1;
781 rsp.ret = 0;
782 goto out;
783
784err1:
785 rsp.ret = -1;
786out:
ea2a070b
CB
787 cilen = lxc_cmd_rsp_send(fd, &rsp);
788 if (cilen < 0)
789 return LXC_CMD_REAP_CLIENT_FD;
790
791 return 0;
ef6e34ee
DE
792}
793
794/*
795 * lxc_cmd_get_state: Get current state of the container
796 *
797 * @name : name of container to connect to
798 * @lxcpath : the lxcpath in which the container is running
799 *
800 * Returns the state on success, < 0 on failure
801 */
dbc9832d 802int lxc_cmd_get_state(const char *name, const char *lxcpath)
ef6e34ee 803{
0ecf64b5 804 int ret, stopped;
ef6e34ee 805 struct lxc_cmd_rr cmd = {
6c6497ea
CB
806 .req = {
807 .cmd = LXC_CMD_GET_STATE,
808 },
ef6e34ee 809 };
26b2d152 810
88556fd7 811 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ebdd307d 812 if (ret < 0 && stopped)
ef6e34ee
DE
813 return STOPPED;
814
815 if (ret < 0)
26b2d152 816 return -1;
26b2d152 817
6c6497ea
CB
818 if (!ret)
819 return log_warn(-1, "Container \"%s\" has stopped before sending its state", name);
fe84a562 820
6c6497ea
CB
821 return log_debug(PTR_TO_INT(cmd.rsp.data),
822 "Container \"%s\" is in \"%s\" state", name,
823 lxc_state2str(PTR_TO_INT(cmd.rsp.data)));
ef6e34ee
DE
824}
825
826static int lxc_cmd_get_state_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
827 struct lxc_handler *handler,
828 struct lxc_epoll_descr *descr)
ef6e34ee 829{
ea2a070b 830 int ret;
6c6497ea
CB
831 struct lxc_cmd_rsp rsp = {
832 .data = INT_TO_PTR(handler->state),
833 };
ef6e34ee 834
ea2a070b
CB
835 ret = lxc_cmd_rsp_send(fd, &rsp);
836 if (ret < 0)
837 return LXC_CMD_REAP_CLIENT_FD;
838
839 return 0;
ef6e34ee
DE
840}
841
842/*
843 * lxc_cmd_stop: Stop the container previously started with lxc_start. All
844 * the processes running inside this container will be killed.
845 *
846 * @name : name of container to connect to
847 * @lxcpath : the lxcpath in which the container is running
848 *
849 * Returns 0 on success, < 0 on failure
850 */
851int lxc_cmd_stop(const char *name, const char *lxcpath)
852{
0ecf64b5 853 int ret, stopped;
ef6e34ee 854 struct lxc_cmd_rr cmd = {
6c6497ea
CB
855 .req = {
856 .cmd = LXC_CMD_STOP,
857 },
ef6e34ee
DE
858 };
859
88556fd7 860 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
26b2d152 861 if (ret < 0) {
6c6497ea
CB
862 if (stopped)
863 return log_info(0, "Container \"%s\" is already stopped", name);
fe84a562 864
26b2d152
MN
865 return -1;
866 }
867
fe84a562
CB
868 /* We do not expect any answer, because we wait for the connection to be
869 * closed.
95d5b147 870 */
6c6497ea
CB
871 if (ret > 0)
872 return log_error_errno(-1, -cmd.rsp.ret, "Failed to stop container \"%s\"", name);
26b2d152 873
6c6497ea 874 return log_info(0, "Container \"%s\" has stopped", name);
26b2d152
MN
875}
876
ef6e34ee 877static int lxc_cmd_stop_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
878 struct lxc_handler *handler,
879 struct lxc_epoll_descr *descr)
d5088cf2 880{
ef6e34ee 881 struct lxc_cmd_rsp rsp;
ef6e34ee 882 int stopsignal = SIGKILL;
2202afc9 883 struct cgroup_ops *cgroup_ops = handler->cgroup_ops;
ea2a070b 884 int ret;
ef6e34ee
DE
885
886 if (handler->conf->stopsignal)
887 stopsignal = handler->conf->stopsignal;
888 memset(&rsp, 0, sizeof(rsp));
9837ee46 889
8ad4fa68 890 if (handler->pidfd >= 0)
9837ee46
CB
891 rsp.ret = lxc_raw_pidfd_send_signal(handler->pidfd, stopsignal, NULL, 0);
892 else
893 rsp.ret = kill(handler->pid, stopsignal);
ef6e34ee 894 if (!rsp.ret) {
9837ee46
CB
895 if (handler->pidfd >= 0)
896 TRACE("Sent signal %d to pidfd %d", stopsignal, handler->pidfd);
897 else
898 TRACE("Sent signal %d to pidfd %d", stopsignal, handler->pid);
899
8db8adea
CB
900 ret = cgroup_ops->unfreeze(cgroup_ops, -1);
901 if (ret)
902 WARN("Failed to unfreeze container \"%s\"", handler->name);
fe84a562 903
8db8adea 904 return 0;
018051e3
CB
905 } else {
906 rsp.ret = -errno;
ef6e34ee
DE
907 }
908
ea2a070b
CB
909 ret = lxc_cmd_rsp_send(fd, &rsp);
910 if (ret < 0)
911 return LXC_CMD_REAP_CLIENT_FD;
912
913 return 0;
ef6e34ee 914}
d5088cf2 915
b5159817 916/*
2bd158cc 917 * lxc_cmd_terminal_winch: noop
b5159817
DE
918 *
919 * @name : name of container to connect to
920 * @lxcpath : the lxcpath in which the container is running
921 *
922 * Returns 0 on success, < 0 on failure
923 */
8ccbbf94 924int lxc_cmd_terminal_winch(const char *name, const char *lxcpath)
b5159817 925{
b5159817
DE
926 return 0;
927}
928
8ccbbf94 929static int lxc_cmd_terminal_winch_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
930 struct lxc_handler *handler,
931 struct lxc_epoll_descr *descr)
b5159817 932{
2bd158cc 933 /* should never be called */
6c6497ea 934 return log_error_errno(-1, ENOSYS, "Called lxc_cmd_terminal_winch_callback()");
b5159817
DE
935}
936
ef6e34ee
DE
937/*
938 * lxc_cmd_console: Open an fd to a tty in the container
939 *
940 * @name : name of container to connect to
941 * @ttynum : in: the tty to open or -1 for next available
942 * : out: the tty allocated
36a94ce8 943 * @fd : out: file descriptor for ptx side of pty
ef6e34ee
DE
944 * @lxcpath : the lxcpath in which the container is running
945 *
0115f8fd 946 * Returns fd holding tty allocated on success, < 0 on failure
ef6e34ee
DE
947 */
948int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
949{
8259d86d 950 __do_free struct lxc_cmd_console_rsp_data *rspdata = NULL;
0ecf64b5 951 int ret, stopped;
ef6e34ee 952 struct lxc_cmd_rr cmd = {
6c6497ea
CB
953 .req = {
954 .cmd = LXC_CMD_CONSOLE,
955 .data = INT_TO_PTR(*ttynum),
956 },
ef6e34ee 957 };
d5088cf2 958
88556fd7 959 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ef6e34ee
DE
960 if (ret < 0)
961 return ret;
0115f8fd 962
8259d86d 963 rspdata = cmd.rsp.data;
6c6497ea
CB
964 if (cmd.rsp.ret < 0)
965 return log_error_errno(-1, -cmd.rsp.ret, "Denied access to tty");
d5088cf2 966
6c6497ea
CB
967 if (ret == 0)
968 return log_error(-1, "tty number %d invalid, busy or all ttys busy", *ttynum);
ef6e34ee 969
36a94ce8 970 if (rspdata->ptxfd < 0)
6c6497ea 971 return log_error(-1, "Unable to allocate fd for tty %d", rspdata->ttynum);
ef6e34ee 972
fe84a562 973 ret = cmd.rsp.ret; /* socket fd */
36a94ce8 974 *fd = rspdata->ptxfd;
ef6e34ee 975 *ttynum = rspdata->ttynum;
fe84a562 976
6c6497ea 977 return log_info(ret, "Alloced fd %d for tty %d via socket %d", *fd, rspdata->ttynum, ret);
ef6e34ee
DE
978}
979
980static int lxc_cmd_console_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
981 struct lxc_handler *handler,
982 struct lxc_epoll_descr *descr)
ef6e34ee 983{
36a94ce8 984 int ptxfd, ret;
ef6e34ee 985 struct lxc_cmd_rsp rsp;
fe84a562 986 int ttynum = PTR_TO_INT(req->data);
ef6e34ee 987
36a94ce8
CB
988 ptxfd = lxc_terminal_allocate(handler->conf, fd, &ttynum);
989 if (ptxfd < 0)
ea2a070b 990 return LXC_CMD_REAP_CLIENT_FD;
ef6e34ee 991
ef6e34ee
DE
992 memset(&rsp, 0, sizeof(rsp));
993 rsp.data = INT_TO_PTR(ttynum);
36a94ce8 994 ret = lxc_abstract_unix_send_fds(fd, &ptxfd, 1, &rsp, sizeof(rsp));
fe84a562 995 if (ret < 0) {
3dfe6f8d 996 lxc_terminal_free(handler->conf, fd);
ea2a070b
CB
997 return log_error_errno(LXC_CMD_REAP_CLIENT_FD, errno,
998 "Failed to send tty to client");
ef6e34ee
DE
999 }
1000
ef6e34ee 1001 return 0;
d5088cf2
CS
1002}
1003
88556fd7
ÇO
1004/*
1005 * lxc_cmd_get_name: Returns the name of the container
1006 *
1007 * @hashed_sock_name: hashed socket name
1008 *
1009 * Returns the name on success, NULL on failure.
1010 */
1011char *lxc_cmd_get_name(const char *hashed_sock_name)
1012{
1013 int ret, stopped;
1014 struct lxc_cmd_rr cmd = {
6c6497ea
CB
1015 .req = {
1016 .cmd = LXC_CMD_GET_NAME,
1017 },
88556fd7
ÇO
1018 };
1019
1020 ret = lxc_cmd(NULL, &cmd, &stopped, NULL, hashed_sock_name);
fe84a562 1021 if (ret < 0)
88556fd7 1022 return NULL;
88556fd7
ÇO
1023
1024 if (cmd.rsp.ret == 0)
1025 return cmd.rsp.data;
fe84a562 1026
88556fd7
ÇO
1027 return NULL;
1028}
1029
1030static int lxc_cmd_get_name_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1031 struct lxc_handler *handler,
1032 struct lxc_epoll_descr *descr)
88556fd7 1033{
ea2a070b 1034 int ret;
88556fd7
ÇO
1035 struct lxc_cmd_rsp rsp;
1036
1037 memset(&rsp, 0, sizeof(rsp));
1038
f0ecc19d 1039 rsp.data = (char *)handler->name;
88556fd7
ÇO
1040 rsp.datalen = strlen(handler->name) + 1;
1041 rsp.ret = 0;
1042
ea2a070b
CB
1043 ret = lxc_cmd_rsp_send(fd, &rsp);
1044 if (ret < 0)
1045 return LXC_CMD_REAP_CLIENT_FD;
1046
1047 return 0;
88556fd7
ÇO
1048}
1049
1050/*
1051 * lxc_cmd_get_lxcpath: Returns the lxcpath of the container
1052 *
1053 * @hashed_sock_name: hashed socket name
1054 *
1055 * Returns the lxcpath on success, NULL on failure.
1056 */
1057char *lxc_cmd_get_lxcpath(const char *hashed_sock_name)
1058{
1059 int ret, stopped;
1060 struct lxc_cmd_rr cmd = {
6c6497ea
CB
1061 .req = {
1062 .cmd = LXC_CMD_GET_LXCPATH,
1063 },
88556fd7 1064 };
724e753c 1065
88556fd7 1066 ret = lxc_cmd(NULL, &cmd, &stopped, NULL, hashed_sock_name);
fe84a562 1067 if (ret < 0)
88556fd7 1068 return NULL;
88556fd7
ÇO
1069
1070 if (cmd.rsp.ret == 0)
1071 return cmd.rsp.data;
fe84a562 1072
88556fd7
ÇO
1073 return NULL;
1074}
1075
1076static int lxc_cmd_get_lxcpath_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1077 struct lxc_handler *handler,
1078 struct lxc_epoll_descr *descr)
88556fd7 1079{
ea2a070b 1080 int ret;
6c6497ea
CB
1081 struct lxc_cmd_rsp rsp = {
1082 .ret = 0,
1083 .data = (char *)handler->lxcpath,
1084 .datalen = strlen(handler->lxcpath) + 1,
1085 };
88556fd7 1086
ea2a070b
CB
1087 ret = lxc_cmd_rsp_send(fd, &rsp);
1088 if (ret < 0)
1089 return LXC_CMD_REAP_CLIENT_FD;
1090
1091 return 0;
88556fd7 1092}
ef6e34ee 1093
54446942 1094int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
92e35018
CB
1095 lxc_state_t states[MAX_STATE],
1096 int *state_client_fd)
dbc9832d 1097{
f62cf1d4 1098 __do_close int clientfd = -EBADF;
bc631984 1099 int state, stopped;
dbc9832d 1100 ssize_t ret;
dbc9832d 1101 struct lxc_cmd_rr cmd = {
6c6497ea
CB
1102 .req = {
1103 .cmd = LXC_CMD_ADD_STATE_CLIENT,
1104 .data = states,
1105 .datalen = (sizeof(lxc_state_t) * MAX_STATE)
1106 },
dbc9832d
CB
1107 };
1108
dbc9832d 1109 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
bc631984
CB
1110 if (states[STOPPED] != 0 && stopped != 0)
1111 return STOPPED;
1112
dbc9832d 1113 if (ret < 0) {
f577e061 1114 if (errno != ECONNREFUSED)
6d1400b5 1115 SYSERROR("Failed to execute command");
1116
dbc9832d
CB
1117 return -1;
1118 }
fe84a562 1119
dbc9832d
CB
1120 /* We should now be guaranteed to get an answer from the state sending
1121 * function.
1122 */
cd889e57 1123 clientfd = cmd.rsp.ret;
6c6497ea
CB
1124 if (clientfd < 0)
1125 return log_error_errno(-1, -clientfd, "Failed to receive socket fd");
dbc9832d 1126
bc631984 1127 state = PTR_TO_INT(cmd.rsp.data);
6c6497ea
CB
1128 if (state < MAX_STATE)
1129 return log_trace(state, "Container is already in requested state %s", lxc_state2str(state));
bc631984 1130
240fecd0 1131 *state_client_fd = move_fd(clientfd);
ea2a070b
CB
1132 TRACE("State connection fd %d ready to listen for container state changes", *state_client_fd);
1133 return MAX_STATE;
dbc9832d
CB
1134}
1135
ebbca852 1136static int lxc_cmd_add_state_client_callback(__owns int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1137 struct lxc_handler *handler,
1138 struct lxc_epoll_descr *descr)
dbc9832d 1139{
44552fb2 1140 int ret;
dbc9832d 1141 struct lxc_cmd_rsp rsp = {0};
dbc9832d 1142
fe84a562 1143 if (req->datalen < 0)
ea2a070b 1144 return LXC_CMD_REAP_CLIENT_FD;
dbc9832d 1145
71fc9c04 1146 if (req->datalen != (sizeof(lxc_state_t) * MAX_STATE))
ea2a070b 1147 return LXC_CMD_REAP_CLIENT_FD;
dbc9832d 1148
fe84a562 1149 if (!req->data)
ea2a070b 1150 return LXC_CMD_REAP_CLIENT_FD;
dbc9832d 1151
c01c2be6 1152 rsp.ret = lxc_add_state_client(fd, handler, (lxc_state_t *)req->data);
44552fb2 1153 if (rsp.ret < 0)
ea2a070b 1154 return LXC_CMD_REAP_CLIENT_FD;
44552fb2 1155
bc631984 1156 rsp.data = INT_TO_PTR(rsp.ret);
dbc9832d 1157
44552fb2
CB
1158 ret = lxc_cmd_rsp_send(fd, &rsp);
1159 if (ret < 0)
ea2a070b 1160 return LXC_CMD_REAP_CLIENT_FD;
44552fb2
CB
1161
1162 return 0;
dbc9832d
CB
1163}
1164
2a63b5cb
CB
1165int lxc_cmd_add_bpf_device_cgroup(const char *name, const char *lxcpath,
1166 struct device_item *device)
1167{
1168#ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX
1169 int stopped = 0;
1170 struct lxc_cmd_rr cmd = {
6c6497ea
CB
1171 .req = {
1172 .cmd = LXC_CMD_ADD_BPF_DEVICE_CGROUP,
1173 .data = device,
1174 .datalen = sizeof(struct device_item),
1175 },
2a63b5cb
CB
1176 };
1177 int ret;
1178
1179 if (strlen(device->access) > STRLITERALLEN("rwm"))
3d0327ed 1180 return log_error_errno(-1, EINVAL, "Invalid access mode specified %s",
2a63b5cb
CB
1181 device->access);
1182
1183 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
1184 if (ret < 0 || cmd.rsp.ret < 0)
3d0327ed 1185 return log_error_errno(-1, errno, "Failed to add new bpf device cgroup rule");
2a63b5cb
CB
1186
1187 return 0;
1188#else
3d0327ed 1189 return ret_set_errno(-1, ENOSYS);
2a63b5cb
CB
1190#endif
1191}
1192
1193static int lxc_cmd_add_bpf_device_cgroup_callback(int fd, struct lxc_cmd_req *req,
1194 struct lxc_handler *handler,
1195 struct lxc_epoll_descr *descr)
1196{
1197#ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX
1198 __do_bpf_program_free struct bpf_program *devices = NULL;
1199 struct lxc_cmd_rsp rsp = {0};
1200 struct lxc_conf *conf = handler->conf;
31b84c7a
CB
1201 struct cgroup_ops *cgroup_ops = handler->cgroup_ops;
1202 struct hierarchy *unified = cgroup_ops->unified;
2a63b5cb
CB
1203 int ret;
1204 struct lxc_list *it;
1205 struct device_item *device;
1206 struct bpf_program *devices_old;
1207
1208 if (req->datalen <= 0)
ea2a070b 1209 return LXC_CMD_REAP_CLIENT_FD;
2a63b5cb
CB
1210
1211 if (req->datalen != sizeof(struct device_item))
ea2a070b 1212 return LXC_CMD_REAP_CLIENT_FD;
2a63b5cb
CB
1213
1214 if (!req->data)
ea2a070b 1215 return LXC_CMD_REAP_CLIENT_FD;
2a63b5cb
CB
1216 device = (struct device_item *)req->data;
1217
1218 rsp.ret = -1;
1219 if (!unified)
1220 goto respond;
1221
1222 ret = bpf_list_add_device(conf, device);
1223 if (ret < 0)
1224 goto respond;
1225
1226 devices = bpf_program_new(BPF_PROG_TYPE_CGROUP_DEVICE);
1227 if (!devices)
1228 goto respond;
1229
1230 ret = bpf_program_init(devices);
1231 if (ret)
1232 goto respond;
1233
1234 lxc_list_for_each(it, &conf->devices) {
1235 struct device_item *cur = it->elem;
1236
1237 ret = bpf_program_append_device(devices, cur);
1238 if (ret)
1239 goto respond;
1240 }
1241
1242 ret = bpf_program_finalize(devices);
1243 if (ret)
1244 goto respond;
1245
1246 ret = bpf_program_cgroup_attach(devices, BPF_CGROUP_DEVICE,
1247 unified->container_full_path,
1248 BPF_F_ALLOW_MULTI);
1249 if (ret)
1250 goto respond;
1251
1252 /* Replace old bpf program. */
31b84c7a
CB
1253 devices_old = move_ptr(cgroup_ops->cgroup2_devices);
1254 cgroup_ops->cgroup2_devices = move_ptr(devices);
2a63b5cb
CB
1255 devices = move_ptr(devices_old);
1256
1257 rsp.ret = 0;
1258
1259respond:
1260 ret = lxc_cmd_rsp_send(fd, &rsp);
1261 if (ret < 0)
ea2a070b 1262 return LXC_CMD_REAP_CLIENT_FD;
2a63b5cb
CB
1263
1264 return 0;
2a63b5cb 1265#else
3d0327ed 1266 return ret_set_errno(-1, ENOSYS);
2a63b5cb
CB
1267#endif
1268}
1269
191d43cc
CB
1270int lxc_cmd_console_log(const char *name, const char *lxcpath,
1271 struct lxc_console_log *log)
1272{
1273 int ret, stopped;
1274 struct lxc_cmd_console_log data;
1275 struct lxc_cmd_rr cmd;
1276
1277 data.clear = log->clear;
1278 data.read = log->read;
1279 data.read_max = *log->read_max;
1280
1281 cmd.req.cmd = LXC_CMD_CONSOLE_LOG;
1282 cmd.req.data = &data;
1283 cmd.req.datalen = sizeof(struct lxc_cmd_console_log);
1284
1285 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
1286 if (ret < 0)
1287 return ret;
1288
1289 /* There is nothing to be read from the buffer. So clear any values we
1290 * where passed to clearly indicate to the user that nothing went wrong.
1291 */
63b74cda 1292 if (cmd.rsp.ret == -ENODATA || cmd.rsp.ret == -EFAULT || cmd.rsp.ret == -ENOENT) {
191d43cc
CB
1293 *log->read_max = 0;
1294 log->data = NULL;
1295 }
1296
1297 /* This is a proper error so don't touch any values we were passed. */
1298 if (cmd.rsp.ret < 0)
1299 return cmd.rsp.ret;
1300
1301 *log->read_max = cmd.rsp.datalen;
1302 log->data = cmd.rsp.data;
1303
1304 return 0;
1305}
1306
1307static int lxc_cmd_console_log_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1308 struct lxc_handler *handler,
1309 struct lxc_epoll_descr *descr)
191d43cc
CB
1310{
1311 struct lxc_cmd_rsp rsp;
28f3b1cd 1312 uint64_t buffer_size = handler->conf->console.buffer_size;
191d43cc
CB
1313 const struct lxc_cmd_console_log *log = req->data;
1314 struct lxc_ringbuf *buf = &handler->conf->console.ringbuf;
1315
1316 rsp.ret = -EFAULT;
1317 rsp.datalen = 0;
1318 rsp.data = NULL;
28f3b1cd 1319 if (buffer_size <= 0)
191d43cc
CB
1320 goto out;
1321
5928191e
CB
1322 if (log->read || log->write_logfile)
1323 rsp.datalen = lxc_ringbuf_used(buf);
1324
191d43cc
CB
1325 if (log->read)
1326 rsp.data = lxc_ringbuf_get_read_addr(buf);
1327
1328 if (log->read_max > 0 && (log->read_max <= rsp.datalen))
1329 rsp.datalen = log->read_max;
1330
1331 /* there's nothing to read */
63b74cda 1332 rsp.ret = -ENODATA;
191d43cc 1333 if (log->read && (buf->r_off == buf->w_off))
63b74cda
CB
1334 goto out;
1335
63b74cda 1336 rsp.ret = 0;
23e0d9af 1337 if (log->clear)
43366ca2 1338 lxc_ringbuf_clear(buf); /* clear the ringbuffer */
23e0d9af 1339 else if (rsp.datalen > 0)
191d43cc
CB
1340 lxc_ringbuf_move_read_addr(buf, rsp.datalen);
1341
1342out:
1343 return lxc_cmd_rsp_send(fd, &rsp);
1344}
1345
974a8aba
CB
1346int lxc_cmd_serve_state_clients(const char *name, const char *lxcpath,
1347 lxc_state_t state)
1348{
1349 int stopped;
1350 ssize_t ret;
1351 struct lxc_cmd_rr cmd = {
6c6497ea
CB
1352 .req = {
1353 .cmd = LXC_CMD_SERVE_STATE_CLIENTS,
1354 .data = INT_TO_PTR(state)
1355 },
974a8aba
CB
1356 };
1357
1358 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
6c6497ea
CB
1359 if (ret < 0)
1360 return log_error_errno(-1, errno, "Failed to serve state clients");
974a8aba
CB
1361
1362 return 0;
1363}
1364
1365static int lxc_cmd_serve_state_clients_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1366 struct lxc_handler *handler,
1367 struct lxc_epoll_descr *descr)
974a8aba
CB
1368{
1369 int ret;
1370 lxc_state_t state = PTR_TO_INT(req->data);
1371 struct lxc_cmd_rsp rsp = {0};
1372
1373 ret = lxc_serve_state_clients(handler->name, handler, state);
1374 if (ret < 0)
ea2a070b 1375 return LXC_CMD_REAP_CLIENT_FD;
974a8aba
CB
1376
1377 ret = lxc_cmd_rsp_send(fd, &rsp);
1378 if (ret < 0)
ea2a070b 1379 return LXC_CMD_REAP_CLIENT_FD;
974a8aba
CB
1380
1381 return 0;
974a8aba
CB
1382}
1383
cdb2a47f
CB
1384int lxc_cmd_seccomp_notify_add_listener(const char *name, const char *lxcpath,
1385 int fd,
1386 /* unused */ unsigned int command,
1387 /* unused */ unsigned int flags)
1388{
1389
c3e3c21a 1390#ifdef HAVE_SECCOMP_NOTIFY
cdb2a47f
CB
1391 int ret, stopped;
1392 struct lxc_cmd_rr cmd = {
1393 .req = {
1394 .cmd = LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER,
1395 .data = INT_TO_PTR(fd),
1396 },
1397 };
1398
1399 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
6c6497ea
CB
1400 if (ret < 0)
1401 return log_error_errno(-1, errno, "Failed to add seccomp listener");
cdb2a47f
CB
1402
1403 return cmd.rsp.ret;
1404#else
3d0327ed 1405 return ret_set_errno(-1, ENOSYS);
cdb2a47f
CB
1406#endif
1407}
1408
1409static int lxc_cmd_seccomp_notify_add_listener_callback(int fd,
1410 struct lxc_cmd_req *req,
1411 struct lxc_handler *handler,
1412 struct lxc_epoll_descr *descr)
1413{
1414 struct lxc_cmd_rsp rsp = {0};
cdb2a47f 1415
c3e3c21a
CB
1416#ifdef HAVE_SECCOMP_NOTIFY
1417 int ret;
f62cf1d4 1418 __do_close int recv_fd = -EBADF;
cdb2a47f 1419
c3e3c21a
CB
1420 ret = lxc_abstract_unix_recv_fds(fd, &recv_fd, 1, NULL, 0);
1421 if (ret <= 0) {
1422 rsp.ret = -errno;
1423 goto out;
cdb2a47f
CB
1424 }
1425
c3e3c21a
CB
1426 if (!handler->conf->seccomp.notifier.wants_supervision ||
1427 handler->conf->seccomp.notifier.proxy_fd < 0) {
1428 SYSERROR("No seccomp proxy fd specified");
1429 rsp.ret = -EINVAL;
1430 goto out;
1431 }
cdb2a47f 1432
c3e3c21a 1433 ret = lxc_mainloop_add_handler(descr, recv_fd, seccomp_notify_handler,
cdb2a47f 1434 handler);
c3e3c21a
CB
1435 if (ret < 0) {
1436 rsp.ret = -errno;
1437 goto out;
1438 }
68a9e3eb 1439 move_fd(recv_fd);
cdb2a47f 1440
c3e3c21a 1441out:
cdb2a47f
CB
1442#else
1443 rsp.ret = -ENOSYS;
cdb2a47f 1444
c3e3c21a
CB
1445#endif
1446 return lxc_cmd_rsp_send(fd, &rsp);
cdb2a47f
CB
1447}
1448
018051e3
CB
1449int lxc_cmd_freeze(const char *name, const char *lxcpath, int timeout)
1450{
1451 int ret, stopped;
1452 struct lxc_cmd_rr cmd = {
1453 .req = {
1454 .cmd = LXC_CMD_FREEZE,
1455 .data = INT_TO_PTR(timeout),
1456 },
1457 };
1458
1459 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
1460 if (ret <= 0 || cmd.rsp.ret < 0)
3d0327ed 1461 return log_error_errno(-1, errno, "Failed to freeze container");
018051e3
CB
1462
1463 return cmd.rsp.ret;
1464}
1465
1466static int lxc_cmd_freeze_callback(int fd, struct lxc_cmd_req *req,
1467 struct lxc_handler *handler,
1468 struct lxc_epoll_descr *descr)
1469{
1470 int timeout = PTR_TO_INT(req->data);
1471 struct lxc_cmd_rsp rsp = {
6c6497ea 1472 .ret = -ENOENT,
018051e3
CB
1473 };
1474 struct cgroup_ops *ops = handler->cgroup_ops;
1475
1973b62a 1476 if (pure_unified_layout(ops))
018051e3
CB
1477 rsp.ret = ops->freeze(ops, timeout);
1478
1479 return lxc_cmd_rsp_send(fd, &rsp);
1480}
1481
1482int lxc_cmd_unfreeze(const char *name, const char *lxcpath, int timeout)
1483{
1484 int ret, stopped;
1485 struct lxc_cmd_rr cmd = {
1486 .req = {
1487 .cmd = LXC_CMD_UNFREEZE,
1488 .data = INT_TO_PTR(timeout),
1489 },
1490 };
1491
1492 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
1493 if (ret <= 0 || cmd.rsp.ret < 0)
3d0327ed 1494 return log_error_errno(-1, errno, "Failed to unfreeze container");
018051e3
CB
1495
1496 return cmd.rsp.ret;
1497}
1498
1499static int lxc_cmd_unfreeze_callback(int fd, struct lxc_cmd_req *req,
1500 struct lxc_handler *handler,
1501 struct lxc_epoll_descr *descr)
1502{
1503 int timeout = PTR_TO_INT(req->data);
1504 struct lxc_cmd_rsp rsp = {
6c6497ea 1505 .ret = -ENOENT,
018051e3
CB
1506 };
1507 struct cgroup_ops *ops = handler->cgroup_ops;
1508
1973b62a 1509 if (pure_unified_layout(ops))
018051e3
CB
1510 rsp.ret = ops->unfreeze(ops, timeout);
1511
1512 return lxc_cmd_rsp_send(fd, &rsp);
1513}
1514
bad788b0
CB
1515int lxc_cmd_get_cgroup2_fd(const char *name, const char *lxcpath)
1516{
1517 int ret, stopped;
1518 struct lxc_cmd_rr cmd = {
1519 .req = {
1520 .cmd = LXC_CMD_GET_CGROUP2_FD,
1521 },
1522 };
1523
1524 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
23a917e5
CB
1525 if (ret < 0)
1526 return -1;
1527
1528 if (cmd.rsp.ret < 0)
a5263e59 1529 return log_debug_errno(cmd.rsp.ret, -cmd.rsp.ret, "Failed to receive cgroup2 fd");
bad788b0
CB
1530
1531 return PTR_TO_INT(cmd.rsp.data);
1532}
1533
a900cbaf
WB
1534static int lxc_cmd_get_cgroup2_fd_callback_do(int fd, struct lxc_cmd_req *req,
1535 struct lxc_handler *handler,
1536 struct lxc_epoll_descr *descr,
1537 bool limiting_cgroup)
bad788b0
CB
1538{
1539 struct lxc_cmd_rsp rsp = {
1540 .ret = -EINVAL,
1541 };
1542 struct cgroup_ops *ops = handler->cgroup_ops;
a900cbaf 1543 int ret, send_fd;
bad788b0 1544
1973b62a 1545 if (!pure_unified_layout(ops) || !ops->unified)
bad788b0
CB
1546 return lxc_cmd_rsp_send(fd, &rsp);
1547
a900cbaf
WB
1548 send_fd = limiting_cgroup ? ops->unified->cgfd_limit
1549 : ops->unified->cgfd_con;
1550
bad788b0 1551 rsp.ret = 0;
a900cbaf 1552 ret = lxc_abstract_unix_send_fds(fd, &send_fd, 1, &rsp, sizeof(rsp));
bad788b0 1553 if (ret < 0)
a804c19b 1554 return log_error(LXC_CMD_REAP_CLIENT_FD, "Failed to send cgroup2 fd");
bad788b0
CB
1555
1556 return 0;
1557}
1558
a900cbaf
WB
1559static int lxc_cmd_get_cgroup2_fd_callback(int fd, struct lxc_cmd_req *req,
1560 struct lxc_handler *handler,
1561 struct lxc_epoll_descr *descr)
1562{
1563 return lxc_cmd_get_cgroup2_fd_callback_do(fd, req, handler, descr,
1564 false);
1565}
1566
1567static int lxc_cmd_get_limiting_cgroup2_fd_callback(int fd,
1568 struct lxc_cmd_req *req,
1569 struct lxc_handler *handler,
1570 struct lxc_epoll_descr *descr)
1571{
1572 return lxc_cmd_get_cgroup2_fd_callback_do(fd, req, handler, descr,
1573 true);
1574}
1575
ef6e34ee 1576static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1577 struct lxc_handler *handler,
1578 struct lxc_epoll_descr *descr)
724e753c 1579{
cdb2a47f
CB
1580 typedef int (*callback)(int, struct lxc_cmd_req *, struct lxc_handler *,
1581 struct lxc_epoll_descr *);
ef6e34ee
DE
1582
1583 callback cb[LXC_CMD_MAX] = {
2a63b5cb
CB
1584 [LXC_CMD_CONSOLE] = lxc_cmd_console_callback,
1585 [LXC_CMD_TERMINAL_WINCH] = lxc_cmd_terminal_winch_callback,
1586 [LXC_CMD_STOP] = lxc_cmd_stop_callback,
1587 [LXC_CMD_GET_STATE] = lxc_cmd_get_state_callback,
1588 [LXC_CMD_GET_INIT_PID] = lxc_cmd_get_init_pid_callback,
1589 [LXC_CMD_GET_CLONE_FLAGS] = lxc_cmd_get_clone_flags_callback,
1590 [LXC_CMD_GET_CGROUP] = lxc_cmd_get_cgroup_callback,
1591 [LXC_CMD_GET_CONFIG_ITEM] = lxc_cmd_get_config_item_callback,
1592 [LXC_CMD_GET_NAME] = lxc_cmd_get_name_callback,
1593 [LXC_CMD_GET_LXCPATH] = lxc_cmd_get_lxcpath_callback,
1594 [LXC_CMD_ADD_STATE_CLIENT] = lxc_cmd_add_state_client_callback,
1595 [LXC_CMD_CONSOLE_LOG] = lxc_cmd_console_log_callback,
1596 [LXC_CMD_SERVE_STATE_CLIENTS] = lxc_cmd_serve_state_clients_callback,
1597 [LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER] = lxc_cmd_seccomp_notify_add_listener_callback,
1598 [LXC_CMD_ADD_BPF_DEVICE_CGROUP] = lxc_cmd_add_bpf_device_cgroup_callback,
018051e3
CB
1599 [LXC_CMD_FREEZE] = lxc_cmd_freeze_callback,
1600 [LXC_CMD_UNFREEZE] = lxc_cmd_unfreeze_callback,
bad788b0 1601 [LXC_CMD_GET_CGROUP2_FD] = lxc_cmd_get_cgroup2_fd_callback,
746aab51 1602 [LXC_CMD_GET_INIT_PIDFD] = lxc_cmd_get_init_pidfd_callback,
a900cbaf
WB
1603 [LXC_CMD_GET_LIMITING_CGROUP] = lxc_cmd_get_limiting_cgroup_callback,
1604 [LXC_CMD_GET_LIMITING_CGROUP2_FD] = lxc_cmd_get_limiting_cgroup2_fd_callback,
f797f05e 1605 [LXC_CMD_GET_DEVPTS_FD] = lxc_cmd_get_devpts_fd_callback,
21405769 1606 [LXC_CMD_GET_SECCOMP_NOTIFY_FD] = lxc_cmd_get_seccomp_notify_fd_callback,
724e753c
MN
1607 };
1608
23a917e5 1609 if (req->cmd >= LXC_CMD_MAX)
769b88ea 1610 return log_trace_errno(-1, EINVAL, "Invalid command id %d", req->cmd);
23a917e5 1611
cdb2a47f 1612 return cb[req->cmd](fd, req, handler, descr);
724e753c
MN
1613}
1614
ef6e34ee 1615static void lxc_cmd_fd_cleanup(int fd, struct lxc_handler *handler,
cdb2a47f 1616 struct lxc_epoll_descr *descr, const lxc_cmd_t cmd)
724e753c 1617{
3dfe6f8d 1618 lxc_terminal_free(handler->conf, fd);
724e753c 1619 lxc_mainloop_del_handler(descr, fd);
f6fc1565 1620
cd5369b0 1621 if (cmd == LXC_CMD_ADD_STATE_CLIENT) {
ab92468c
CB
1622 struct lxc_list *cur, *next;
1623
cdb2a47f
CB
1624 lxc_list_for_each_safe(cur, &handler->conf->state_clients, next) {
1625 struct lxc_state_client *client = cur->elem;
1626
1627 if (client->clientfd != fd)
1628 continue;
1629
ab92468c
CB
1630 /*
1631 * Only kick client from list so it can't be found
1632 * anymore. The actual close happens, as for all other
1633 * file descriptors, below.
1634 */
cdb2a47f 1635 lxc_list_del(cur);
cdb2a47f
CB
1636 free(cur->elem);
1637 free(cur);
ab92468c 1638
39e2a438
CB
1639 /*
1640 * No need to walk the whole list. If we found the state
cdb2a47f
CB
1641 * client fd there can't be a second one.
1642 */
ea2a070b 1643 TRACE("Found state client fd %d in state client list for command \"%s\"", fd, lxc_cmd_str(cmd));
ab92468c 1644 break;
cdb2a47f 1645 }
39e2a438
CB
1646
1647 /*
1648 * We didn't add the state client to the list. Either because
1649 * we failed to allocate memory (unlikely) or because the state
1650 * was already reached by the time we were ready to add it. So
1651 * fallthrough and clean it up.
1652 */
ea2a070b 1653 TRACE("Closing state client fd %d for command \"%s\"", fd, lxc_cmd_str(cmd));
f6fc1565 1654 }
cd5369b0 1655
ea2a070b 1656 TRACE("Closing client fd %d for command \"%s\"", fd, lxc_cmd_str(cmd));
cd5369b0 1657 close(fd);
724e753c
MN
1658}
1659
84c92abd
DE
1660static int lxc_cmd_handler(int fd, uint32_t events, void *data,
1661 struct lxc_epoll_descr *descr)
724e753c 1662{
5265a60c 1663 __do_free void *reqdata = NULL;
724e753c 1664 int ret;
ef6e34ee 1665 struct lxc_cmd_req req;
724e753c
MN
1666 struct lxc_handler *handler = data;
1667
aae93dd3 1668 ret = lxc_abstract_unix_rcv_credential(fd, &req, sizeof(req));
ded1d23f 1669 if (ret < 0) {
ea2a070b 1670 SYSERROR("Failed to receive data on command socket for command \"%s\"", lxc_cmd_str(req.cmd));
9044b79e 1671
1672 if (errno == EACCES) {
1673 /* We don't care for the peer, just send and close. */
ea2a070b 1674 struct lxc_cmd_rsp rsp = {
f7a97743 1675 .ret = -EPERM,
ea2a070b 1676 };
9044b79e 1677
1678 lxc_cmd_rsp_send(fd, &rsp);
1679 }
1680
724e753c
MN
1681 goto out_close;
1682 }
1683
fe84a562 1684 if (ret == 0)
724e753c 1685 goto out_close;
724e753c 1686
ef6e34ee 1687 if (ret != sizeof(req)) {
ea2a070b 1688 WARN("Failed to receive full command request. Ignoring request for \"%s\"", lxc_cmd_str(req.cmd));
ef6e34ee
DE
1689 goto out_close;
1690 }
1691
ea2a070b
CB
1692 if ((req.datalen > LXC_CMD_DATA_MAX) && (req.cmd != LXC_CMD_CONSOLE_LOG)) {
1693 ERROR("Received command data length %d is too large for command \"%s\"", req.datalen, lxc_cmd_str(req.cmd));
724e753c
MN
1694 goto out_close;
1695 }
1696
ef6e34ee 1697 if (req.datalen > 0) {
5265a60c 1698 reqdata = must_realloc(NULL, req.datalen);
e3233f26 1699 ret = lxc_recv_nointr(fd, reqdata, req.datalen, 0);
ef6e34ee 1700 if (ret != req.datalen) {
ea2a070b 1701 WARN("Failed to receive full command request. Ignoring request for \"%s\"", lxc_cmd_str(req.cmd));
ef6e34ee
DE
1702 goto out_close;
1703 }
fe84a562 1704
ef6e34ee
DE
1705 req.data = reqdata;
1706 }
1707
cdb2a47f 1708 ret = lxc_cmd_process(fd, &req, handler, descr);
724e753c 1709 if (ret) {
fe84a562 1710 /* This is not an error, but only a request to close fd. */
724e753c
MN
1711 goto out_close;
1712 }
1713
1714out:
f7a97743 1715 return LXC_MAINLOOP_CONTINUE;
fe84a562 1716
724e753c 1717out_close:
f6fc1565 1718 lxc_cmd_fd_cleanup(fd, handler, descr, req.cmd);
724e753c
MN
1719 goto out;
1720}
1721
84c92abd
DE
1722static int lxc_cmd_accept(int fd, uint32_t events, void *data,
1723 struct lxc_epoll_descr *descr)
724e753c 1724{
f62cf1d4 1725 __do_close int connection = -EBADF;
fe84a562 1726 int opt = 1, ret = -1;
724e753c
MN
1727
1728 connection = accept(fd, NULL, 0);
6c6497ea
CB
1729 if (connection < 0)
1730 return log_error_errno(LXC_MAINLOOP_ERROR, errno, "Failed to accept connection to run command");
724e753c 1731
fe84a562 1732 ret = fcntl(connection, F_SETFD, FD_CLOEXEC);
6c6497ea
CB
1733 if (ret < 0)
1734 return log_error_errno(ret, errno, "Failed to set close-on-exec on incoming command connection");
9ccb2dbc 1735
fe84a562 1736 ret = setsockopt(connection, SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt));
6c6497ea
CB
1737 if (ret < 0)
1738 return log_error_errno(ret, errno, "Failed to enable necessary credentials on command socket");
724e753c 1739
ef6e34ee 1740 ret = lxc_mainloop_add_handler(descr, connection, lxc_cmd_handler, data);
6c6497ea
CB
1741 if (ret)
1742 return log_error(ret, "Failed to add command handler");
724e753c 1743
ea2a070b 1744 TRACE("Accepted new client as fd %d on command server fd %d", connection, fd);
240fecd0 1745 move_fd(connection);
724e753c 1746 return ret;
724e753c
MN
1747}
1748
9dfa4041 1749int lxc_cmd_init(const char *name, const char *lxcpath, const char *suffix)
724e753c 1750{
f62cf1d4 1751 __do_close int fd = -EBADF;
c13e7111 1752 int ret;
b1234129 1753 char path[LXC_AUDS_ADDR_LEN] = {0};
724e753c 1754
5b46db1a 1755 ret = lxc_make_abstract_socket_name(path, sizeof(path), name, lxcpath, NULL, suffix);
fe84a562 1756 if (ret < 0)
9ba8130c 1757 return -1;
724e753c 1758
aae93dd3 1759 fd = lxc_abstract_unix_open(path, SOCK_STREAM, 0);
724e753c 1760 if (fd < 0) {
08aa08fe 1761 if (errno == EADDRINUSE)
fe84a562 1762 ERROR("Container \"%s\" appears to be already running", name);
6d1400b5 1763
6c6497ea 1764 return log_error_errno(-1, errno, "Failed to create command socket %s", &path[1]);
724e753c
MN
1765 }
1766
fe84a562 1767 ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
6c6497ea
CB
1768 if (ret < 0)
1769 return log_error_errno(-1, errno, "Failed to set FD_CLOEXEC on command socket file descriptor");
91480a0f 1770
6c6497ea 1771 return log_trace(move_fd(fd), "Created abstract unix socket \"%s\"", &path[1]);
d2e30e99
DE
1772}
1773
fe84a562 1774int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr,
ef6e34ee 1775 struct lxc_handler *handler)
d2e30e99 1776{
fe84a562 1777 int ret;
d2e30e99 1778
ea2a070b 1779 ret = lxc_mainloop_add_handler(descr, handler->conf->maincmd_fd, lxc_cmd_accept, handler);
6c6497ea 1780 if (ret < 0)
ea2a070b 1781 return log_error(ret, "Failed to add handler for command socket fd %d", handler->conf->maincmd_fd);
724e753c
MN
1782
1783 return ret;
1784}