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