]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/commands.c
share_ns: improve error handling
[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",
ef6e34ee 86 };
724e753c 87
f371aca9 88 if (cmd >= LXC_CMD_MAX)
a8007512 89 return "Invalid request";
fe84a562 90
ef6e34ee
DE
91 return cmdname[cmd];
92}
93
94/*
95 * lxc_cmd_rsp_recv: Receive a response to a command
96 *
97 * @sock : the socket connected to the container
98 * @cmd : command to put response in
99 *
100 * Returns the size of the response message or < 0 on failure
101 *
102 * Note that if the command response datalen > 0, then data is
103 * a malloc()ed buffer and should be free()ed by the caller. If
104 * the response data is <= a void * worth of data, it will be
105 * stored directly in data and datalen will be 0.
106 *
107 * As a special case, the response for LXC_CMD_CONSOLE is created
0115f8fd
DE
108 * here as it contains an fd for the master pty passed through the
109 * unix socket.
ef6e34ee
DE
110 */
111static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
112{
23a917e5
CB
113 __do_close_prot_errno int fd_rsp = -EBADF;
114 int ret;
ef6e34ee
DE
115 struct lxc_cmd_rsp *rsp = &cmd->rsp;
116
23a917e5
CB
117 ret = lxc_abstract_unix_recv_fds(sock, &fd_rsp, 1, rsp, sizeof(*rsp));
118 if (ret < 0)
119 return log_warn_errno(-1,
120 errno, "Failed to receive response for command \"%s\"",
121 lxc_cmd_str(cmd->req.cmd));
fe84a562 122 TRACE("Command \"%s\" received response", lxc_cmd_str(cmd->req.cmd));
ef6e34ee
DE
123
124 if (cmd->req.cmd == LXC_CMD_CONSOLE) {
125 struct lxc_cmd_console_rsp_data *rspdata;
126
0115f8fd
DE
127 /* recv() returns 0 bytes when a tty cannot be allocated,
128 * rsp->ret is < 0 when the peer permission check failed
129 */
130 if (ret == 0 || rsp->ret < 0)
131 return 0;
132
ef6e34ee 133 rspdata = malloc(sizeof(*rspdata));
23a917e5
CB
134 if (!rspdata)
135 return log_warn_errno(-1,
136 ENOMEM, "Failed to receive response for command \"%s\"",
137 lxc_cmd_str(cmd->req.cmd));
2a850b2c 138
23a917e5 139 rspdata->masterfd = move_fd(fd_rsp);
ef6e34ee
DE
140 rspdata->ttynum = PTR_TO_INT(rsp->data);
141 rsp->data = rspdata;
142 }
143
23a917e5
CB
144 if (cmd->req.cmd == LXC_CMD_GET_CGROUP2_FD) {
145 int cgroup2_fd = move_fd(fd_rsp);
146 rsp->data = INT_TO_PTR(cgroup2_fd);
860e7c43 147 }
fe84a562 148
23a917e5
CB
149 if (rsp->datalen == 0)
150 return log_debug(ret,
151 "Response data length for command \"%s\" is 0",
152 lxc_cmd_str(cmd->req.cmd));
153
191d43cc 154 if ((rsp->datalen > LXC_CMD_DATA_MAX) &&
23a917e5
CB
155 (cmd->req.cmd != LXC_CMD_CONSOLE_LOG))
156 return log_error(-1, "Response data for command \"%s\" is too long: %d bytes > %d",
157 lxc_cmd_str(cmd->req.cmd), rsp->datalen,
158 LXC_CMD_DATA_MAX);
ef6e34ee 159
191d43cc
CB
160 if (cmd->req.cmd == LXC_CMD_CONSOLE_LOG) {
161 rsp->data = malloc(rsp->datalen + 1);
162 ((char *)rsp->data)[rsp->datalen] = '\0';
163 } else {
164 rsp->data = malloc(rsp->datalen);
165 }
23a917e5
CB
166 if (!rsp->data)
167 return log_error_errno(-1,
168 ENOMEM, "Failed to allocate response buffer for command \"%s\"",
169 lxc_cmd_str(cmd->req.cmd));
fe84a562 170
2a850b2c 171 ret = lxc_recv_nointr(sock, rsp->data, rsp->datalen, 0);
23a917e5
CB
172 if (ret != rsp->datalen)
173 return log_error_errno(-1,
174 errno, "Failed to receive response data for command \"%s\"",
175 lxc_cmd_str(cmd->req.cmd));
724e753c
MN
176
177 return ret;
178}
179
ef6e34ee
DE
180/*
181 * lxc_cmd_rsp_send: Send a command response
182 *
183 * @fd : file descriptor of socket to send response on
184 * @rsp : response to send
185 *
186 * Returns 0 on success, < 0 on failure
187 */
188static int lxc_cmd_rsp_send(int fd, struct lxc_cmd_rsp *rsp)
189{
fe84a562 190 ssize_t ret;
ef6e34ee 191
7fbb15ec
CB
192 errno = EMSGSIZE;
193 ret = lxc_send_nointr(fd, rsp, sizeof(*rsp), MSG_NOSIGNAL);
6c6497ea
CB
194 if (ret < 0 || (size_t)ret != sizeof(*rsp))
195 return log_error_errno(-1, errno, "Failed to send command response %zd", ret);
ef6e34ee 196
a674dfe1 197 if (!rsp->data || rsp->datalen <= 0)
fe84a562
CB
198 return 0;
199
7fbb15ec
CB
200 errno = EMSGSIZE;
201 ret = lxc_send_nointr(fd, rsp->data, rsp->datalen, MSG_NOSIGNAL);
6c6497ea
CB
202 if (ret < 0 || ret != (ssize_t)rsp->datalen)
203 return log_warn_errno(-1, errno, "Failed to send command response data %zd", ret);
fe84a562 204
ef6e34ee
DE
205 return 0;
206}
207
c01c2be6 208static int lxc_cmd_send(const char *name, struct lxc_cmd_rr *cmd,
fe84a562 209 const char *lxcpath, const char *hashed_sock_name)
c01c2be6 210{
e96f9291 211 __do_close_prot_errno int client_fd = -EBADF;
fe84a562 212 ssize_t ret = -1;
c01c2be6 213
9dfa4041 214 client_fd = lxc_cmd_connect(name, lxcpath, hashed_sock_name, "command");
2a850b2c 215 if (client_fd < 0)
fe84a562 216 return -1;
c01c2be6 217
fe84a562
CB
218 ret = lxc_abstract_unix_send_credential(client_fd, &cmd->req,
219 sizeof(cmd->req));
2a850b2c 220 if (ret < 0 || (size_t)ret != sizeof(cmd->req))
e96f9291 221 return -1;
9044b79e 222
cdb2a47f
CB
223 if (cmd->req.cmd == LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER) {
224 int notify_fd = PTR_TO_INT(cmd->req.data);
225 ret = lxc_abstract_unix_send_fds(client_fd, &notify_fd, 1, NULL, 0);
226 if (ret <= 0)
227 return -1;
228 } else {
229 if (cmd->req.datalen <= 0)
230 return move_fd(client_fd);
c01c2be6 231
cdb2a47f
CB
232 errno = EMSGSIZE;
233 ret = lxc_send_nointr(client_fd, (void *)cmd->req.data,
234 cmd->req.datalen, MSG_NOSIGNAL);
235 if (ret < 0 || ret != (ssize_t)cmd->req.datalen)
236 return -1;
237 }
c01c2be6 238
240fecd0 239 return move_fd(client_fd);
c01c2be6
CB
240}
241
ef6e34ee
DE
242/*
243 * lxc_cmd: Connect to the specified running container, send it a command
244 * request and collect the response
245 *
246 * @name : name of container to connect to
1e8cfdf6 247 * @cmd : command with initialized request to send
ef6e34ee
DE
248 * @stopped : output indicator if the container was not running
249 * @lxcpath : the lxcpath in which the container is running
250 *
251 * Returns the size of the response message on success, < 0 on failure
252 *
253 * Note that there is a special case for LXC_CMD_CONSOLE. For this command
254 * the fd cannot be closed because it is used as a placeholder to indicate
255 * that a particular tty slot is in use. The fd is also used as a signal to
256 * the container that when the caller dies or closes the fd, the container
0115f8fd
DE
257 * will notice the fd on its side of the socket in its mainloop select and
258 * then free the slot with lxc_cmd_fd_cleanup(). The socket fd will be
259 * returned in the cmd response structure.
ef6e34ee
DE
260 */
261static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
88556fd7 262 const char *lxcpath, const char *hashed_sock_name)
724e753c 263{
c34ff119 264 __do_close_prot_errno int client_fd = -EBADF;
fe84a562 265 int ret = -1;
dbc9832d
CB
266 bool stay_connected = false;
267
268 if (cmd->req.cmd == LXC_CMD_CONSOLE ||
54446942 269 cmd->req.cmd == LXC_CMD_ADD_STATE_CLIENT)
dbc9832d 270 stay_connected = true;
724e753c 271
0ecf64b5
SH
272 *stopped = 0;
273
c01c2be6
CB
274 client_fd = lxc_cmd_send(name, cmd, lxcpath, hashed_sock_name);
275 if (client_fd < 0) {
00e5ca13 276 if (errno == ECONNREFUSED || errno == EPIPE)
ef6e34ee 277 *stopped = 1;
3f903c04 278
6c6497ea
CB
279 return log_trace_errno(-1, errno, "Command \"%s\" failed to connect command socket",
280 lxc_cmd_str(cmd->req.cmd));
724e753c
MN
281 }
282
c01c2be6 283 ret = lxc_cmd_rsp_recv(client_fd, cmd);
2a850b2c 284 if (ret < 0 && errno == ECONNRESET)
6b7f85cb 285 *stopped = 1;
6a93ae77 286
c34ff119 287 if (stay_connected && ret > 0)
240fecd0 288 cmd->rsp.ret = move_fd(client_fd);
43eb6f29 289
1362f2eb 290 return ret;
724e753c
MN
291}
292
b494d2dd
SH
293int lxc_try_cmd(const char *name, const char *lxcpath)
294{
0ecf64b5 295 int stopped, ret;
b494d2dd
SH
296 struct lxc_cmd_rr cmd = {
297 .req = { .cmd = LXC_CMD_GET_INIT_PID },
298 };
299
88556fd7 300 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
b494d2dd
SH
301 if (stopped)
302 return 0;
303 if (ret > 0 && cmd.rsp.ret < 0) {
304 errno = cmd.rsp.ret;
305 return -1;
306 }
307 if (ret > 0)
308 return 0;
309
fe84a562
CB
310 /* At this point we weren't denied access, and the container *was*
311 * started. There was some inexplicable error in the protocol. I'm not
312 * clear on whether we should return -1 here, but we didn't receive a
313 * -EACCES, so technically it's not that we're not allowed to control
314 * the container - it's just not behaving.
b494d2dd
SH
315 */
316 return 0;
317}
318
cc4c0832 319/* Implementations of the commands and their callbacks */
ef6e34ee
DE
320
321/*
322 * lxc_cmd_get_init_pid: Get pid of the container's init process
323 *
324 * @name : name of container to connect to
325 * @lxcpath : the lxcpath in which the container is running
326 *
327 * Returns the pid on success, < 0 on failure
328 */
329pid_t lxc_cmd_get_init_pid(const char *name, const char *lxcpath)
43eb6f29 330{
0ecf64b5 331 int ret, stopped;
6c6497ea 332 intmax_t pid = -1;
ef6e34ee 333 struct lxc_cmd_rr cmd = {
e8cd1208
CB
334 .req = {
335 .cmd = LXC_CMD_GET_INIT_PID
336 },
337 .rsp = {
6c6497ea 338 .data = INTMAX_TO_PTR(pid)
e8cd1208 339 }
ef6e34ee
DE
340 };
341
88556fd7 342 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ef6e34ee 343 if (ret < 0)
8ed8a626 344 return -1;
ef6e34ee 345
9234406b
CB
346 pid = PTR_TO_INTMAX(cmd.rsp.data);
347 if (pid < 0)
348 return -1;
349
350 /* We need to assume that pid_t can actually hold any pid given to us
351 * by the kernel. If it can't it's a libc bug.
352 */
353 return (pid_t)pid;
43eb6f29
DL
354}
355
ef6e34ee 356static int lxc_cmd_get_init_pid_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
357 struct lxc_handler *handler,
358 struct lxc_epoll_descr *descr)
43eb6f29 359{
54dcfd81
CB
360 intmax_t pid = handler->pid;
361
9234406b 362 struct lxc_cmd_rsp rsp = {
54dcfd81 363 .data = INTMAX_TO_PTR(pid)
9234406b 364 };
ef6e34ee
DE
365
366 return lxc_cmd_rsp_send(fd, &rsp);
43eb6f29
DL
367}
368
ef6e34ee
DE
369/*
370 * lxc_cmd_get_clone_flags: Get clone flags container was spawned with
371 *
372 * @name : name of container to connect to
373 * @lxcpath : the lxcpath in which the container is running
374 *
375 * Returns the clone flags on success, < 0 on failure
376 */
377int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath)
378{
0ecf64b5 379 int ret, stopped;
ef6e34ee 380 struct lxc_cmd_rr cmd = {
6c6497ea
CB
381 .req = {
382 .cmd = LXC_CMD_GET_CLONE_FLAGS,
383 },
ef6e34ee
DE
384 };
385
88556fd7 386 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ef6e34ee
DE
387 if (ret < 0)
388 return ret;
43eb6f29 389
ef6e34ee
DE
390 return PTR_TO_INT(cmd.rsp.data);
391}
392
393static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
394 struct lxc_handler *handler,
395 struct lxc_epoll_descr *descr)
26b2d152 396{
6c6497ea
CB
397 struct lxc_cmd_rsp rsp = {
398 .data = INT_TO_PTR(handler->ns_clone_flags),
399 };
ef6e34ee
DE
400
401 return lxc_cmd_rsp_send(fd, &rsp);
402}
403
404/*
405 * lxc_cmd_get_cgroup_path: Calculate a container's cgroup path for a
406 * particular subsystem. This is the cgroup path relative to the root
407 * of the cgroup filesystem.
408 *
ef6e34ee
DE
409 * @name : name of container to connect to
410 * @lxcpath : the lxcpath in which the container is running
b98f7d6e 411 * @subsystem : the subsystem being asked about
ef6e34ee
DE
412 *
413 * Returns the path on success, NULL on failure. The caller must free() the
414 * returned path.
415 */
b98f7d6e 416char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
fe84a562 417 const char *subsystem)
ef6e34ee 418{
0ecf64b5 419 int ret, stopped;
ef6e34ee 420 struct lxc_cmd_rr cmd = {
b98f7d6e
SH
421 .req = {
422 .cmd = LXC_CMD_GET_CGROUP,
b98f7d6e 423 .data = subsystem,
c2aed66d 424 .datalen = 0,
b98f7d6e 425 },
26b2d152
MN
426 };
427
c2aed66d
CB
428 cmd.req.data = subsystem;
429 cmd.req.datalen = 0;
430 if (subsystem)
431 cmd.req.datalen = strlen(subsystem) + 1;
432
88556fd7 433 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
fe84a562 434 if (ret < 0)
ef6e34ee
DE
435 return NULL;
436
fe84a562 437 if (ret == 0)
ef6e34ee 438 return NULL;
ef6e34ee 439
fe84a562 440 if (cmd.rsp.ret < 0 || cmd.rsp.datalen < 0)
ef6e34ee 441 return NULL;
3f903c04 442
ef6e34ee
DE
443 return cmd.rsp.data;
444}
445
446static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
447 struct lxc_handler *handler,
448 struct lxc_epoll_descr *descr)
ef6e34ee 449{
4fb3cba5 450 const char *path;
fe84a562 451 struct lxc_cmd_rsp rsp;
2202afc9 452 struct cgroup_ops *cgroup_ops = handler->cgroup_ops;
b98f7d6e 453
c2aed66d 454 if (req->datalen > 0)
2202afc9 455 path = cgroup_ops->get_cgroup(cgroup_ops, req->data);
c2aed66d 456 else
2202afc9 457 path = cgroup_ops->get_cgroup(cgroup_ops, NULL);
b98f7d6e
SH
458 if (!path)
459 return -1;
fe84a562 460
4f17323e 461 rsp.ret = 0;
fe84a562
CB
462 rsp.datalen = strlen(path) + 1;
463 rsp.data = (char *)path;
ef6e34ee
DE
464
465 return lxc_cmd_rsp_send(fd, &rsp);
466}
467
468/*
469 * lxc_cmd_get_config_item: Get config item the running container
470 *
471 * @name : name of container to connect to
7fa3f2e9 472 * @item : the configuration item to retrieve (ex: lxc.net.0.veth.pair)
ef6e34ee
DE
473 * @lxcpath : the lxcpath in which the container is running
474 *
475 * Returns the item on success, NULL on failure. The caller must free() the
476 * returned item.
477 */
478char *lxc_cmd_get_config_item(const char *name, const char *item,
479 const char *lxcpath)
480{
0ecf64b5 481 int ret, stopped;
ef6e34ee
DE
482 struct lxc_cmd_rr cmd = {
483 .req = { .cmd = LXC_CMD_GET_CONFIG_ITEM,
484 .data = item,
fe84a562 485 .datalen = strlen(item) + 1,
ef6e34ee
DE
486 },
487 };
488
88556fd7 489 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ef6e34ee
DE
490 if (ret < 0)
491 return NULL;
492
493 if (cmd.rsp.ret == 0)
494 return cmd.rsp.data;
fe84a562 495
ef6e34ee
DE
496 return NULL;
497}
498
499static int lxc_cmd_get_config_item_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
500 struct lxc_handler *handler,
501 struct lxc_epoll_descr *descr)
ef6e34ee 502{
5265a60c 503 __do_free char *cidata = NULL;
ef6e34ee 504 int cilen;
30aec088 505 struct lxc_config_t *item;
fe84a562 506 struct lxc_cmd_rsp rsp;
ef6e34ee
DE
507
508 memset(&rsp, 0, sizeof(rsp));
300df83e 509 item = lxc_get_config(req->data);
30aec088
CB
510 if (!item)
511 goto err1;
fe84a562 512
cccd2219 513 cilen = item->get(req->data, NULL, 0, handler->conf, NULL);
ef6e34ee
DE
514 if (cilen <= 0)
515 goto err1;
516
5265a60c 517 cidata = must_realloc(NULL, cilen + 1);
cccd2219 518 if (item->get(req->data, cidata, cilen + 1, handler->conf, NULL) != cilen)
ef6e34ee 519 goto err1;
fe84a562 520
ef6e34ee
DE
521 cidata[cilen] = '\0';
522 rsp.data = cidata;
523 rsp.datalen = cilen + 1;
524 rsp.ret = 0;
525 goto out;
526
527err1:
528 rsp.ret = -1;
529out:
530 return lxc_cmd_rsp_send(fd, &rsp);
531}
532
533/*
534 * lxc_cmd_get_state: Get current state of the container
535 *
536 * @name : name of container to connect to
537 * @lxcpath : the lxcpath in which the container is running
538 *
539 * Returns the state on success, < 0 on failure
540 */
dbc9832d 541int lxc_cmd_get_state(const char *name, const char *lxcpath)
ef6e34ee 542{
0ecf64b5 543 int ret, stopped;
ef6e34ee 544 struct lxc_cmd_rr cmd = {
6c6497ea
CB
545 .req = {
546 .cmd = LXC_CMD_GET_STATE,
547 },
ef6e34ee 548 };
26b2d152 549
88556fd7 550 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ebdd307d 551 if (ret < 0 && stopped)
ef6e34ee
DE
552 return STOPPED;
553
554 if (ret < 0)
26b2d152 555 return -1;
26b2d152 556
6c6497ea
CB
557 if (!ret)
558 return log_warn(-1, "Container \"%s\" has stopped before sending its state", name);
fe84a562 559
6c6497ea
CB
560 return log_debug(PTR_TO_INT(cmd.rsp.data),
561 "Container \"%s\" is in \"%s\" state", name,
562 lxc_state2str(PTR_TO_INT(cmd.rsp.data)));
ef6e34ee
DE
563}
564
565static int lxc_cmd_get_state_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
566 struct lxc_handler *handler,
567 struct lxc_epoll_descr *descr)
ef6e34ee 568{
6c6497ea
CB
569 struct lxc_cmd_rsp rsp = {
570 .data = INT_TO_PTR(handler->state),
571 };
ef6e34ee
DE
572
573 return lxc_cmd_rsp_send(fd, &rsp);
574}
575
576/*
577 * lxc_cmd_stop: Stop the container previously started with lxc_start. All
578 * the processes running inside this container will be killed.
579 *
580 * @name : name of container to connect to
581 * @lxcpath : the lxcpath in which the container is running
582 *
583 * Returns 0 on success, < 0 on failure
584 */
585int lxc_cmd_stop(const char *name, const char *lxcpath)
586{
0ecf64b5 587 int ret, stopped;
ef6e34ee 588 struct lxc_cmd_rr cmd = {
6c6497ea
CB
589 .req = {
590 .cmd = LXC_CMD_STOP,
591 },
ef6e34ee
DE
592 };
593
88556fd7 594 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
26b2d152 595 if (ret < 0) {
6c6497ea
CB
596 if (stopped)
597 return log_info(0, "Container \"%s\" is already stopped", name);
fe84a562 598
26b2d152
MN
599 return -1;
600 }
601
fe84a562
CB
602 /* We do not expect any answer, because we wait for the connection to be
603 * closed.
95d5b147 604 */
6c6497ea
CB
605 if (ret > 0)
606 return log_error_errno(-1, -cmd.rsp.ret, "Failed to stop container \"%s\"", name);
26b2d152 607
6c6497ea 608 return log_info(0, "Container \"%s\" has stopped", name);
26b2d152
MN
609}
610
ef6e34ee 611static int lxc_cmd_stop_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
612 struct lxc_handler *handler,
613 struct lxc_epoll_descr *descr)
d5088cf2 614{
ef6e34ee 615 struct lxc_cmd_rsp rsp;
ef6e34ee 616 int stopsignal = SIGKILL;
2202afc9 617 struct cgroup_ops *cgroup_ops = handler->cgroup_ops;
ef6e34ee
DE
618
619 if (handler->conf->stopsignal)
620 stopsignal = handler->conf->stopsignal;
621 memset(&rsp, 0, sizeof(rsp));
622 rsp.ret = kill(handler->pid, stopsignal);
623 if (!rsp.ret) {
018051e3
CB
624 rsp.ret = cgroup_ops->unfreeze(cgroup_ops, -1);
625 if (!rsp.ret)
95d5b147 626 return 0;
fe84a562
CB
627
628 ERROR("Failed to unfreeze container \"%s\"", handler->name);
018051e3
CB
629 rsp.ret = -errno;
630 } else {
631 rsp.ret = -errno;
ef6e34ee
DE
632 }
633
634 return lxc_cmd_rsp_send(fd, &rsp);
635}
d5088cf2 636
b5159817 637/*
2bd158cc 638 * lxc_cmd_terminal_winch: noop
b5159817
DE
639 *
640 * @name : name of container to connect to
641 * @lxcpath : the lxcpath in which the container is running
642 *
643 * Returns 0 on success, < 0 on failure
644 */
8ccbbf94 645int lxc_cmd_terminal_winch(const char *name, const char *lxcpath)
b5159817 646{
b5159817
DE
647 return 0;
648}
649
8ccbbf94 650static int lxc_cmd_terminal_winch_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
651 struct lxc_handler *handler,
652 struct lxc_epoll_descr *descr)
b5159817 653{
2bd158cc 654 /* should never be called */
6c6497ea 655 return log_error_errno(-1, ENOSYS, "Called lxc_cmd_terminal_winch_callback()");
b5159817
DE
656}
657
ef6e34ee
DE
658/*
659 * lxc_cmd_console: Open an fd to a tty in the container
660 *
661 * @name : name of container to connect to
662 * @ttynum : in: the tty to open or -1 for next available
663 * : out: the tty allocated
664 * @fd : out: file descriptor for master side of pty
665 * @lxcpath : the lxcpath in which the container is running
666 *
0115f8fd 667 * Returns fd holding tty allocated on success, < 0 on failure
ef6e34ee
DE
668 */
669int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
670{
8259d86d 671 __do_free struct lxc_cmd_console_rsp_data *rspdata = NULL;
0ecf64b5 672 int ret, stopped;
ef6e34ee 673 struct lxc_cmd_rr cmd = {
6c6497ea
CB
674 .req = {
675 .cmd = LXC_CMD_CONSOLE,
676 .data = INT_TO_PTR(*ttynum),
677 },
ef6e34ee 678 };
d5088cf2 679
88556fd7 680 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ef6e34ee
DE
681 if (ret < 0)
682 return ret;
0115f8fd 683
8259d86d 684 rspdata = cmd.rsp.data;
6c6497ea
CB
685 if (cmd.rsp.ret < 0)
686 return log_error_errno(-1, -cmd.rsp.ret, "Denied access to tty");
d5088cf2 687
6c6497ea
CB
688 if (ret == 0)
689 return log_error(-1, "tty number %d invalid, busy or all ttys busy", *ttynum);
ef6e34ee 690
6c6497ea
CB
691 if (rspdata->masterfd < 0)
692 return log_error(-1, "Unable to allocate fd for tty %d", rspdata->ttynum);
ef6e34ee 693
fe84a562 694 ret = cmd.rsp.ret; /* socket fd */
0115f8fd 695 *fd = rspdata->masterfd;
ef6e34ee 696 *ttynum = rspdata->ttynum;
fe84a562 697
6c6497ea 698 return log_info(ret, "Alloced fd %d for tty %d via socket %d", *fd, rspdata->ttynum, ret);
ef6e34ee
DE
699}
700
701static int lxc_cmd_console_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
702 struct lxc_handler *handler,
703 struct lxc_epoll_descr *descr)
ef6e34ee 704{
fe84a562 705 int masterfd, ret;
ef6e34ee 706 struct lxc_cmd_rsp rsp;
fe84a562 707 int ttynum = PTR_TO_INT(req->data);
ef6e34ee 708
c1ee47cd 709 masterfd = lxc_terminal_allocate(handler->conf, fd, &ttynum);
b5159817 710 if (masterfd < 0)
ef6e34ee
DE
711 goto out_close;
712
ef6e34ee
DE
713 memset(&rsp, 0, sizeof(rsp));
714 rsp.data = INT_TO_PTR(ttynum);
fe84a562
CB
715 ret = lxc_abstract_unix_send_fds(fd, &masterfd, 1, &rsp, sizeof(rsp));
716 if (ret < 0) {
9044b79e 717 SYSERROR("Failed to send tty to client");
3dfe6f8d 718 lxc_terminal_free(handler->conf, fd);
ef6e34ee
DE
719 goto out_close;
720 }
721
ef6e34ee
DE
722 return 0;
723
724out_close:
fe84a562
CB
725 /* Special indicator to lxc_cmd_handler() to close the fd and do
726 * related cleanup.
ef6e34ee
DE
727 */
728 return 1;
d5088cf2
CS
729}
730
88556fd7
ÇO
731/*
732 * lxc_cmd_get_name: Returns the name of the container
733 *
734 * @hashed_sock_name: hashed socket name
735 *
736 * Returns the name on success, NULL on failure.
737 */
738char *lxc_cmd_get_name(const char *hashed_sock_name)
739{
740 int ret, stopped;
741 struct lxc_cmd_rr cmd = {
6c6497ea
CB
742 .req = {
743 .cmd = LXC_CMD_GET_NAME,
744 },
88556fd7
ÇO
745 };
746
747 ret = lxc_cmd(NULL, &cmd, &stopped, NULL, hashed_sock_name);
fe84a562 748 if (ret < 0)
88556fd7 749 return NULL;
88556fd7
ÇO
750
751 if (cmd.rsp.ret == 0)
752 return cmd.rsp.data;
fe84a562 753
88556fd7
ÇO
754 return NULL;
755}
756
757static int lxc_cmd_get_name_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
758 struct lxc_handler *handler,
759 struct lxc_epoll_descr *descr)
88556fd7
ÇO
760{
761 struct lxc_cmd_rsp rsp;
762
763 memset(&rsp, 0, sizeof(rsp));
764
f0ecc19d 765 rsp.data = (char *)handler->name;
88556fd7
ÇO
766 rsp.datalen = strlen(handler->name) + 1;
767 rsp.ret = 0;
768
769 return lxc_cmd_rsp_send(fd, &rsp);
770}
771
772/*
773 * lxc_cmd_get_lxcpath: Returns the lxcpath of the container
774 *
775 * @hashed_sock_name: hashed socket name
776 *
777 * Returns the lxcpath on success, NULL on failure.
778 */
779char *lxc_cmd_get_lxcpath(const char *hashed_sock_name)
780{
781 int ret, stopped;
782 struct lxc_cmd_rr cmd = {
6c6497ea
CB
783 .req = {
784 .cmd = LXC_CMD_GET_LXCPATH,
785 },
88556fd7 786 };
724e753c 787
88556fd7 788 ret = lxc_cmd(NULL, &cmd, &stopped, NULL, hashed_sock_name);
fe84a562 789 if (ret < 0)
88556fd7 790 return NULL;
88556fd7
ÇO
791
792 if (cmd.rsp.ret == 0)
793 return cmd.rsp.data;
fe84a562 794
88556fd7
ÇO
795 return NULL;
796}
797
798static int lxc_cmd_get_lxcpath_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
799 struct lxc_handler *handler,
800 struct lxc_epoll_descr *descr)
88556fd7 801{
6c6497ea
CB
802 struct lxc_cmd_rsp rsp = {
803 .ret = 0,
804 .data = (char *)handler->lxcpath,
805 .datalen = strlen(handler->lxcpath) + 1,
806 };
88556fd7
ÇO
807
808 return lxc_cmd_rsp_send(fd, &rsp);
809}
ef6e34ee 810
54446942 811int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
92e35018
CB
812 lxc_state_t states[MAX_STATE],
813 int *state_client_fd)
dbc9832d 814{
cd889e57 815 __do_close_prot_errno int clientfd = -EBADF;
bc631984 816 int state, stopped;
dbc9832d 817 ssize_t ret;
dbc9832d 818 struct lxc_cmd_rr cmd = {
6c6497ea
CB
819 .req = {
820 .cmd = LXC_CMD_ADD_STATE_CLIENT,
821 .data = states,
822 .datalen = (sizeof(lxc_state_t) * MAX_STATE)
823 },
dbc9832d
CB
824 };
825
dbc9832d 826 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
bc631984
CB
827 if (states[STOPPED] != 0 && stopped != 0)
828 return STOPPED;
829
dbc9832d 830 if (ret < 0) {
f577e061 831 if (errno != ECONNREFUSED)
6d1400b5 832 SYSERROR("Failed to execute command");
833
dbc9832d
CB
834 return -1;
835 }
fe84a562 836
dbc9832d
CB
837 /* We should now be guaranteed to get an answer from the state sending
838 * function.
839 */
cd889e57 840 clientfd = cmd.rsp.ret;
6c6497ea
CB
841 if (clientfd < 0)
842 return log_error_errno(-1, -clientfd, "Failed to receive socket fd");
dbc9832d 843
bc631984 844 state = PTR_TO_INT(cmd.rsp.data);
6c6497ea
CB
845 if (state < MAX_STATE)
846 return log_trace(state, "Container is already in requested state %s", lxc_state2str(state));
bc631984 847
240fecd0 848 *state_client_fd = move_fd(clientfd);
6c6497ea 849 return log_trace(MAX_STATE, "Added state client %d to state client list", *state_client_fd);
dbc9832d
CB
850}
851
ebbca852 852static int lxc_cmd_add_state_client_callback(__owns int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
853 struct lxc_handler *handler,
854 struct lxc_epoll_descr *descr)
dbc9832d 855{
44552fb2 856 int ret;
dbc9832d 857 struct lxc_cmd_rsp rsp = {0};
dbc9832d 858
fe84a562 859 if (req->datalen < 0)
44552fb2 860 goto reap_client_fd;
dbc9832d 861
71fc9c04 862 if (req->datalen != (sizeof(lxc_state_t) * MAX_STATE))
44552fb2 863 goto reap_client_fd;
dbc9832d 864
fe84a562 865 if (!req->data)
44552fb2 866 goto reap_client_fd;
dbc9832d 867
c01c2be6 868 rsp.ret = lxc_add_state_client(fd, handler, (lxc_state_t *)req->data);
44552fb2
CB
869 if (rsp.ret < 0)
870 goto reap_client_fd;
871
bc631984 872 rsp.data = INT_TO_PTR(rsp.ret);
dbc9832d 873
44552fb2
CB
874 ret = lxc_cmd_rsp_send(fd, &rsp);
875 if (ret < 0)
876 goto reap_client_fd;
877
ebbca852
MH
878 /* close fd if state is already achieved to avoid leakage */
879 if (rsp.ret != MAX_STATE)
880 close(fd);
881
44552fb2
CB
882 return 0;
883
884reap_client_fd:
885 /* Special indicator to lxc_cmd_handler() to close the fd and do related
886 * cleanup.
887 */
888 return 1;
dbc9832d
CB
889}
890
2a63b5cb
CB
891int lxc_cmd_add_bpf_device_cgroup(const char *name, const char *lxcpath,
892 struct device_item *device)
893{
894#ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX
895 int stopped = 0;
896 struct lxc_cmd_rr cmd = {
6c6497ea
CB
897 .req = {
898 .cmd = LXC_CMD_ADD_BPF_DEVICE_CGROUP,
899 .data = device,
900 .datalen = sizeof(struct device_item),
901 },
2a63b5cb
CB
902 };
903 int ret;
904
905 if (strlen(device->access) > STRLITERALLEN("rwm"))
3d0327ed 906 return log_error_errno(-1, EINVAL, "Invalid access mode specified %s",
2a63b5cb
CB
907 device->access);
908
909 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
910 if (ret < 0 || cmd.rsp.ret < 0)
3d0327ed 911 return log_error_errno(-1, errno, "Failed to add new bpf device cgroup rule");
2a63b5cb
CB
912
913 return 0;
914#else
3d0327ed 915 return ret_set_errno(-1, ENOSYS);
2a63b5cb
CB
916#endif
917}
918
919static int lxc_cmd_add_bpf_device_cgroup_callback(int fd, struct lxc_cmd_req *req,
920 struct lxc_handler *handler,
921 struct lxc_epoll_descr *descr)
922{
923#ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX
924 __do_bpf_program_free struct bpf_program *devices = NULL;
925 struct lxc_cmd_rsp rsp = {0};
926 struct lxc_conf *conf = handler->conf;
927 struct hierarchy *unified = handler->cgroup_ops->unified;
2a63b5cb
CB
928 int ret;
929 struct lxc_list *it;
930 struct device_item *device;
931 struct bpf_program *devices_old;
932
933 if (req->datalen <= 0)
934 goto reap_client_fd;
935
936 if (req->datalen != sizeof(struct device_item))
937 goto reap_client_fd;
938
939 if (!req->data)
940 goto reap_client_fd;
941 device = (struct device_item *)req->data;
942
943 rsp.ret = -1;
944 if (!unified)
945 goto respond;
946
947 ret = bpf_list_add_device(conf, device);
948 if (ret < 0)
949 goto respond;
950
951 devices = bpf_program_new(BPF_PROG_TYPE_CGROUP_DEVICE);
952 if (!devices)
953 goto respond;
954
955 ret = bpf_program_init(devices);
956 if (ret)
957 goto respond;
958
959 lxc_list_for_each(it, &conf->devices) {
960 struct device_item *cur = it->elem;
961
962 ret = bpf_program_append_device(devices, cur);
963 if (ret)
964 goto respond;
965 }
966
967 ret = bpf_program_finalize(devices);
968 if (ret)
969 goto respond;
970
971 ret = bpf_program_cgroup_attach(devices, BPF_CGROUP_DEVICE,
972 unified->container_full_path,
973 BPF_F_ALLOW_MULTI);
974 if (ret)
975 goto respond;
976
977 /* Replace old bpf program. */
978 devices_old = move_ptr(conf->cgroup2_devices);
979 conf->cgroup2_devices = move_ptr(devices);
980 devices = move_ptr(devices_old);
981
982 rsp.ret = 0;
983
984respond:
985 ret = lxc_cmd_rsp_send(fd, &rsp);
986 if (ret < 0)
987 goto reap_client_fd;
988
989 return 0;
990
991reap_client_fd:
992 /* Special indicator to lxc_cmd_handler() to close the fd and do related
993 * cleanup.
994 */
995 return 1;
996#else
3d0327ed 997 return ret_set_errno(-1, ENOSYS);
2a63b5cb
CB
998#endif
999}
1000
191d43cc
CB
1001int lxc_cmd_console_log(const char *name, const char *lxcpath,
1002 struct lxc_console_log *log)
1003{
1004 int ret, stopped;
1005 struct lxc_cmd_console_log data;
1006 struct lxc_cmd_rr cmd;
1007
1008 data.clear = log->clear;
1009 data.read = log->read;
1010 data.read_max = *log->read_max;
1011
1012 cmd.req.cmd = LXC_CMD_CONSOLE_LOG;
1013 cmd.req.data = &data;
1014 cmd.req.datalen = sizeof(struct lxc_cmd_console_log);
1015
1016 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
1017 if (ret < 0)
1018 return ret;
1019
1020 /* There is nothing to be read from the buffer. So clear any values we
1021 * where passed to clearly indicate to the user that nothing went wrong.
1022 */
63b74cda 1023 if (cmd.rsp.ret == -ENODATA || cmd.rsp.ret == -EFAULT || cmd.rsp.ret == -ENOENT) {
191d43cc
CB
1024 *log->read_max = 0;
1025 log->data = NULL;
1026 }
1027
1028 /* This is a proper error so don't touch any values we were passed. */
1029 if (cmd.rsp.ret < 0)
1030 return cmd.rsp.ret;
1031
1032 *log->read_max = cmd.rsp.datalen;
1033 log->data = cmd.rsp.data;
1034
1035 return 0;
1036}
1037
1038static int lxc_cmd_console_log_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1039 struct lxc_handler *handler,
1040 struct lxc_epoll_descr *descr)
191d43cc
CB
1041{
1042 struct lxc_cmd_rsp rsp;
28f3b1cd 1043 uint64_t buffer_size = handler->conf->console.buffer_size;
191d43cc
CB
1044 const struct lxc_cmd_console_log *log = req->data;
1045 struct lxc_ringbuf *buf = &handler->conf->console.ringbuf;
1046
1047 rsp.ret = -EFAULT;
1048 rsp.datalen = 0;
1049 rsp.data = NULL;
28f3b1cd 1050 if (buffer_size <= 0)
191d43cc
CB
1051 goto out;
1052
5928191e
CB
1053 if (log->read || log->write_logfile)
1054 rsp.datalen = lxc_ringbuf_used(buf);
1055
191d43cc
CB
1056 if (log->read)
1057 rsp.data = lxc_ringbuf_get_read_addr(buf);
1058
1059 if (log->read_max > 0 && (log->read_max <= rsp.datalen))
1060 rsp.datalen = log->read_max;
1061
1062 /* there's nothing to read */
63b74cda 1063 rsp.ret = -ENODATA;
191d43cc 1064 if (log->read && (buf->r_off == buf->w_off))
63b74cda
CB
1065 goto out;
1066
63b74cda 1067 rsp.ret = 0;
23e0d9af 1068 if (log->clear)
43366ca2 1069 lxc_ringbuf_clear(buf); /* clear the ringbuffer */
23e0d9af 1070 else if (rsp.datalen > 0)
191d43cc
CB
1071 lxc_ringbuf_move_read_addr(buf, rsp.datalen);
1072
1073out:
1074 return lxc_cmd_rsp_send(fd, &rsp);
1075}
1076
974a8aba
CB
1077int lxc_cmd_serve_state_clients(const char *name, const char *lxcpath,
1078 lxc_state_t state)
1079{
1080 int stopped;
1081 ssize_t ret;
1082 struct lxc_cmd_rr cmd = {
6c6497ea
CB
1083 .req = {
1084 .cmd = LXC_CMD_SERVE_STATE_CLIENTS,
1085 .data = INT_TO_PTR(state)
1086 },
974a8aba
CB
1087 };
1088
1089 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
6c6497ea
CB
1090 if (ret < 0)
1091 return log_error_errno(-1, errno, "Failed to serve state clients");
974a8aba
CB
1092
1093 return 0;
1094}
1095
1096static int lxc_cmd_serve_state_clients_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1097 struct lxc_handler *handler,
1098 struct lxc_epoll_descr *descr)
974a8aba
CB
1099{
1100 int ret;
1101 lxc_state_t state = PTR_TO_INT(req->data);
1102 struct lxc_cmd_rsp rsp = {0};
1103
1104 ret = lxc_serve_state_clients(handler->name, handler, state);
1105 if (ret < 0)
1106 goto reap_client_fd;
1107
1108 ret = lxc_cmd_rsp_send(fd, &rsp);
1109 if (ret < 0)
1110 goto reap_client_fd;
1111
1112 return 0;
1113
1114reap_client_fd:
6c6497ea
CB
1115 /*
1116 * Special indicator to lxc_cmd_handler() to close the fd and do
1117 * related cleanup.
974a8aba
CB
1118 */
1119 return 1;
1120}
1121
cdb2a47f
CB
1122int lxc_cmd_seccomp_notify_add_listener(const char *name, const char *lxcpath,
1123 int fd,
1124 /* unused */ unsigned int command,
1125 /* unused */ unsigned int flags)
1126{
1127
c3e3c21a 1128#ifdef HAVE_SECCOMP_NOTIFY
cdb2a47f
CB
1129 int ret, stopped;
1130 struct lxc_cmd_rr cmd = {
1131 .req = {
1132 .cmd = LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER,
1133 .data = INT_TO_PTR(fd),
1134 },
1135 };
1136
1137 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
6c6497ea
CB
1138 if (ret < 0)
1139 return log_error_errno(-1, errno, "Failed to add seccomp listener");
cdb2a47f
CB
1140
1141 return cmd.rsp.ret;
1142#else
3d0327ed 1143 return ret_set_errno(-1, ENOSYS);
cdb2a47f
CB
1144#endif
1145}
1146
1147static int lxc_cmd_seccomp_notify_add_listener_callback(int fd,
1148 struct lxc_cmd_req *req,
1149 struct lxc_handler *handler,
1150 struct lxc_epoll_descr *descr)
1151{
1152 struct lxc_cmd_rsp rsp = {0};
cdb2a47f 1153
c3e3c21a
CB
1154#ifdef HAVE_SECCOMP_NOTIFY
1155 int ret;
cdb2a47f 1156 __do_close_prot_errno int recv_fd = -EBADF;
cdb2a47f 1157
c3e3c21a
CB
1158 ret = lxc_abstract_unix_recv_fds(fd, &recv_fd, 1, NULL, 0);
1159 if (ret <= 0) {
1160 rsp.ret = -errno;
1161 goto out;
cdb2a47f
CB
1162 }
1163
c3e3c21a
CB
1164 if (!handler->conf->seccomp.notifier.wants_supervision ||
1165 handler->conf->seccomp.notifier.proxy_fd < 0) {
1166 SYSERROR("No seccomp proxy fd specified");
1167 rsp.ret = -EINVAL;
1168 goto out;
1169 }
cdb2a47f 1170
c3e3c21a 1171 ret = lxc_mainloop_add_handler(descr, recv_fd, seccomp_notify_handler,
cdb2a47f 1172 handler);
c3e3c21a
CB
1173 if (ret < 0) {
1174 rsp.ret = -errno;
1175 goto out;
1176 }
68a9e3eb 1177 move_fd(recv_fd);
cdb2a47f 1178
c3e3c21a 1179out:
cdb2a47f
CB
1180#else
1181 rsp.ret = -ENOSYS;
cdb2a47f 1182
c3e3c21a
CB
1183#endif
1184 return lxc_cmd_rsp_send(fd, &rsp);
cdb2a47f
CB
1185}
1186
018051e3
CB
1187int lxc_cmd_freeze(const char *name, const char *lxcpath, int timeout)
1188{
1189 int ret, stopped;
1190 struct lxc_cmd_rr cmd = {
1191 .req = {
1192 .cmd = LXC_CMD_FREEZE,
1193 .data = INT_TO_PTR(timeout),
1194 },
1195 };
1196
1197 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
1198 if (ret <= 0 || cmd.rsp.ret < 0)
3d0327ed 1199 return log_error_errno(-1, errno, "Failed to freeze container");
018051e3
CB
1200
1201 return cmd.rsp.ret;
1202}
1203
1204static int lxc_cmd_freeze_callback(int fd, struct lxc_cmd_req *req,
1205 struct lxc_handler *handler,
1206 struct lxc_epoll_descr *descr)
1207{
1208 int timeout = PTR_TO_INT(req->data);
1209 struct lxc_cmd_rsp rsp = {
6c6497ea 1210 .ret = -ENOENT,
018051e3
CB
1211 };
1212 struct cgroup_ops *ops = handler->cgroup_ops;
1213
1973b62a 1214 if (pure_unified_layout(ops))
018051e3
CB
1215 rsp.ret = ops->freeze(ops, timeout);
1216
1217 return lxc_cmd_rsp_send(fd, &rsp);
1218}
1219
1220int lxc_cmd_unfreeze(const char *name, const char *lxcpath, int timeout)
1221{
1222 int ret, stopped;
1223 struct lxc_cmd_rr cmd = {
1224 .req = {
1225 .cmd = LXC_CMD_UNFREEZE,
1226 .data = INT_TO_PTR(timeout),
1227 },
1228 };
1229
1230 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
1231 if (ret <= 0 || cmd.rsp.ret < 0)
3d0327ed 1232 return log_error_errno(-1, errno, "Failed to unfreeze container");
018051e3
CB
1233
1234 return cmd.rsp.ret;
1235}
1236
1237static int lxc_cmd_unfreeze_callback(int fd, struct lxc_cmd_req *req,
1238 struct lxc_handler *handler,
1239 struct lxc_epoll_descr *descr)
1240{
1241 int timeout = PTR_TO_INT(req->data);
1242 struct lxc_cmd_rsp rsp = {
6c6497ea 1243 .ret = -ENOENT,
018051e3
CB
1244 };
1245 struct cgroup_ops *ops = handler->cgroup_ops;
1246
1973b62a 1247 if (pure_unified_layout(ops))
018051e3
CB
1248 rsp.ret = ops->unfreeze(ops, timeout);
1249
1250 return lxc_cmd_rsp_send(fd, &rsp);
1251}
1252
bad788b0
CB
1253int lxc_cmd_get_cgroup2_fd(const char *name, const char *lxcpath)
1254{
1255 int ret, stopped;
1256 struct lxc_cmd_rr cmd = {
1257 .req = {
1258 .cmd = LXC_CMD_GET_CGROUP2_FD,
1259 },
1260 };
1261
1262 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
23a917e5
CB
1263 if (ret < 0)
1264 return -1;
1265
1266 if (cmd.rsp.ret < 0)
900b6606 1267 return log_debug_errno(-1, errno, "Failed to receive cgroup2 fd");
bad788b0
CB
1268
1269 return PTR_TO_INT(cmd.rsp.data);
1270}
1271
1272static int lxc_cmd_get_cgroup2_fd_callback(int fd, struct lxc_cmd_req *req,
1273 struct lxc_handler *handler,
1274 struct lxc_epoll_descr *descr)
1275{
1276 struct lxc_cmd_rsp rsp = {
1277 .ret = -EINVAL,
1278 };
1279 struct cgroup_ops *ops = handler->cgroup_ops;
1280 int ret;
1281
1973b62a 1282 if (!pure_unified_layout(ops) || !ops->unified)
bad788b0
CB
1283 return lxc_cmd_rsp_send(fd, &rsp);
1284
1285 rsp.ret = 0;
1973b62a 1286 ret = lxc_abstract_unix_send_fds(fd, &ops->unified->cgfd_con, 1, &rsp,
bad788b0
CB
1287 sizeof(rsp));
1288 if (ret < 0)
1289 return log_error(1, "Failed to send cgroup2 fd");
1290
1291 return 0;
1292}
1293
ef6e34ee 1294static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1295 struct lxc_handler *handler,
1296 struct lxc_epoll_descr *descr)
724e753c 1297{
cdb2a47f
CB
1298 typedef int (*callback)(int, struct lxc_cmd_req *, struct lxc_handler *,
1299 struct lxc_epoll_descr *);
ef6e34ee
DE
1300
1301 callback cb[LXC_CMD_MAX] = {
2a63b5cb
CB
1302 [LXC_CMD_CONSOLE] = lxc_cmd_console_callback,
1303 [LXC_CMD_TERMINAL_WINCH] = lxc_cmd_terminal_winch_callback,
1304 [LXC_CMD_STOP] = lxc_cmd_stop_callback,
1305 [LXC_CMD_GET_STATE] = lxc_cmd_get_state_callback,
1306 [LXC_CMD_GET_INIT_PID] = lxc_cmd_get_init_pid_callback,
1307 [LXC_CMD_GET_CLONE_FLAGS] = lxc_cmd_get_clone_flags_callback,
1308 [LXC_CMD_GET_CGROUP] = lxc_cmd_get_cgroup_callback,
1309 [LXC_CMD_GET_CONFIG_ITEM] = lxc_cmd_get_config_item_callback,
1310 [LXC_CMD_GET_NAME] = lxc_cmd_get_name_callback,
1311 [LXC_CMD_GET_LXCPATH] = lxc_cmd_get_lxcpath_callback,
1312 [LXC_CMD_ADD_STATE_CLIENT] = lxc_cmd_add_state_client_callback,
1313 [LXC_CMD_CONSOLE_LOG] = lxc_cmd_console_log_callback,
1314 [LXC_CMD_SERVE_STATE_CLIENTS] = lxc_cmd_serve_state_clients_callback,
1315 [LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER] = lxc_cmd_seccomp_notify_add_listener_callback,
1316 [LXC_CMD_ADD_BPF_DEVICE_CGROUP] = lxc_cmd_add_bpf_device_cgroup_callback,
018051e3
CB
1317 [LXC_CMD_FREEZE] = lxc_cmd_freeze_callback,
1318 [LXC_CMD_UNFREEZE] = lxc_cmd_unfreeze_callback,
bad788b0 1319 [LXC_CMD_GET_CGROUP2_FD] = lxc_cmd_get_cgroup2_fd_callback,
724e753c
MN
1320 };
1321
23a917e5
CB
1322 if (req->cmd >= LXC_CMD_MAX)
1323 return log_error_errno(-1, ENOENT, "Undefined command id %d", req->cmd);
1324
cdb2a47f 1325 return cb[req->cmd](fd, req, handler, descr);
724e753c
MN
1326}
1327
ef6e34ee 1328static void lxc_cmd_fd_cleanup(int fd, struct lxc_handler *handler,
cdb2a47f 1329 struct lxc_epoll_descr *descr, const lxc_cmd_t cmd)
724e753c 1330{
f6fc1565
CB
1331 struct lxc_list *cur, *next;
1332
3dfe6f8d 1333 lxc_terminal_free(handler->conf, fd);
724e753c 1334 lxc_mainloop_del_handler(descr, fd);
f6fc1565 1335
cdb2a47f
CB
1336 switch (cmd) {
1337 case LXC_CMD_ADD_STATE_CLIENT:
1338 lxc_list_for_each_safe(cur, &handler->conf->state_clients, next) {
1339 struct lxc_state_client *client = cur->elem;
1340
1341 if (client->clientfd != fd)
1342 continue;
1343
1344 /* kick client from list */
1345 lxc_list_del(cur);
1346 close(client->clientfd);
1347 free(cur->elem);
1348 free(cur);
1349 /* No need to walk the whole list. If we found the state
1350 * client fd there can't be a second one.
1351 */
1352 break;
1353 }
b1ca434a 1354 break;
cdb2a47f
CB
1355 default:
1356 close(fd);
f6fc1565 1357 }
724e753c
MN
1358}
1359
84c92abd
DE
1360static int lxc_cmd_handler(int fd, uint32_t events, void *data,
1361 struct lxc_epoll_descr *descr)
724e753c 1362{
5265a60c 1363 __do_free void *reqdata = NULL;
724e753c 1364 int ret;
ef6e34ee 1365 struct lxc_cmd_req req;
724e753c
MN
1366 struct lxc_handler *handler = data;
1367
aae93dd3 1368 ret = lxc_abstract_unix_rcv_credential(fd, &req, sizeof(req));
ded1d23f 1369 if (ret < 0) {
fe84a562 1370 SYSERROR("Failed to receive data on command socket for command "
9044b79e 1371 "\"%s\"", lxc_cmd_str(req.cmd));
1372
1373 if (errno == EACCES) {
1374 /* We don't care for the peer, just send and close. */
1375 struct lxc_cmd_rsp rsp = {.ret = ret};
1376
1377 lxc_cmd_rsp_send(fd, &rsp);
1378 }
1379
724e753c
MN
1380 goto out_close;
1381 }
1382
fe84a562 1383 if (ret == 0)
724e753c 1384 goto out_close;
724e753c 1385
ef6e34ee 1386 if (ret != sizeof(req)) {
c01c2be6 1387 WARN("Failed to receive full command request. Ignoring request "
fe84a562 1388 "for \"%s\"", lxc_cmd_str(req.cmd));
ef6e34ee
DE
1389 ret = -1;
1390 goto out_close;
1391 }
1392
191d43cc
CB
1393 if ((req.datalen > LXC_CMD_DATA_MAX) &&
1394 (req.cmd != LXC_CMD_CONSOLE_LOG)) {
c01c2be6 1395 ERROR("Received command data length %d is too large for "
fe84a562
CB
1396 "command \"%s\"", req.datalen, lxc_cmd_str(req.cmd));
1397 errno = EFBIG;
1398 ret = -EFBIG;
724e753c
MN
1399 goto out_close;
1400 }
1401
ef6e34ee 1402 if (req.datalen > 0) {
5265a60c 1403 reqdata = must_realloc(NULL, req.datalen);
e3233f26 1404 ret = lxc_recv_nointr(fd, reqdata, req.datalen, 0);
ef6e34ee 1405 if (ret != req.datalen) {
c01c2be6 1406 WARN("Failed to receive full command request. Ignoring "
fe84a562 1407 "request for \"%s\"", lxc_cmd_str(req.cmd));
b2a48508 1408 ret = LXC_MAINLOOP_ERROR;
ef6e34ee
DE
1409 goto out_close;
1410 }
fe84a562 1411
ef6e34ee
DE
1412 req.data = reqdata;
1413 }
1414
cdb2a47f 1415 ret = lxc_cmd_process(fd, &req, handler, descr);
724e753c 1416 if (ret) {
fe84a562 1417 /* This is not an error, but only a request to close fd. */
b2a48508 1418 ret = LXC_MAINLOOP_CONTINUE;
724e753c
MN
1419 goto out_close;
1420 }
1421
1422out:
1423 return ret;
fe84a562 1424
724e753c 1425out_close:
f6fc1565 1426 lxc_cmd_fd_cleanup(fd, handler, descr, req.cmd);
724e753c
MN
1427 goto out;
1428}
1429
84c92abd
DE
1430static int lxc_cmd_accept(int fd, uint32_t events, void *data,
1431 struct lxc_epoll_descr *descr)
724e753c 1432{
4c2effce 1433 __do_close_prot_errno int connection = -EBADF;
fe84a562 1434 int opt = 1, ret = -1;
724e753c
MN
1435
1436 connection = accept(fd, NULL, 0);
6c6497ea
CB
1437 if (connection < 0)
1438 return log_error_errno(LXC_MAINLOOP_ERROR, errno, "Failed to accept connection to run command");
724e753c 1439
fe84a562 1440 ret = fcntl(connection, F_SETFD, FD_CLOEXEC);
6c6497ea
CB
1441 if (ret < 0)
1442 return log_error_errno(ret, errno, "Failed to set close-on-exec on incoming command connection");
9ccb2dbc 1443
fe84a562 1444 ret = setsockopt(connection, SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt));
6c6497ea
CB
1445 if (ret < 0)
1446 return log_error_errno(ret, errno, "Failed to enable necessary credentials on command socket");
724e753c 1447
ef6e34ee 1448 ret = lxc_mainloop_add_handler(descr, connection, lxc_cmd_handler, data);
6c6497ea
CB
1449 if (ret)
1450 return log_error(ret, "Failed to add command handler");
724e753c 1451
240fecd0 1452 move_fd(connection);
724e753c 1453 return ret;
724e753c
MN
1454}
1455
9dfa4041 1456int lxc_cmd_init(const char *name, const char *lxcpath, const char *suffix)
724e753c 1457{
c13e7111
CB
1458 __do_close_prot_errno int fd = -EBADF;
1459 int ret;
b1234129 1460 char path[LXC_AUDS_ADDR_LEN] = {0};
724e753c 1461
5b46db1a 1462 ret = lxc_make_abstract_socket_name(path, sizeof(path), name, lxcpath, NULL, suffix);
fe84a562 1463 if (ret < 0)
9ba8130c 1464 return -1;
724e753c 1465
aae93dd3 1466 fd = lxc_abstract_unix_open(path, SOCK_STREAM, 0);
724e753c 1467 if (fd < 0) {
08aa08fe 1468 if (errno == EADDRINUSE)
fe84a562 1469 ERROR("Container \"%s\" appears to be already running", name);
6d1400b5 1470
6c6497ea 1471 return log_error_errno(-1, errno, "Failed to create command socket %s", &path[1]);
724e753c
MN
1472 }
1473
fe84a562 1474 ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
6c6497ea
CB
1475 if (ret < 0)
1476 return log_error_errno(-1, errno, "Failed to set FD_CLOEXEC on command socket file descriptor");
91480a0f 1477
6c6497ea 1478 return log_trace(move_fd(fd), "Created abstract unix socket \"%s\"", &path[1]);
d2e30e99
DE
1479}
1480
fe84a562 1481int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr,
ef6e34ee 1482 struct lxc_handler *handler)
d2e30e99 1483{
2a30bdea 1484 __do_close_prot_errno int fd = handler->conf->maincmd_fd;
fe84a562 1485 int ret;
d2e30e99 1486
ef6e34ee 1487 ret = lxc_mainloop_add_handler(descr, fd, lxc_cmd_accept, handler);
6c6497ea
CB
1488 if (ret < 0)
1489 return log_error(ret, "Failed to add handler for command socket");
724e753c 1490
240fecd0 1491 move_fd(fd);
724e753c
MN
1492 return ret;
1493}