]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/commands.c
commands: port lxc_try_cmd() to new helpers
[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"
5f126977 20#include "cgroups/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] = {
7e85a2c4 68 [LXC_CMD_GET_TTY_FD] = "get_tty_fd",
2a63b5cb
CB
69 [LXC_CMD_TERMINAL_WINCH] = "terminal_winch",
70 [LXC_CMD_STOP] = "stop",
71 [LXC_CMD_GET_STATE] = "get_state",
72 [LXC_CMD_GET_INIT_PID] = "get_init_pid",
73 [LXC_CMD_GET_CLONE_FLAGS] = "get_clone_flags",
74 [LXC_CMD_GET_CGROUP] = "get_cgroup",
75 [LXC_CMD_GET_CONFIG_ITEM] = "get_config_item",
76 [LXC_CMD_GET_NAME] = "get_name",
77 [LXC_CMD_GET_LXCPATH] = "get_lxcpath",
78 [LXC_CMD_ADD_STATE_CLIENT] = "add_state_client",
79 [LXC_CMD_CONSOLE_LOG] = "console_log",
80 [LXC_CMD_SERVE_STATE_CLIENTS] = "serve_state_clients",
81 [LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER] = "seccomp_notify_add_listener",
82 [LXC_CMD_ADD_BPF_DEVICE_CGROUP] = "add_bpf_device_cgroup",
018051e3
CB
83 [LXC_CMD_FREEZE] = "freeze",
84 [LXC_CMD_UNFREEZE] = "unfreeze",
bad788b0 85 [LXC_CMD_GET_CGROUP2_FD] = "get_cgroup2_fd",
746aab51 86 [LXC_CMD_GET_INIT_PIDFD] = "get_init_pidfd",
a9b642ee
CB
87 [LXC_CMD_GET_LIMIT_CGROUP] = "get_limit_cgroup",
88 [LXC_CMD_GET_LIMIT_CGROUP2_FD] = "get_limit_cgroup2_fd",
f797f05e 89 [LXC_CMD_GET_DEVPTS_FD] = "get_devpts_fd",
21405769 90 [LXC_CMD_GET_SECCOMP_NOTIFY_FD] = "get_seccomp_notify_fd",
ef6e048a 91 [LXC_CMD_GET_CGROUP_CTX] = "get_cgroup_ctx",
c206ac24
CB
92 [LXC_CMD_GET_CGROUP_FD] = "get_cgroup_fd",
93 [LXC_CMD_GET_LIMIT_CGROUP_FD] = "get_limit_cgroup_fd",
ef6e34ee 94 };
724e753c 95
f371aca9 96 if (cmd >= LXC_CMD_MAX)
a8007512 97 return "Invalid request";
fe84a562 98
ef6e34ee
DE
99 return cmdname[cmd];
100}
101
ef6e048a
CB
102static int __transfer_cgroup_ctx_fds(struct unix_fds *fds, struct cgroup_ctx *ctx)
103{
104 /* This shouldn't be able to happen but better safe than sorry. */
105 if (ctx->fd_len != fds->fd_count_ret ||
106 fds->fd_count_ret > CGROUP_CTX_MAX_FD)
107 return syswarn_set(-EINVAL, "Unexpected number of file descriptors received %u != %u",
108 ctx->fd_len, fds->fd_count_ret);
109
110 memcpy(ctx->fd, fds->fd, ctx->fd_len * sizeof(__s32));
111 fds->fd_count_ret = 0;
112 return 0;
113}
114
abb6f657
CB
115static int __transfer_cgroup_fd(struct unix_fds *fds, struct cgroup_fd *fd)
116{
117 fd->fd = move_fd(fds->fd[0]);
118 return 0;
119}
120
ef6e34ee
DE
121/*
122 * lxc_cmd_rsp_recv: Receive a response to a command
123 *
124 * @sock : the socket connected to the container
125 * @cmd : command to put response in
126 *
127 * Returns the size of the response message or < 0 on failure
128 *
129 * Note that if the command response datalen > 0, then data is
130 * a malloc()ed buffer and should be free()ed by the caller. If
131 * the response data is <= a void * worth of data, it will be
132 * stored directly in data and datalen will be 0.
133 *
7e85a2c4
CB
134 * As a special case, the response for LXC_CMD_GET_TTY_FD is created here as
135 * it contains an fd for the ptx pty passed through the unix socket.
ef6e34ee
DE
136 */
137static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
138{
abb6f657 139 __do_free void *__private_ptr = NULL;
7e85a2c4 140 struct lxc_cmd_tty_rsp_data *data_console = NULL;
f8cc4ae8 141 call_cleaner(put_unix_fds) struct unix_fds *fds = &(struct unix_fds){};
ef6e34ee 142 struct lxc_cmd_rsp *rsp = &cmd->rsp;
abb6f657 143 int cur_cmd = cmd->req.cmd, fret = 0;
1454e5d9 144 const char *cur_cmdstr;
f8cc4ae8 145 int ret;
ef6e34ee 146
abb6f657
CB
147 /*
148 * Determine whether this command will receive file descriptors and how
149 * many at most.
150 */
1454e5d9
CB
151 cur_cmdstr = lxc_cmd_str(cur_cmd);
152 switch (cur_cmd) {
c206ac24
CB
153 case LXC_CMD_GET_CGROUP_FD:
154 __fallthrough;
155 case LXC_CMD_GET_LIMIT_CGROUP_FD:
156 __fallthrough;
f8cc4ae8
CB
157 case LXC_CMD_GET_CGROUP2_FD:
158 __fallthrough;
a9b642ee 159 case LXC_CMD_GET_LIMIT_CGROUP2_FD:
f8cc4ae8
CB
160 __fallthrough;
161 case LXC_CMD_GET_INIT_PIDFD:
162 __fallthrough;
163 case LXC_CMD_GET_SECCOMP_NOTIFY_FD:
164 __fallthrough;
165 case LXC_CMD_GET_DEVPTS_FD:
166 __fallthrough;
7e85a2c4 167 case LXC_CMD_GET_TTY_FD:
f8cc4ae8
CB
168 fds->fd_count_max = 1;
169 break;
ef6e048a
CB
170 case LXC_CMD_GET_CGROUP_CTX:
171 fds->fd_count_max = CGROUP_CTX_MAX_FD;
f8cc4ae8
CB
172 break;
173 default:
174 fds->fd_count_max = 0;
ef6e048a 175 break;
f8cc4ae8 176 }
abb6f657
CB
177
178 /* Receive the first response including file descriptors if any. */
d17c815d 179 ret = lxc_abstract_unix_recv_fds(sock, fds, rsp, sizeof(*rsp));
23a917e5 180 if (ret < 0)
1454e5d9 181 return syserrno(ret, "Failed to receive response for command \"%s\"", cur_cmdstr);
00df5330 182
abb6f657
CB
183 /*
184 * Verify that we actually received any file descriptors if the command
185 * expects to do so.
186 */
00df5330 187 if (fds->fd_count_max == 0) {
abb6f657 188 WARN("Command \"%s\" received response", cur_cmdstr);
00df5330 189 } else if (fds->fd_count_ret == 0) {
abb6f657 190 TRACE("Command \"%s\" received response without any of the expected %u file descriptors", cur_cmdstr, fds->fd_count_max);
00df5330 191 fret = -EBADF;
abb6f657
CB
192 } else {
193 TRACE("Command \"%s\" received response with %u of %u expected file descriptors", cur_cmdstr, fds->fd_count_ret, fds->fd_count_max);
00df5330 194 }
ef6e34ee 195
abb6f657
CB
196 /*
197 * Ensure that no excessive data is sent unless someone retrieves the
198 * console ringbuffer.
199 */
200 if ((rsp->datalen > LXC_CMD_DATA_MAX) &&
201 (cur_cmd != LXC_CMD_CONSOLE_LOG))
202 return syserrno_set(fret ?: -E2BIG, "Response data for command \"%s\" is too long: %d bytes > %d",
203 cur_cmdstr, rsp->datalen, LXC_CMD_DATA_MAX);
ef6e34ee 204
abb6f657
CB
205 /*
206 * Prepare buffer for any command that expects to receive additional
207 * data. Note that some don't want any additional data.
208 */
1454e5d9 209 switch (cur_cmd) {
abb6f657 210 case LXC_CMD_GET_CGROUP2_FD: /* no data */
c206ac24 211 __fallthrough;
abb6f657 212 case LXC_CMD_GET_LIMIT_CGROUP2_FD: /* no data */
2092492c 213 __fallthrough;
abb6f657 214 case LXC_CMD_GET_INIT_PIDFD: /* no data */
2092492c 215 __fallthrough;
abb6f657 216 case LXC_CMD_GET_DEVPTS_FD: /* no data */
2092492c 217 __fallthrough;
abb6f657
CB
218 case LXC_CMD_GET_SECCOMP_NOTIFY_FD: /* no data */
219 if (!fret)
220 rsp->data = INT_TO_PTR(move_fd(fds->fd[0]));
221
222 /* Return for any command that doesn't expect additional data. */
223 return log_debug(fret ?: ret, "Finished processing \"%s\" with file descriptor %d", cur_cmdstr, PTR_TO_INT(rsp->data));
224 case LXC_CMD_GET_CGROUP_FD: /* data */
2092492c 225 __fallthrough;
abb6f657
CB
226 case LXC_CMD_GET_LIMIT_CGROUP_FD: /* data */
227 if (rsp->datalen > sizeof(struct cgroup_fd))
1454e5d9 228 return syserrno_set(fret ?: -EINVAL, "Invalid response size from server for \"%s\"", cur_cmdstr);
ef6e048a
CB
229
230 /* Don't pointlessly allocate. */
231 rsp->data = (void *)cmd->req.data;
2092492c 232 break;
abb6f657
CB
233 case LXC_CMD_GET_CGROUP_CTX: /* data */
234 if (rsp->datalen > sizeof(struct cgroup_ctx))
235 return syserrno_set(fret ?: -EINVAL, "Invalid response size from server for \"%s\"", cur_cmdstr);
236
237 /* Don't pointlessly allocate. */
238 rsp->data = (void *)cmd->req.data;
2092492c 239 break;
7e85a2c4 240 case LXC_CMD_GET_TTY_FD: /* data */
abb6f657
CB
241 /*
242 * recv() returns 0 bytes when a tty cannot be allocated,
243 * rsp->ret is < 0 when the peer permission check failed
244 */
245 if (ret == 0 || rsp->ret < 0)
246 return 0;
21405769 247
7e85a2c4 248 __private_ptr = malloc(sizeof(struct lxc_cmd_tty_rsp_data));
abb6f657
CB
249 if (!__private_ptr)
250 return syserrno_set(fret ?: -ENOMEM, "Failed to receive response for command \"%s\"", cur_cmdstr);
7e85a2c4 251 data_console = (struct lxc_cmd_tty_rsp_data *)__private_ptr;
abb6f657
CB
252 data_console->ptxfd = move_fd(fds->fd[0]);
253 data_console->ttynum = PTR_TO_INT(rsp->data);
23a917e5 254
abb6f657
CB
255 rsp->datalen = 0;
256 rsp->data = data_console;
257 break;
258 case LXC_CMD_CONSOLE_LOG: /* data */
259 __private_ptr = zalloc(rsp->datalen + 1);
260 rsp->data = __private_ptr;
261 break;
262 default: /* catch any additional command */
263 if (rsp->datalen > 0) {
264 __private_ptr = zalloc(rsp->datalen);
265 rsp->data = __private_ptr;
266 }
267 break;
268 }
ef6e34ee 269
abb6f657
CB
270 if (rsp->datalen == 0) {
271 DEBUG("Command \"%s\" requested no additional data", cur_cmdstr);
272 /*
7e85a2c4
CB
273 * Note that LXC_CMD_GET_TTY_FD historically allocates memory
274 * to return info to the caller. That's why we jump to no_data
275 * so we ensure that the allocated data is wiped if we return
abb6f657
CB
276 * early here.
277 */
278 goto no_data;
279 }
280
281 /*
282 * All commands ending up here expect data so rsp->data must be valid.
283 * Either static or allocated memory.
284 */
23a917e5 285 if (!rsp->data)
abb6f657 286 return syserrno_set(fret ?: -ENOMEM, "Failed to prepare response buffer for command \"%s\"", cur_cmdstr);
fe84a562 287
2a850b2c 288 ret = lxc_recv_nointr(sock, rsp->data, rsp->datalen, 0);
23a917e5 289 if (ret != rsp->datalen)
abb6f657 290 return syserrno(-errno, "Failed to receive response data for command \"%s\": %d != %d", cur_cmdstr, ret, rsp->datalen);
ef6e048a 291
abb6f657
CB
292 switch (cur_cmd) {
293 case LXC_CMD_GET_CGROUP_CTX:
294 if (!fret)
295 ret = __transfer_cgroup_ctx_fds(fds, rsp->data);
296 /* Make sure any received fds are wiped by us. */
297 break;
298 case LXC_CMD_GET_CGROUP_FD:
299 __fallthrough;
300 case LXC_CMD_GET_LIMIT_CGROUP_FD:
301 if (!fret)
302 ret = __transfer_cgroup_fd(fds, rsp->data);
303 /* Make sure any received fds are wiped by us. */
304 break;
ef6e048a 305 }
724e753c 306
abb6f657
CB
307no_data:
308 if (!fret && ret >= 0)
309 move_ptr(__private_ptr);
310
00df5330 311 return fret ?: ret;
724e753c
MN
312}
313
ef6e34ee
DE
314/*
315 * lxc_cmd_rsp_send: Send a command response
316 *
317 * @fd : file descriptor of socket to send response on
318 * @rsp : response to send
319 *
320 * Returns 0 on success, < 0 on failure
321 */
4b5f4bdc 322static int __lxc_cmd_rsp_send(int fd, struct lxc_cmd_rsp *rsp)
ef6e34ee 323{
fe84a562 324 ssize_t ret;
ef6e34ee 325
7fbb15ec 326 ret = lxc_send_nointr(fd, rsp, sizeof(*rsp), MSG_NOSIGNAL);
6c6497ea 327 if (ret < 0 || (size_t)ret != sizeof(*rsp))
4b5f4bdc 328 return syserrno(-errno, "Failed to send command response %zd", ret);
ef6e34ee 329
a674dfe1 330 if (!rsp->data || rsp->datalen <= 0)
fe84a562
CB
331 return 0;
332
7fbb15ec 333 ret = lxc_send_nointr(fd, rsp->data, rsp->datalen, MSG_NOSIGNAL);
6c6497ea 334 if (ret < 0 || ret != (ssize_t)rsp->datalen)
4b5f4bdc 335 return syswarn(-errno, "Failed to send command response %zd", ret);
fe84a562 336
ef6e34ee
DE
337 return 0;
338}
339
4b5f4bdc
CB
340static inline int lxc_cmd_rsp_send_reap(int fd, struct lxc_cmd_rsp *rsp)
341{
342 int ret;
343
344 ret = __lxc_cmd_rsp_send(fd, rsp);
345 if (ret < 0)
346 return ret;
347
348 return LXC_CMD_REAP_CLIENT_FD;
349}
350
254a22e1
CB
351static inline int lxc_cmd_rsp_send_keep(int fd, struct lxc_cmd_rsp *rsp)
352{
353 int ret;
354
355 ret = __lxc_cmd_rsp_send(fd, rsp);
356 if (ret < 0)
357 return ret;
358
359 return 0;
360}
361
c2f40088
CB
362static inline int rsp_one_fd(int fd, int fd_send, struct lxc_cmd_rsp *rsp)
363{
124b60ec 364 ssize_t ret;
c2f40088
CB
365
366 ret = lxc_abstract_unix_send_fds(fd, &fd_send, 1, rsp, sizeof(*rsp));
367 if (ret < 0)
368 return ret;
369
124b60ec
CB
370 if (rsp->data && rsp->datalen > 0) {
371 ret = lxc_send_nointr(fd, rsp->data, rsp->datalen, MSG_NOSIGNAL);
372 if (ret < 0 || ret != (ssize_t)rsp->datalen)
373 return syswarn(-errno, "Failed to send command response %zd", ret);
374 }
375
c2f40088
CB
376 return LXC_CMD_REAP_CLIENT_FD;
377}
378
e848413e
CB
379__access_r(3, 2) static int rsp_many_fds(int fd, __u32 fds_len,
380 const __s32 fds[static 2],
381 struct lxc_cmd_rsp *rsp)
9c3eb8d5 382{
ef6e048a
CB
383 ssize_t ret;
384
385 if (fds_len > KERNEL_SCM_MAX_FD) {
386 rsp->ret = -E2BIG;
387 return lxc_cmd_rsp_send_reap(fd, rsp);
388 } else if (fds_len == 0) {
389 rsp->ret = -ENOENT;
390 return lxc_cmd_rsp_send_reap(fd, rsp);
391 }
9c3eb8d5 392
ef6e048a 393 ret = lxc_abstract_unix_send_fds(fd, fds, fds_len, rsp, sizeof(*rsp));
9c3eb8d5
CB
394 if (ret < 0)
395 return ret;
396
ef6e048a
CB
397 if (rsp->data && rsp->datalen > 0) {
398 ret = lxc_send_nointr(fd, rsp->data, rsp->datalen, MSG_NOSIGNAL);
399 if (ret < 0 || ret != (ssize_t)rsp->datalen)
400 return syswarn(-errno, "Failed to send command response %zd", ret);
401 }
402
9c3eb8d5
CB
403 return LXC_CMD_REAP_CLIENT_FD;
404}
405
c01c2be6 406static int lxc_cmd_send(const char *name, struct lxc_cmd_rr *cmd,
fe84a562 407 const char *lxcpath, const char *hashed_sock_name)
c01c2be6 408{
f62cf1d4 409 __do_close int client_fd = -EBADF;
fe84a562 410 ssize_t ret = -1;
c01c2be6 411
9dfa4041 412 client_fd = lxc_cmd_connect(name, lxcpath, hashed_sock_name, "command");
2a850b2c 413 if (client_fd < 0)
fe84a562 414 return -1;
c01c2be6 415
fe84a562
CB
416 ret = lxc_abstract_unix_send_credential(client_fd, &cmd->req,
417 sizeof(cmd->req));
2a850b2c 418 if (ret < 0 || (size_t)ret != sizeof(cmd->req))
e96f9291 419 return -1;
9044b79e 420
cdb2a47f
CB
421 if (cmd->req.cmd == LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER) {
422 int notify_fd = PTR_TO_INT(cmd->req.data);
423 ret = lxc_abstract_unix_send_fds(client_fd, &notify_fd, 1, NULL, 0);
424 if (ret <= 0)
425 return -1;
426 } else {
427 if (cmd->req.datalen <= 0)
428 return move_fd(client_fd);
c01c2be6 429
cdb2a47f
CB
430 errno = EMSGSIZE;
431 ret = lxc_send_nointr(client_fd, (void *)cmd->req.data,
432 cmd->req.datalen, MSG_NOSIGNAL);
433 if (ret < 0 || ret != (ssize_t)cmd->req.datalen)
434 return -1;
435 }
c01c2be6 436
240fecd0 437 return move_fd(client_fd);
c01c2be6
CB
438}
439
ef6e34ee
DE
440/*
441 * lxc_cmd: Connect to the specified running container, send it a command
442 * request and collect the response
443 *
444 * @name : name of container to connect to
1e8cfdf6 445 * @cmd : command with initialized request to send
ef6e34ee
DE
446 * @stopped : output indicator if the container was not running
447 * @lxcpath : the lxcpath in which the container is running
448 *
449 * Returns the size of the response message on success, < 0 on failure
450 *
7e85a2c4
CB
451 * Note that there is a special case for LXC_CMD_GET_TTY_FD. For this command
452 * the fd cannot be closed because it is used as a placeholder to indicate that
453 * a particular tty slot is in use. The fd is also used as a signal to the
454 * container that when the caller dies or closes the fd, the container will
455 * notice the fd on its side of the socket in its mainloop select and then free
456 * the slot with lxc_cmd_fd_cleanup(). The socket fd will be returned in the
457 * cmd response structure.
ef6e34ee 458 */
8a598112 459static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, bool *stopped,
88556fd7 460 const char *lxcpath, const char *hashed_sock_name)
724e753c 461{
f62cf1d4 462 __do_close int client_fd = -EBADF;
fe84a562 463 int ret = -1;
dbc9832d
CB
464 bool stay_connected = false;
465
7e85a2c4 466 if (cmd->req.cmd == LXC_CMD_GET_TTY_FD ||
54446942 467 cmd->req.cmd == LXC_CMD_ADD_STATE_CLIENT)
dbc9832d 468 stay_connected = true;
724e753c 469
0ecf64b5
SH
470 *stopped = 0;
471
c01c2be6
CB
472 client_fd = lxc_cmd_send(name, cmd, lxcpath, hashed_sock_name);
473 if (client_fd < 0) {
0437eac5 474 if (IN_SET(errno, ECONNREFUSED, EPIPE))
ef6e34ee 475 *stopped = 1;
3f903c04 476
6c6497ea
CB
477 return log_trace_errno(-1, errno, "Command \"%s\" failed to connect command socket",
478 lxc_cmd_str(cmd->req.cmd));
724e753c
MN
479 }
480
c01c2be6 481 ret = lxc_cmd_rsp_recv(client_fd, cmd);
2a850b2c 482 if (ret < 0 && errno == ECONNRESET)
6b7f85cb 483 *stopped = 1;
6a93ae77 484
ea2a070b
CB
485 TRACE("Opened new command socket connection fd %d for command \"%s\"",
486 client_fd, lxc_cmd_str(cmd->req.cmd));
487
c34ff119 488 if (stay_connected && ret > 0)
240fecd0 489 cmd->rsp.ret = move_fd(client_fd);
43eb6f29 490
1362f2eb 491 return ret;
724e753c
MN
492}
493
b494d2dd
SH
494int lxc_try_cmd(const char *name, const char *lxcpath)
495{
8a598112 496 bool stopped = false;
8a598112 497 int ret;
38d14ebd
CB
498 struct lxc_cmd_rr cmd;
499
500 lxc_cmd_init(&cmd, LXC_CMD_GET_INIT_PID);
b494d2dd 501
88556fd7 502 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
b494d2dd
SH
503 if (stopped)
504 return 0;
505 if (ret > 0 && cmd.rsp.ret < 0) {
506 errno = cmd.rsp.ret;
507 return -1;
508 }
509 if (ret > 0)
510 return 0;
511
8a598112
CB
512 /*
513 * At this point we weren't denied access, and the container *was*
fe84a562
CB
514 * started. There was some inexplicable error in the protocol. I'm not
515 * clear on whether we should return -1 here, but we didn't receive a
516 * -EACCES, so technically it's not that we're not allowed to control
517 * the container - it's just not behaving.
b494d2dd
SH
518 */
519 return 0;
520}
521
e6bc68d6
WB
522/*
523 * Validate that the input is a proper string parameter. If not,
524 * send an EINVAL response and return -1.
525 *
526 * Precondition: there is non-zero-length data available.
527 */
528static int validate_string_request(int fd, const struct lxc_cmd_req *req)
529{
e6bc68d6
WB
530 size_t maxlen = req->datalen - 1;
531 const char *data = req->data;
532
533 if (data[maxlen] == 0 && strnlen(data, maxlen) == maxlen)
534 return 0;
535
536 struct lxc_cmd_rsp rsp = {
da63ea6b
CB
537 .ret = -EINVAL,
538 .datalen = 0,
539 .data = NULL,
e6bc68d6
WB
540 };
541
4b5f4bdc 542 return lxc_cmd_rsp_send_reap(fd, &rsp);
e6bc68d6
WB
543}
544
cc4c0832 545/* Implementations of the commands and their callbacks */
ef6e34ee
DE
546
547/*
548 * lxc_cmd_get_init_pid: Get pid of the container's init process
549 *
550 * @name : name of container to connect to
551 * @lxcpath : the lxcpath in which the container is running
552 *
553 * Returns the pid on success, < 0 on failure
554 */
555pid_t lxc_cmd_get_init_pid(const char *name, const char *lxcpath)
43eb6f29 556{
8a598112 557 bool stopped = false;
565eb353 558 pid_t pid = -1;
ef6e34ee 559 struct lxc_cmd_rr cmd = {
e8cd1208
CB
560 .req = {
561 .cmd = LXC_CMD_GET_INIT_PID
562 },
563 .rsp = {
565eb353 564 .data = PID_TO_PTR(pid)
e8cd1208 565 }
ef6e34ee 566 };
8a598112 567 int ret;
ef6e34ee 568
88556fd7 569 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ef6e34ee 570 if (ret < 0)
8ed8a626 571 return -1;
ef6e34ee 572
565eb353 573 pid = PTR_TO_PID(cmd.rsp.data);
9234406b
CB
574 if (pid < 0)
575 return -1;
576
8a598112
CB
577 /*
578 * We need to assume that pid_t can actually hold any pid given to us
9234406b
CB
579 * by the kernel. If it can't it's a libc bug.
580 */
581 return (pid_t)pid;
43eb6f29
DL
582}
583
ef6e34ee 584static int lxc_cmd_get_init_pid_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
585 struct lxc_handler *handler,
586 struct lxc_epoll_descr *descr)
43eb6f29 587{
9234406b 588 struct lxc_cmd_rsp rsp = {
4b5f4bdc 589 .data = PID_TO_PTR(handler->pid),
9234406b 590 };
ef6e34ee 591
4b5f4bdc 592 return lxc_cmd_rsp_send_reap(fd, &rsp);
43eb6f29
DL
593}
594
746aab51
CB
595int lxc_cmd_get_init_pidfd(const char *name, const char *lxcpath)
596{
8a598112 597 bool stopped = false;
746aab51
CB
598 struct lxc_cmd_rr cmd = {
599 .req = {
600 .cmd = LXC_CMD_GET_INIT_PIDFD,
601 },
8a95cd82
CB
602 .rsp = {
603 .data = INT_TO_PTR(-EBADF),
604 .ret = ENOSYS,
605 },
746aab51 606 };
8a598112 607 int pidfd, ret;
746aab51
CB
608
609 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
610 if (ret < 0)
611 return log_debug_errno(-1, errno, "Failed to process init pidfd command");
612
613 if (cmd.rsp.ret < 0)
8a95cd82 614 return syserrno_set(cmd.rsp.ret, "Failed to receive init pidfd");
746aab51 615
8a95cd82
CB
616 pidfd = PTR_TO_INT(cmd.rsp.data);
617 if (pidfd < 0)
618 return syserrno_set(pidfd, "Failed to receive init pidfd");
619
620 return pidfd;
746aab51
CB
621}
622
623static int lxc_cmd_get_init_pidfd_callback(int fd, struct lxc_cmd_req *req,
624 struct lxc_handler *handler,
625 struct lxc_epoll_descr *descr)
626{
627 struct lxc_cmd_rsp rsp = {
4b5f4bdc 628 .ret = -EBADF,
746aab51 629 };
746aab51
CB
630
631 if (handler->pidfd < 0)
4b5f4bdc
CB
632 return lxc_cmd_rsp_send_reap(fd, &rsp);
633
634 rsp.ret = 0;
c2f40088 635 return rsp_one_fd(fd, handler->pidfd, &rsp);
746aab51
CB
636}
637
f797f05e
CB
638int lxc_cmd_get_devpts_fd(const char *name, const char *lxcpath)
639{
8a598112 640 bool stopped = false;
f797f05e
CB
641 struct lxc_cmd_rr cmd = {
642 .req = {
643 .cmd = LXC_CMD_GET_DEVPTS_FD,
644 },
645 };
8a598112 646 int ret;
f797f05e
CB
647
648 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
649 if (ret < 0)
650 return log_debug_errno(-1, errno, "Failed to process devpts fd command");
651
652 if (cmd.rsp.ret < 0)
653 return log_debug_errno(-EBADF, errno, "Failed to receive devpts fd");
654
655 return PTR_TO_INT(cmd.rsp.data);
656}
657
658static int lxc_cmd_get_devpts_fd_callback(int fd, struct lxc_cmd_req *req,
659 struct lxc_handler *handler,
660 struct lxc_epoll_descr *descr)
661{
662 struct lxc_cmd_rsp rsp = {
4b5f4bdc 663 .ret = -EBADF,
f797f05e 664 };
f797f05e 665
4b5f4bdc
CB
666 if (!handler->conf || handler->conf->devpts_fd < 0)
667 return lxc_cmd_rsp_send_reap(fd, &rsp);
668
669 rsp.ret = 0;
c2f40088 670 return rsp_one_fd(fd, handler->conf->devpts_fd, &rsp);
f797f05e
CB
671}
672
21405769
CB
673int lxc_cmd_get_seccomp_notify_fd(const char *name, const char *lxcpath)
674{
a342b11f 675#ifdef HAVE_SECCOMP_NOTIFY
8a598112 676 bool stopped = false;
21405769
CB
677 struct lxc_cmd_rr cmd = {
678 .req = {
679 .cmd = LXC_CMD_GET_SECCOMP_NOTIFY_FD,
680 },
681 };
8a598112 682 int ret;
21405769
CB
683
684 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
685 if (ret < 0)
686 return log_debug_errno(-1, errno, "Failed to process seccomp notify fd command");
687
688 if (cmd.rsp.ret < 0)
689 return log_debug_errno(-EBADF, errno, "Failed to receive seccomp notify fd");
690
691 return PTR_TO_INT(cmd.rsp.data);
692#else
693 return ret_errno(EOPNOTSUPP);
694#endif
695}
696
697static int lxc_cmd_get_seccomp_notify_fd_callback(int fd, struct lxc_cmd_req *req,
698 struct lxc_handler *handler,
699 struct lxc_epoll_descr *descr)
700{
a342b11f 701#ifdef HAVE_SECCOMP_NOTIFY
21405769 702 struct lxc_cmd_rsp rsp = {
4b5f4bdc 703 .ret = -EBADF,
21405769 704 };
21405769
CB
705
706 if (!handler->conf || handler->conf->seccomp.notifier.notify_fd < 0)
4b5f4bdc
CB
707 return lxc_cmd_rsp_send_reap(fd, &rsp);
708
709 rsp.ret = 0;
c2f40088 710 return rsp_one_fd(fd, handler->conf->seccomp.notifier.notify_fd, &rsp);
21405769 711#else
4b5f4bdc 712 return syserrno_set(-EOPNOTSUPP, "Seccomp notifier not supported");
21405769
CB
713#endif
714}
715
ef6e048a 716int lxc_cmd_get_cgroup_ctx(const char *name, const char *lxcpath,
ac5eacc6 717 size_t size_ret_ctx, struct cgroup_ctx *ret_ctx)
9c3eb8d5 718{
8a598112 719 bool stopped = false;
9c3eb8d5
CB
720 struct lxc_cmd_rr cmd = {
721 .req = {
ef6e048a
CB
722 .cmd = LXC_CMD_GET_CGROUP_CTX,
723 .datalen = size_ret_ctx,
724 .data = ret_ctx,
9c3eb8d5 725 },
d3be623e
CB
726 .rsp = {
727 .ret = -ENOSYS,
728 },
9c3eb8d5 729 };
8a598112 730 int ret;
9c3eb8d5 731
9c3eb8d5
CB
732 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
733 if (ret < 0)
d3be623e 734 return log_debug_errno(-1, errno, "Failed to process cgroup context command");
9c3eb8d5
CB
735
736 if (cmd.rsp.ret < 0)
737 return log_debug_errno(-EBADF, errno, "Failed to receive cgroup fds");
738
739 return 0;
740}
741
ef6e048a
CB
742static int lxc_cmd_get_cgroup_ctx_callback(int fd, struct lxc_cmd_req *req,
743 struct lxc_handler *handler,
744 struct lxc_epoll_descr *descr)
9c3eb8d5 745{
f8cc4ae8 746 struct lxc_cmd_rsp rsp = {
ef6e048a 747 .ret = EINVAL,
f8cc4ae8 748 };
9c3eb8d5 749 struct cgroup_ops *cgroup_ops = handler->cgroup_ops;
ef6e048a 750 struct cgroup_ctx ctx_server = {};
f8cc4ae8
CB
751 int ret;
752
ef6e048a
CB
753 ret = copy_struct_from_client(sizeof(struct cgroup_ctx), &ctx_server,
754 req->datalen, req->data);
f8cc4ae8 755 if (ret < 0)
ef6e048a
CB
756 return lxc_cmd_rsp_send_reap(fd, &rsp);
757
758 ret = prepare_cgroup_ctx(cgroup_ops, &ctx_server);
759 if (ret < 0) {
760 rsp.ret = ret;
761 return lxc_cmd_rsp_send_reap(fd, &rsp);
762 }
9c3eb8d5 763
28c738eb 764 rsp.ret = 0;
ef6e048a
CB
765 rsp.data = &ctx_server;
766 rsp.datalen = min(sizeof(struct cgroup_ctx), (size_t)req->datalen);
767 return rsp_many_fds(fd, ctx_server.fd_len, ctx_server.fd, &rsp);
9c3eb8d5
CB
768}
769
ef6e34ee
DE
770/*
771 * lxc_cmd_get_clone_flags: Get clone flags container was spawned with
772 *
773 * @name : name of container to connect to
774 * @lxcpath : the lxcpath in which the container is running
775 *
776 * Returns the clone flags on success, < 0 on failure
777 */
778int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath)
779{
8a598112 780 bool stopped = false;
ef6e34ee 781 struct lxc_cmd_rr cmd = {
6c6497ea
CB
782 .req = {
783 .cmd = LXC_CMD_GET_CLONE_FLAGS,
784 },
ef6e34ee 785 };
8a598112 786 int ret;
ef6e34ee 787
88556fd7 788 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ef6e34ee
DE
789 if (ret < 0)
790 return ret;
43eb6f29 791
ef6e34ee
DE
792 return PTR_TO_INT(cmd.rsp.data);
793}
794
795static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
796 struct lxc_handler *handler,
797 struct lxc_epoll_descr *descr)
26b2d152 798{
6c6497ea
CB
799 struct lxc_cmd_rsp rsp = {
800 .data = INT_TO_PTR(handler->ns_clone_flags),
801 };
ef6e34ee 802
4b5f4bdc 803 return lxc_cmd_rsp_send_reap(fd, &rsp);
ef6e34ee
DE
804}
805
a900cbaf
WB
806static char *lxc_cmd_get_cgroup_path_do(const char *name, const char *lxcpath,
807 const char *subsystem,
808 lxc_cmd_t command)
ef6e34ee 809{
8a598112 810 bool stopped = false;
ef6e34ee 811 struct lxc_cmd_rr cmd = {
b98f7d6e 812 .req = {
a900cbaf 813 .cmd = command,
b98f7d6e 814 .data = subsystem,
c2aed66d 815 .datalen = 0,
b98f7d6e 816 },
26b2d152 817 };
8a598112 818 int ret;
26b2d152 819
c2aed66d
CB
820 cmd.req.data = subsystem;
821 cmd.req.datalen = 0;
822 if (subsystem)
823 cmd.req.datalen = strlen(subsystem) + 1;
824
88556fd7 825 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
fe84a562 826 if (ret < 0)
ef6e34ee
DE
827 return NULL;
828
400d579e 829 if (ret == 0) {
a9b642ee 830 if (command == LXC_CMD_GET_LIMIT_CGROUP) {
400d579e
WB
831 /*
832 * This may indicate that the container was started
833 * under an ealier version before
834 * `cgroup_advanced_isolation` as implemented, there
835 * it sees an unknown command and just closes the
836 * socket, sending us an EOF.
837 */
838 return lxc_cmd_get_cgroup_path_do(name, lxcpath,
839 subsystem,
840 LXC_CMD_GET_CGROUP);
841 }
ef6e34ee 842 return NULL;
400d579e 843 }
ef6e34ee 844
fe84a562 845 if (cmd.rsp.ret < 0 || cmd.rsp.datalen < 0)
ef6e34ee 846 return NULL;
3f903c04 847
ef6e34ee
DE
848 return cmd.rsp.data;
849}
850
a900cbaf
WB
851/*
852 * lxc_cmd_get_cgroup_path: Calculate a container's cgroup path for a
853 * particular subsystem. This is the cgroup path relative to the root
854 * of the cgroup filesystem.
855 *
856 * @name : name of container to connect to
857 * @lxcpath : the lxcpath in which the container is running
858 * @subsystem : the subsystem being asked about
859 *
860 * Returns the path on success, NULL on failure. The caller must free() the
861 * returned path.
862 */
863char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
864 const char *subsystem)
865{
866 return lxc_cmd_get_cgroup_path_do(name, lxcpath, subsystem,
867 LXC_CMD_GET_CGROUP);
868}
869
870/*
a9b642ee 871 * lxc_cmd_get_limit_cgroup_path: Calculate a container's limit cgroup
a900cbaf
WB
872 * path for a particular subsystem. This is the cgroup path relative to the
873 * root of the cgroup filesystem. This may be the same as the path returned by
a9b642ee 874 * lxc_cmd_get_cgroup_path if the container doesn't have a limit path prefix
a900cbaf
WB
875 * set.
876 *
877 * @name : name of container to connect to
878 * @lxcpath : the lxcpath in which the container is running
879 * @subsystem : the subsystem being asked about
880 *
881 * Returns the path on success, NULL on failure. The caller must free() the
882 * returned path.
883 */
a9b642ee
CB
884char *lxc_cmd_get_limit_cgroup_path(const char *name, const char *lxcpath,
885 const char *subsystem)
a900cbaf
WB
886{
887 return lxc_cmd_get_cgroup_path_do(name, lxcpath, subsystem,
a9b642ee 888 LXC_CMD_GET_LIMIT_CGROUP);
a900cbaf
WB
889}
890
891static int lxc_cmd_get_cgroup_callback_do(int fd, struct lxc_cmd_req *req,
892 struct lxc_handler *handler,
893 struct lxc_epoll_descr *descr,
894 bool limiting_cgroup)
ef6e34ee 895{
ea2a070b 896 int ret;
4fb3cba5 897 const char *path;
a900cbaf 898 const void *reqdata;
fe84a562 899 struct lxc_cmd_rsp rsp;
2202afc9 900 struct cgroup_ops *cgroup_ops = handler->cgroup_ops;
a900cbaf 901 const char *(*get_fn)(struct cgroup_ops *ops, const char *controller);
b98f7d6e 902
e6bc68d6
WB
903 if (req->datalen > 0) {
904 ret = validate_string_request(fd, req);
905 if (ret != 0)
906 return ret;
a900cbaf 907 reqdata = req->data;
e6bc68d6 908 } else {
a900cbaf 909 reqdata = NULL;
e6bc68d6 910 }
a900cbaf 911
a9b642ee 912 get_fn = (limiting_cgroup ? cgroup_ops->get_limit_cgroup
29d652a9 913 : cgroup_ops->get_cgroup);
a900cbaf
WB
914
915 path = get_fn(cgroup_ops, reqdata);
916
b98f7d6e
SH
917 if (!path)
918 return -1;
fe84a562 919
4f17323e 920 rsp.ret = 0;
fe84a562
CB
921 rsp.datalen = strlen(path) + 1;
922 rsp.data = (char *)path;
ef6e34ee 923
4b5f4bdc 924 return lxc_cmd_rsp_send_reap(fd, &rsp);
ef6e34ee
DE
925}
926
a900cbaf
WB
927static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
928 struct lxc_handler *handler,
929 struct lxc_epoll_descr *descr)
930{
931 return lxc_cmd_get_cgroup_callback_do(fd, req, handler, descr, false);
932}
933
a9b642ee
CB
934static int lxc_cmd_get_limit_cgroup_callback(int fd, struct lxc_cmd_req *req,
935 struct lxc_handler *handler,
936 struct lxc_epoll_descr *descr)
a900cbaf
WB
937{
938 return lxc_cmd_get_cgroup_callback_do(fd, req, handler, descr, true);
939}
940
ef6e34ee
DE
941/*
942 * lxc_cmd_get_config_item: Get config item the running container
943 *
944 * @name : name of container to connect to
7fa3f2e9 945 * @item : the configuration item to retrieve (ex: lxc.net.0.veth.pair)
ef6e34ee
DE
946 * @lxcpath : the lxcpath in which the container is running
947 *
948 * Returns the item on success, NULL on failure. The caller must free() the
949 * returned item.
950 */
951char *lxc_cmd_get_config_item(const char *name, const char *item,
952 const char *lxcpath)
953{
8a598112 954 bool stopped = false;
ef6e34ee
DE
955 struct lxc_cmd_rr cmd = {
956 .req = { .cmd = LXC_CMD_GET_CONFIG_ITEM,
957 .data = item,
fe84a562 958 .datalen = strlen(item) + 1,
ef6e34ee
DE
959 },
960 };
8a598112 961 int ret;
ef6e34ee 962
88556fd7 963 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ef6e34ee
DE
964 if (ret < 0)
965 return NULL;
966
967 if (cmd.rsp.ret == 0)
968 return cmd.rsp.data;
fe84a562 969
ef6e34ee
DE
970 return NULL;
971}
972
973static int lxc_cmd_get_config_item_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
974 struct lxc_handler *handler,
975 struct lxc_epoll_descr *descr)
ef6e34ee 976{
5265a60c 977 __do_free char *cidata = NULL;
ef6e34ee 978 int cilen;
30aec088 979 struct lxc_config_t *item;
fe84a562 980 struct lxc_cmd_rsp rsp;
ef6e34ee
DE
981
982 memset(&rsp, 0, sizeof(rsp));
300df83e 983 item = lxc_get_config(req->data);
30aec088
CB
984 if (!item)
985 goto err1;
fe84a562 986
cccd2219 987 cilen = item->get(req->data, NULL, 0, handler->conf, NULL);
ef6e34ee
DE
988 if (cilen <= 0)
989 goto err1;
990
5265a60c 991 cidata = must_realloc(NULL, cilen + 1);
cccd2219 992 if (item->get(req->data, cidata, cilen + 1, handler->conf, NULL) != cilen)
ef6e34ee 993 goto err1;
fe84a562 994
ef6e34ee
DE
995 cidata[cilen] = '\0';
996 rsp.data = cidata;
997 rsp.datalen = cilen + 1;
998 rsp.ret = 0;
999 goto out;
1000
1001err1:
1002 rsp.ret = -1;
1003out:
4b5f4bdc 1004 return lxc_cmd_rsp_send_reap(fd, &rsp);
ef6e34ee
DE
1005}
1006
1007/*
1008 * lxc_cmd_get_state: Get current state of the container
1009 *
1010 * @name : name of container to connect to
1011 * @lxcpath : the lxcpath in which the container is running
1012 *
1013 * Returns the state on success, < 0 on failure
1014 */
dbc9832d 1015int lxc_cmd_get_state(const char *name, const char *lxcpath)
ef6e34ee 1016{
8a598112 1017 bool stopped = false;
ef6e34ee 1018 struct lxc_cmd_rr cmd = {
6c6497ea
CB
1019 .req = {
1020 .cmd = LXC_CMD_GET_STATE,
1021 },
ef6e34ee 1022 };
8a598112 1023 int ret;
26b2d152 1024
88556fd7 1025 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ebdd307d 1026 if (ret < 0 && stopped)
ef6e34ee
DE
1027 return STOPPED;
1028
1029 if (ret < 0)
26b2d152 1030 return -1;
26b2d152 1031
6c6497ea
CB
1032 if (!ret)
1033 return log_warn(-1, "Container \"%s\" has stopped before sending its state", name);
fe84a562 1034
6c6497ea
CB
1035 return log_debug(PTR_TO_INT(cmd.rsp.data),
1036 "Container \"%s\" is in \"%s\" state", name,
1037 lxc_state2str(PTR_TO_INT(cmd.rsp.data)));
ef6e34ee
DE
1038}
1039
1040static int lxc_cmd_get_state_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1041 struct lxc_handler *handler,
1042 struct lxc_epoll_descr *descr)
ef6e34ee 1043{
6c6497ea
CB
1044 struct lxc_cmd_rsp rsp = {
1045 .data = INT_TO_PTR(handler->state),
1046 };
ef6e34ee 1047
4b5f4bdc 1048 return lxc_cmd_rsp_send_reap(fd, &rsp);
ef6e34ee
DE
1049}
1050
1051/*
1052 * lxc_cmd_stop: Stop the container previously started with lxc_start. All
1053 * the processes running inside this container will be killed.
1054 *
1055 * @name : name of container to connect to
1056 * @lxcpath : the lxcpath in which the container is running
1057 *
1058 * Returns 0 on success, < 0 on failure
1059 */
1060int lxc_cmd_stop(const char *name, const char *lxcpath)
1061{
8a598112 1062 bool stopped = false;
ef6e34ee 1063 struct lxc_cmd_rr cmd = {
6c6497ea
CB
1064 .req = {
1065 .cmd = LXC_CMD_STOP,
1066 },
ef6e34ee 1067 };
8a598112 1068 int ret;
ef6e34ee 1069
88556fd7 1070 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
26b2d152 1071 if (ret < 0) {
6c6497ea
CB
1072 if (stopped)
1073 return log_info(0, "Container \"%s\" is already stopped", name);
fe84a562 1074
26b2d152
MN
1075 return -1;
1076 }
1077
fe84a562
CB
1078 /* We do not expect any answer, because we wait for the connection to be
1079 * closed.
95d5b147 1080 */
6c6497ea
CB
1081 if (ret > 0)
1082 return log_error_errno(-1, -cmd.rsp.ret, "Failed to stop container \"%s\"", name);
26b2d152 1083
6c6497ea 1084 return log_info(0, "Container \"%s\" has stopped", name);
26b2d152
MN
1085}
1086
ef6e34ee 1087static int lxc_cmd_stop_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1088 struct lxc_handler *handler,
1089 struct lxc_epoll_descr *descr)
d5088cf2 1090{
ef6e34ee 1091 struct lxc_cmd_rsp rsp;
ef6e34ee 1092 int stopsignal = SIGKILL;
2202afc9 1093 struct cgroup_ops *cgroup_ops = handler->cgroup_ops;
ea2a070b 1094 int ret;
ef6e34ee
DE
1095
1096 if (handler->conf->stopsignal)
1097 stopsignal = handler->conf->stopsignal;
1098 memset(&rsp, 0, sizeof(rsp));
9837ee46 1099
8ad4fa68 1100 if (handler->pidfd >= 0)
9837ee46
CB
1101 rsp.ret = lxc_raw_pidfd_send_signal(handler->pidfd, stopsignal, NULL, 0);
1102 else
1103 rsp.ret = kill(handler->pid, stopsignal);
ef6e34ee 1104 if (!rsp.ret) {
9837ee46
CB
1105 if (handler->pidfd >= 0)
1106 TRACE("Sent signal %d to pidfd %d", stopsignal, handler->pidfd);
1107 else
1108 TRACE("Sent signal %d to pidfd %d", stopsignal, handler->pid);
1109
9d47970b 1110 if (pure_unified_layout(cgroup_ops))
c0af7b1c 1111 ret = __cgroup_unfreeze(cgroup_ops->unified->dfd_lim, -1);
9d47970b
CB
1112 else
1113 ret = cgroup_ops->unfreeze(cgroup_ops, -1);
8db8adea
CB
1114 if (ret)
1115 WARN("Failed to unfreeze container \"%s\"", handler->name);
fe84a562 1116
8db8adea 1117 return 0;
018051e3
CB
1118 } else {
1119 rsp.ret = -errno;
ef6e34ee
DE
1120 }
1121
4b5f4bdc 1122 return lxc_cmd_rsp_send_reap(fd, &rsp);
ef6e34ee 1123}
d5088cf2 1124
b5159817 1125/*
2bd158cc 1126 * lxc_cmd_terminal_winch: noop
b5159817
DE
1127 *
1128 * @name : name of container to connect to
1129 * @lxcpath : the lxcpath in which the container is running
1130 *
1131 * Returns 0 on success, < 0 on failure
1132 */
8ccbbf94 1133int lxc_cmd_terminal_winch(const char *name, const char *lxcpath)
b5159817 1134{
b5159817
DE
1135 return 0;
1136}
1137
8ccbbf94 1138static int lxc_cmd_terminal_winch_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1139 struct lxc_handler *handler,
1140 struct lxc_epoll_descr *descr)
b5159817 1141{
2bd158cc 1142 /* should never be called */
6c6497ea 1143 return log_error_errno(-1, ENOSYS, "Called lxc_cmd_terminal_winch_callback()");
b5159817
DE
1144}
1145
ef6e34ee 1146/*
7e85a2c4 1147 * lxc_cmd_get_tty_fd: Open an fd to a tty in the container
ef6e34ee
DE
1148 *
1149 * @name : name of container to connect to
1150 * @ttynum : in: the tty to open or -1 for next available
1151 * : out: the tty allocated
36a94ce8 1152 * @fd : out: file descriptor for ptx side of pty
ef6e34ee
DE
1153 * @lxcpath : the lxcpath in which the container is running
1154 *
0115f8fd 1155 * Returns fd holding tty allocated on success, < 0 on failure
ef6e34ee 1156 */
7e85a2c4 1157int lxc_cmd_get_tty_fd(const char *name, int *ttynum, int *fd, const char *lxcpath)
ef6e34ee 1158{
7e85a2c4 1159 __do_free struct lxc_cmd_tty_rsp_data *rspdata = NULL;
8a598112 1160 bool stopped = false;
ef6e34ee 1161 struct lxc_cmd_rr cmd = {
6c6497ea 1162 .req = {
7e85a2c4 1163 .cmd = LXC_CMD_GET_TTY_FD,
6c6497ea
CB
1164 .data = INT_TO_PTR(*ttynum),
1165 },
ef6e34ee 1166 };
8a598112 1167 int ret;
d5088cf2 1168
88556fd7 1169 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ef6e34ee
DE
1170 if (ret < 0)
1171 return ret;
0115f8fd 1172
8259d86d 1173 rspdata = cmd.rsp.data;
6c6497ea
CB
1174 if (cmd.rsp.ret < 0)
1175 return log_error_errno(-1, -cmd.rsp.ret, "Denied access to tty");
d5088cf2 1176
6c6497ea
CB
1177 if (ret == 0)
1178 return log_error(-1, "tty number %d invalid, busy or all ttys busy", *ttynum);
ef6e34ee 1179
36a94ce8 1180 if (rspdata->ptxfd < 0)
6c6497ea 1181 return log_error(-1, "Unable to allocate fd for tty %d", rspdata->ttynum);
ef6e34ee 1182
fe84a562 1183 ret = cmd.rsp.ret; /* socket fd */
36a94ce8 1184 *fd = rspdata->ptxfd;
ef6e34ee 1185 *ttynum = rspdata->ttynum;
fe84a562 1186
6c6497ea 1187 return log_info(ret, "Alloced fd %d for tty %d via socket %d", *fd, rspdata->ttynum, ret);
ef6e34ee
DE
1188}
1189
7e85a2c4
CB
1190static int lxc_cmd_get_tty_fd_callback(int fd, struct lxc_cmd_req *req,
1191 struct lxc_handler *handler,
1192 struct lxc_epoll_descr *descr)
ef6e34ee 1193{
36a94ce8 1194 int ptxfd, ret;
4b5f4bdc
CB
1195 struct lxc_cmd_rsp rsp = {
1196 .ret = -EBADF,
1197 };
fe84a562 1198 int ttynum = PTR_TO_INT(req->data);
ef6e34ee 1199
36a94ce8
CB
1200 ptxfd = lxc_terminal_allocate(handler->conf, fd, &ttynum);
1201 if (ptxfd < 0)
4b5f4bdc 1202 return lxc_cmd_rsp_send_reap(fd, &rsp);
ef6e34ee 1203
4b5f4bdc 1204 rsp.ret = 0;
ef6e34ee 1205 rsp.data = INT_TO_PTR(ttynum);
36a94ce8 1206 ret = lxc_abstract_unix_send_fds(fd, &ptxfd, 1, &rsp, sizeof(rsp));
fe84a562 1207 if (ret < 0) {
3dfe6f8d 1208 lxc_terminal_free(handler->conf, fd);
4b5f4bdc 1209 return ret;
ef6e34ee
DE
1210 }
1211
4b5f4bdc 1212 return log_debug(0, "Send tty to client");
d5088cf2
CS
1213}
1214
88556fd7
ÇO
1215/*
1216 * lxc_cmd_get_name: Returns the name of the container
1217 *
1218 * @hashed_sock_name: hashed socket name
1219 *
1220 * Returns the name on success, NULL on failure.
1221 */
1222char *lxc_cmd_get_name(const char *hashed_sock_name)
1223{
8a598112 1224 bool stopped = false;
88556fd7 1225 struct lxc_cmd_rr cmd = {
6c6497ea
CB
1226 .req = {
1227 .cmd = LXC_CMD_GET_NAME,
1228 },
88556fd7 1229 };
8a598112 1230 int ret;
88556fd7
ÇO
1231
1232 ret = lxc_cmd(NULL, &cmd, &stopped, NULL, hashed_sock_name);
fe84a562 1233 if (ret < 0)
88556fd7 1234 return NULL;
88556fd7
ÇO
1235
1236 if (cmd.rsp.ret == 0)
1237 return cmd.rsp.data;
fe84a562 1238
88556fd7
ÇO
1239 return NULL;
1240}
1241
1242static int lxc_cmd_get_name_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1243 struct lxc_handler *handler,
1244 struct lxc_epoll_descr *descr)
88556fd7
ÇO
1245{
1246 struct lxc_cmd_rsp rsp;
1247
1248 memset(&rsp, 0, sizeof(rsp));
1249
f0ecc19d 1250 rsp.data = (char *)handler->name;
88556fd7
ÇO
1251 rsp.datalen = strlen(handler->name) + 1;
1252 rsp.ret = 0;
1253
4b5f4bdc 1254 return lxc_cmd_rsp_send_reap(fd, &rsp);
88556fd7
ÇO
1255}
1256
1257/*
1258 * lxc_cmd_get_lxcpath: Returns the lxcpath of the container
1259 *
1260 * @hashed_sock_name: hashed socket name
1261 *
1262 * Returns the lxcpath on success, NULL on failure.
1263 */
1264char *lxc_cmd_get_lxcpath(const char *hashed_sock_name)
1265{
8a598112 1266 bool stopped = false;
88556fd7 1267 struct lxc_cmd_rr cmd = {
6c6497ea
CB
1268 .req = {
1269 .cmd = LXC_CMD_GET_LXCPATH,
1270 },
88556fd7 1271 };
8a598112 1272 int ret;
724e753c 1273
88556fd7 1274 ret = lxc_cmd(NULL, &cmd, &stopped, NULL, hashed_sock_name);
fe84a562 1275 if (ret < 0)
88556fd7 1276 return NULL;
88556fd7
ÇO
1277
1278 if (cmd.rsp.ret == 0)
1279 return cmd.rsp.data;
fe84a562 1280
88556fd7
ÇO
1281 return NULL;
1282}
1283
1284static int lxc_cmd_get_lxcpath_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1285 struct lxc_handler *handler,
1286 struct lxc_epoll_descr *descr)
88556fd7 1287{
6c6497ea
CB
1288 struct lxc_cmd_rsp rsp = {
1289 .ret = 0,
1290 .data = (char *)handler->lxcpath,
1291 .datalen = strlen(handler->lxcpath) + 1,
1292 };
88556fd7 1293
4b5f4bdc 1294 return lxc_cmd_rsp_send_reap(fd, &rsp);
88556fd7 1295}
ef6e34ee 1296
54446942 1297int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
3d971319 1298 lxc_state_t states[static MAX_STATE],
92e35018 1299 int *state_client_fd)
dbc9832d 1300{
f62cf1d4 1301 __do_close int clientfd = -EBADF;
8a598112 1302 bool stopped = false;
dbc9832d 1303 struct lxc_cmd_rr cmd = {
6c6497ea
CB
1304 .req = {
1305 .cmd = LXC_CMD_ADD_STATE_CLIENT,
1306 .data = states,
1307 .datalen = (sizeof(lxc_state_t) * MAX_STATE)
1308 },
dbc9832d 1309 };
8a598112
CB
1310 int state;
1311 ssize_t ret;
dbc9832d 1312
dbc9832d 1313 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
bc631984
CB
1314 if (states[STOPPED] != 0 && stopped != 0)
1315 return STOPPED;
1316
dbc9832d 1317 if (ret < 0) {
f577e061 1318 if (errno != ECONNREFUSED)
6d1400b5 1319 SYSERROR("Failed to execute command");
1320
dbc9832d
CB
1321 return -1;
1322 }
fe84a562 1323
dbc9832d
CB
1324 /* We should now be guaranteed to get an answer from the state sending
1325 * function.
1326 */
cd889e57 1327 clientfd = cmd.rsp.ret;
6c6497ea
CB
1328 if (clientfd < 0)
1329 return log_error_errno(-1, -clientfd, "Failed to receive socket fd");
dbc9832d 1330
bc631984 1331 state = PTR_TO_INT(cmd.rsp.data);
6c6497ea
CB
1332 if (state < MAX_STATE)
1333 return log_trace(state, "Container is already in requested state %s", lxc_state2str(state));
bc631984 1334
240fecd0 1335 *state_client_fd = move_fd(clientfd);
ea2a070b
CB
1336 TRACE("State connection fd %d ready to listen for container state changes", *state_client_fd);
1337 return MAX_STATE;
dbc9832d
CB
1338}
1339
ebbca852 1340static int lxc_cmd_add_state_client_callback(__owns int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1341 struct lxc_handler *handler,
1342 struct lxc_epoll_descr *descr)
dbc9832d 1343{
4b5f4bdc
CB
1344 struct lxc_cmd_rsp rsp = {
1345 .ret = -EINVAL,
1346 };
dbc9832d 1347
fe84a562 1348 if (req->datalen < 0)
254a22e1 1349 goto reap_fd;
dbc9832d 1350
71fc9c04 1351 if (req->datalen != (sizeof(lxc_state_t) * MAX_STATE))
254a22e1 1352 goto reap_fd;
dbc9832d 1353
fe84a562 1354 if (!req->data)
254a22e1 1355 goto reap_fd;
dbc9832d 1356
c01c2be6 1357 rsp.ret = lxc_add_state_client(fd, handler, (lxc_state_t *)req->data);
44552fb2 1358 if (rsp.ret < 0)
254a22e1 1359 goto reap_fd;
44552fb2 1360
bc631984 1361 rsp.data = INT_TO_PTR(rsp.ret);
dbc9832d 1362
254a22e1
CB
1363 return lxc_cmd_rsp_send_keep(fd, &rsp);
1364
1365reap_fd:
4b5f4bdc 1366 return lxc_cmd_rsp_send_reap(fd, &rsp);
dbc9832d
CB
1367}
1368
2a63b5cb
CB
1369int lxc_cmd_add_bpf_device_cgroup(const char *name, const char *lxcpath,
1370 struct device_item *device)
1371{
8a598112 1372 bool stopped = false;
2a63b5cb 1373 struct lxc_cmd_rr cmd = {
6c6497ea
CB
1374 .req = {
1375 .cmd = LXC_CMD_ADD_BPF_DEVICE_CGROUP,
1376 .data = device,
1377 .datalen = sizeof(struct device_item),
1378 },
2a63b5cb
CB
1379 };
1380 int ret;
1381
1382 if (strlen(device->access) > STRLITERALLEN("rwm"))
3d0327ed 1383 return log_error_errno(-1, EINVAL, "Invalid access mode specified %s",
2a63b5cb
CB
1384 device->access);
1385
1386 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
1387 if (ret < 0 || cmd.rsp.ret < 0)
3d0327ed 1388 return log_error_errno(-1, errno, "Failed to add new bpf device cgroup rule");
2a63b5cb
CB
1389
1390 return 0;
2a63b5cb
CB
1391}
1392
1393static int lxc_cmd_add_bpf_device_cgroup_callback(int fd, struct lxc_cmd_req *req,
1394 struct lxc_handler *handler,
1395 struct lxc_epoll_descr *descr)
1396{
4b5f4bdc
CB
1397 struct lxc_cmd_rsp rsp = {
1398 .ret = -EINVAL,
1399 };
0a150695 1400 struct lxc_conf *conf;
2a63b5cb
CB
1401
1402 if (req->datalen <= 0)
4b5f4bdc 1403 goto out;
2a63b5cb
CB
1404
1405 if (req->datalen != sizeof(struct device_item))
4b5f4bdc 1406 goto out;
2a63b5cb
CB
1407
1408 if (!req->data)
4b5f4bdc 1409 goto out;
2a63b5cb 1410
0a150695 1411 conf = handler->conf;
a134099d
CB
1412 if (!bpf_cgroup_devices_update(handler->cgroup_ops,
1413 &conf->bpf_devices,
1414 (struct device_item *)req->data))
0a150695
CB
1415 rsp.ret = -1;
1416 else
1417 rsp.ret = 0;
2a63b5cb 1418
4b5f4bdc
CB
1419out:
1420 return lxc_cmd_rsp_send_reap(fd, &rsp);
2a63b5cb
CB
1421}
1422
191d43cc
CB
1423int lxc_cmd_console_log(const char *name, const char *lxcpath,
1424 struct lxc_console_log *log)
1425{
8a598112
CB
1426 bool stopped = false;
1427 int ret;
191d43cc
CB
1428 struct lxc_cmd_console_log data;
1429 struct lxc_cmd_rr cmd;
1430
1431 data.clear = log->clear;
1432 data.read = log->read;
1433 data.read_max = *log->read_max;
1434
1435 cmd.req.cmd = LXC_CMD_CONSOLE_LOG;
1436 cmd.req.data = &data;
1437 cmd.req.datalen = sizeof(struct lxc_cmd_console_log);
1438
1439 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
1440 if (ret < 0)
1441 return ret;
1442
1443 /* There is nothing to be read from the buffer. So clear any values we
1444 * where passed to clearly indicate to the user that nothing went wrong.
1445 */
63b74cda 1446 if (cmd.rsp.ret == -ENODATA || cmd.rsp.ret == -EFAULT || cmd.rsp.ret == -ENOENT) {
191d43cc
CB
1447 *log->read_max = 0;
1448 log->data = NULL;
1449 }
1450
1451 /* This is a proper error so don't touch any values we were passed. */
1452 if (cmd.rsp.ret < 0)
1453 return cmd.rsp.ret;
1454
1455 *log->read_max = cmd.rsp.datalen;
1456 log->data = cmd.rsp.data;
1457
1458 return 0;
1459}
1460
1461static int lxc_cmd_console_log_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1462 struct lxc_handler *handler,
1463 struct lxc_epoll_descr *descr)
191d43cc
CB
1464{
1465 struct lxc_cmd_rsp rsp;
28f3b1cd 1466 uint64_t buffer_size = handler->conf->console.buffer_size;
191d43cc
CB
1467 const struct lxc_cmd_console_log *log = req->data;
1468 struct lxc_ringbuf *buf = &handler->conf->console.ringbuf;
1469
1470 rsp.ret = -EFAULT;
1471 rsp.datalen = 0;
1472 rsp.data = NULL;
28f3b1cd 1473 if (buffer_size <= 0)
191d43cc
CB
1474 goto out;
1475
5928191e
CB
1476 if (log->read || log->write_logfile)
1477 rsp.datalen = lxc_ringbuf_used(buf);
1478
191d43cc
CB
1479 if (log->read)
1480 rsp.data = lxc_ringbuf_get_read_addr(buf);
1481
1482 if (log->read_max > 0 && (log->read_max <= rsp.datalen))
1483 rsp.datalen = log->read_max;
1484
1485 /* there's nothing to read */
63b74cda 1486 rsp.ret = -ENODATA;
191d43cc 1487 if (log->read && (buf->r_off == buf->w_off))
63b74cda
CB
1488 goto out;
1489
63b74cda 1490 rsp.ret = 0;
23e0d9af 1491 if (log->clear)
43366ca2 1492 lxc_ringbuf_clear(buf); /* clear the ringbuffer */
23e0d9af 1493 else if (rsp.datalen > 0)
191d43cc
CB
1494 lxc_ringbuf_move_read_addr(buf, rsp.datalen);
1495
1496out:
4b5f4bdc 1497 return lxc_cmd_rsp_send_reap(fd, &rsp);
191d43cc
CB
1498}
1499
974a8aba
CB
1500int lxc_cmd_serve_state_clients(const char *name, const char *lxcpath,
1501 lxc_state_t state)
1502{
8a598112 1503 bool stopped = false;
974a8aba 1504 struct lxc_cmd_rr cmd = {
6c6497ea
CB
1505 .req = {
1506 .cmd = LXC_CMD_SERVE_STATE_CLIENTS,
1507 .data = INT_TO_PTR(state)
1508 },
974a8aba 1509 };
8a598112 1510 ssize_t ret;
974a8aba
CB
1511
1512 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
6c6497ea
CB
1513 if (ret < 0)
1514 return log_error_errno(-1, errno, "Failed to serve state clients");
974a8aba
CB
1515
1516 return 0;
1517}
1518
1519static int lxc_cmd_serve_state_clients_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1520 struct lxc_handler *handler,
1521 struct lxc_epoll_descr *descr)
974a8aba
CB
1522{
1523 int ret;
1524 lxc_state_t state = PTR_TO_INT(req->data);
1525 struct lxc_cmd_rsp rsp = {0};
1526
1527 ret = lxc_serve_state_clients(handler->name, handler, state);
1528 if (ret < 0)
4b5f4bdc 1529 return ret;
974a8aba 1530
4b5f4bdc 1531 return lxc_cmd_rsp_send_reap(fd, &rsp);
974a8aba
CB
1532}
1533
cdb2a47f
CB
1534int lxc_cmd_seccomp_notify_add_listener(const char *name, const char *lxcpath,
1535 int fd,
1536 /* unused */ unsigned int command,
1537 /* unused */ unsigned int flags)
1538{
1539
c3e3c21a 1540#ifdef HAVE_SECCOMP_NOTIFY
8a598112 1541 bool stopped = false;
cdb2a47f
CB
1542 struct lxc_cmd_rr cmd = {
1543 .req = {
1544 .cmd = LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER,
1545 .data = INT_TO_PTR(fd),
1546 },
1547 };
8a598112 1548 int ret;
cdb2a47f
CB
1549
1550 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
6c6497ea
CB
1551 if (ret < 0)
1552 return log_error_errno(-1, errno, "Failed to add seccomp listener");
cdb2a47f
CB
1553
1554 return cmd.rsp.ret;
1555#else
3d0327ed 1556 return ret_set_errno(-1, ENOSYS);
cdb2a47f
CB
1557#endif
1558}
1559
1560static int lxc_cmd_seccomp_notify_add_listener_callback(int fd,
1561 struct lxc_cmd_req *req,
1562 struct lxc_handler *handler,
1563 struct lxc_epoll_descr *descr)
1564{
1565 struct lxc_cmd_rsp rsp = {0};
cdb2a47f 1566
c3e3c21a
CB
1567#ifdef HAVE_SECCOMP_NOTIFY
1568 int ret;
f62cf1d4 1569 __do_close int recv_fd = -EBADF;
cdb2a47f 1570
d17c815d 1571 ret = lxc_abstract_unix_recv_one_fd(fd, &recv_fd, NULL, 0);
c3e3c21a
CB
1572 if (ret <= 0) {
1573 rsp.ret = -errno;
1574 goto out;
cdb2a47f
CB
1575 }
1576
c3e3c21a
CB
1577 if (!handler->conf->seccomp.notifier.wants_supervision ||
1578 handler->conf->seccomp.notifier.proxy_fd < 0) {
1579 SYSERROR("No seccomp proxy fd specified");
1580 rsp.ret = -EINVAL;
1581 goto out;
1582 }
cdb2a47f 1583
c3e3c21a 1584 ret = lxc_mainloop_add_handler(descr, recv_fd, seccomp_notify_handler,
cdb2a47f 1585 handler);
c3e3c21a
CB
1586 if (ret < 0) {
1587 rsp.ret = -errno;
1588 goto out;
1589 }
68a9e3eb 1590 move_fd(recv_fd);
cdb2a47f 1591
c3e3c21a 1592out:
cdb2a47f
CB
1593#else
1594 rsp.ret = -ENOSYS;
cdb2a47f 1595
c3e3c21a 1596#endif
4b5f4bdc 1597 return lxc_cmd_rsp_send_reap(fd, &rsp);
cdb2a47f
CB
1598}
1599
018051e3
CB
1600int lxc_cmd_freeze(const char *name, const char *lxcpath, int timeout)
1601{
8a598112 1602 bool stopped = false;
018051e3
CB
1603 struct lxc_cmd_rr cmd = {
1604 .req = {
1605 .cmd = LXC_CMD_FREEZE,
1606 .data = INT_TO_PTR(timeout),
1607 },
1608 };
8a598112 1609 int ret;
018051e3
CB
1610
1611 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
1612 if (ret <= 0 || cmd.rsp.ret < 0)
3d0327ed 1613 return log_error_errno(-1, errno, "Failed to freeze container");
018051e3
CB
1614
1615 return cmd.rsp.ret;
1616}
1617
1618static int lxc_cmd_freeze_callback(int fd, struct lxc_cmd_req *req,
1619 struct lxc_handler *handler,
1620 struct lxc_epoll_descr *descr)
1621{
1622 int timeout = PTR_TO_INT(req->data);
1623 struct lxc_cmd_rsp rsp = {
6c6497ea 1624 .ret = -ENOENT,
018051e3
CB
1625 };
1626 struct cgroup_ops *ops = handler->cgroup_ops;
1627
1973b62a 1628 if (pure_unified_layout(ops))
018051e3
CB
1629 rsp.ret = ops->freeze(ops, timeout);
1630
4b5f4bdc 1631 return lxc_cmd_rsp_send_reap(fd, &rsp);
018051e3
CB
1632}
1633
1634int lxc_cmd_unfreeze(const char *name, const char *lxcpath, int timeout)
1635{
8a598112 1636 bool stopped = false;
018051e3
CB
1637 struct lxc_cmd_rr cmd = {
1638 .req = {
1639 .cmd = LXC_CMD_UNFREEZE,
1640 .data = INT_TO_PTR(timeout),
1641 },
1642 };
8a598112 1643 int ret;
018051e3
CB
1644
1645 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
1646 if (ret <= 0 || cmd.rsp.ret < 0)
3d0327ed 1647 return log_error_errno(-1, errno, "Failed to unfreeze container");
018051e3
CB
1648
1649 return cmd.rsp.ret;
1650}
1651
1652static int lxc_cmd_unfreeze_callback(int fd, struct lxc_cmd_req *req,
1653 struct lxc_handler *handler,
1654 struct lxc_epoll_descr *descr)
1655{
1656 int timeout = PTR_TO_INT(req->data);
1657 struct lxc_cmd_rsp rsp = {
6c6497ea 1658 .ret = -ENOENT,
018051e3
CB
1659 };
1660 struct cgroup_ops *ops = handler->cgroup_ops;
1661
1973b62a 1662 if (pure_unified_layout(ops))
018051e3
CB
1663 rsp.ret = ops->unfreeze(ops, timeout);
1664
4b5f4bdc 1665 return lxc_cmd_rsp_send_reap(fd, &rsp);
018051e3
CB
1666}
1667
c206ac24 1668int lxc_cmd_get_cgroup_fd(const char *name, const char *lxcpath,
abb6f657 1669 size_t size_ret_fd, struct cgroup_fd *ret_fd)
c206ac24 1670{
8a598112 1671 bool stopped = false;
c206ac24
CB
1672 struct lxc_cmd_rr cmd = {
1673 .req = {
1674 .cmd = LXC_CMD_GET_CGROUP_FD,
abb6f657
CB
1675 .datalen = sizeof(struct cgroup_fd),
1676 .data = ret_fd,
c206ac24
CB
1677 },
1678 .rsp = {
8a598112 1679 .ret = -ENOSYS,
c206ac24
CB
1680 },
1681 };
8a598112 1682 int ret;
c206ac24
CB
1683
1684 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
1685 if (ret < 0)
abb6f657 1686 return log_debug_errno(-1, errno, "Failed to process cgroup fd command");
c206ac24
CB
1687
1688 if (cmd.rsp.ret < 0)
abb6f657 1689 return log_debug_errno(-EBADF, errno, "Failed to receive cgroup fd");
c206ac24 1690
abb6f657 1691 return 0;
c206ac24
CB
1692}
1693
1694int lxc_cmd_get_limit_cgroup_fd(const char *name, const char *lxcpath,
abb6f657 1695 size_t size_ret_fd, struct cgroup_fd *ret_fd)
c206ac24 1696{
8a598112 1697 bool stopped = false;
c206ac24
CB
1698 struct lxc_cmd_rr cmd = {
1699 .req = {
1700 .cmd = LXC_CMD_GET_LIMIT_CGROUP_FD,
abb6f657
CB
1701 .datalen = sizeof(struct cgroup_fd),
1702 .data = ret_fd,
c206ac24
CB
1703 },
1704 .rsp = {
8a598112 1705 .ret = -ENOSYS,
c206ac24
CB
1706 },
1707 };
8a598112 1708 int ret;
c206ac24
CB
1709
1710 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
1711 if (ret < 0)
abb6f657 1712 return log_debug_errno(-1, errno, "Failed to process limit cgroup fd command");
c206ac24
CB
1713
1714 if (cmd.rsp.ret < 0)
abb6f657 1715 return log_debug_errno(-EBADF, errno, "Failed to receive limit cgroup fd");
c206ac24 1716
abb6f657 1717 return 0;
c206ac24
CB
1718}
1719
1720static int __lxc_cmd_get_cgroup_fd_callback(int fd, struct lxc_cmd_req *req,
1721 struct lxc_handler *handler,
1722 struct lxc_epoll_descr *descr,
abb6f657 1723 bool limit)
c206ac24
CB
1724{
1725 struct lxc_cmd_rsp rsp = {
1726 .ret = -EINVAL,
1727 };
1728 struct cgroup_ops *ops = handler->cgroup_ops;
abb6f657
CB
1729 struct cgroup_fd fd_server = {};
1730 int ret;
c206ac24 1731
abb6f657
CB
1732 ret = copy_struct_from_client(sizeof(struct cgroup_fd), &fd_server,
1733 req->datalen, req->data);
1734 if (ret < 0)
c206ac24
CB
1735 return lxc_cmd_rsp_send_reap(fd, &rsp);
1736
abb6f657
CB
1737 if (strnlen(fd_server.controller, MAX_CGROUP_ROOT_NAMELEN) == 0)
1738 return lxc_cmd_rsp_send_reap(fd, &rsp);
c206ac24 1739
abb6f657
CB
1740 ret = prepare_cgroup_fd(ops, &fd_server, limit);
1741 if (ret < 0) {
1742 rsp.ret = ret;
c206ac24
CB
1743 return lxc_cmd_rsp_send_reap(fd, &rsp);
1744 }
1745
1746 rsp.ret = 0;
abb6f657
CB
1747 rsp.data = &fd_server;
1748 rsp.datalen = min(sizeof(struct cgroup_fd), (size_t)req->datalen);
1749 return rsp_one_fd(fd, fd_server.fd, &rsp);
c206ac24
CB
1750}
1751
1752static int lxc_cmd_get_cgroup_fd_callback(int fd, struct lxc_cmd_req *req,
1753 struct lxc_handler *handler,
1754 struct lxc_epoll_descr *descr)
1755{
1756 return __lxc_cmd_get_cgroup_fd_callback(fd, req, handler, descr, false);
1757}
1758
1759static int lxc_cmd_get_limit_cgroup_fd_callback(int fd, struct lxc_cmd_req *req,
1760 struct lxc_handler *handler,
1761 struct lxc_epoll_descr *descr)
1762{
1763 return __lxc_cmd_get_cgroup_fd_callback(fd, req, handler, descr, true);
1764}
1765
bad788b0
CB
1766int lxc_cmd_get_cgroup2_fd(const char *name, const char *lxcpath)
1767{
8a598112 1768 bool stopped = false;
bad788b0
CB
1769 struct lxc_cmd_rr cmd = {
1770 .req = {
1771 .cmd = LXC_CMD_GET_CGROUP2_FD,
1772 },
d3be623e 1773 .rsp = {
8a598112 1774 .ret = -ENOSYS,
d3be623e 1775 },
bad788b0 1776 };
8a598112 1777 int ret;
bad788b0
CB
1778
1779 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
23a917e5
CB
1780 if (ret < 0)
1781 return -1;
1782
1783 if (cmd.rsp.ret < 0)
a5263e59 1784 return log_debug_errno(cmd.rsp.ret, -cmd.rsp.ret, "Failed to receive cgroup2 fd");
6f7f2966
CB
1785
1786 return PTR_TO_INT(cmd.rsp.data);
1787}
1788
a9b642ee 1789int lxc_cmd_get_limit_cgroup2_fd(const char *name, const char *lxcpath)
6f7f2966 1790{
8a598112 1791 bool stopped = false;
6f7f2966
CB
1792 struct lxc_cmd_rr cmd = {
1793 .req = {
a9b642ee 1794 .cmd = LXC_CMD_GET_LIMIT_CGROUP2_FD,
6f7f2966 1795 },
d3be623e
CB
1796 .rsp = {
1797 .ret = -ENOSYS,
1798 },
6f7f2966 1799 };
8a598112 1800 int ret;
6f7f2966
CB
1801
1802 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
1803 if (ret < 0)
1804 return -1;
1805
1806 if (cmd.rsp.ret < 0)
d3be623e 1807 return syswarn_set(cmd.rsp.ret, "Failed to receive cgroup2 limit fd");
bad788b0
CB
1808
1809 return PTR_TO_INT(cmd.rsp.data);
1810}
1811
a900cbaf
WB
1812static int lxc_cmd_get_cgroup2_fd_callback_do(int fd, struct lxc_cmd_req *req,
1813 struct lxc_handler *handler,
1814 struct lxc_epoll_descr *descr,
1815 bool limiting_cgroup)
bad788b0
CB
1816{
1817 struct lxc_cmd_rsp rsp = {
1818 .ret = -EINVAL,
1819 };
1820 struct cgroup_ops *ops = handler->cgroup_ops;
c2f40088 1821 int send_fd;
bad788b0 1822
1973b62a 1823 if (!pure_unified_layout(ops) || !ops->unified)
4b5f4bdc 1824 return lxc_cmd_rsp_send_reap(fd, &rsp);
bad788b0 1825
c0af7b1c 1826 send_fd = limiting_cgroup ? ops->unified->dfd_lim
e33870e5 1827 : ops->unified->dfd_con;
a900cbaf 1828
4b5f4bdc
CB
1829 if (send_fd < 0) {
1830 rsp.ret = -EBADF;
1831 return lxc_cmd_rsp_send_reap(fd, &rsp);
1832 }
1833
bad788b0 1834 rsp.ret = 0;
c2f40088 1835 return rsp_one_fd(fd, send_fd, &rsp);
bad788b0
CB
1836}
1837
a900cbaf
WB
1838static int lxc_cmd_get_cgroup2_fd_callback(int fd, struct lxc_cmd_req *req,
1839 struct lxc_handler *handler,
1840 struct lxc_epoll_descr *descr)
1841{
1842 return lxc_cmd_get_cgroup2_fd_callback_do(fd, req, handler, descr,
1843 false);
1844}
1845
a9b642ee
CB
1846static int lxc_cmd_get_limit_cgroup2_fd_callback(int fd, struct lxc_cmd_req *req,
1847 struct lxc_handler *handler,
1848 struct lxc_epoll_descr *descr)
a900cbaf
WB
1849{
1850 return lxc_cmd_get_cgroup2_fd_callback_do(fd, req, handler, descr,
1851 true);
1852}
1853
ebc548a1
CB
1854static int lxc_cmd_rsp_send_enosys(int fd, int id)
1855{
1856 struct lxc_cmd_rsp rsp = {
1857 .ret = -ENOSYS,
1858 };
1859
1860 __lxc_cmd_rsp_send(fd, &rsp);
1861 return syserrno_set(-ENOSYS, "Invalid command id %d", id);
1862}
1863
ef6e34ee 1864static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1865 struct lxc_handler *handler,
1866 struct lxc_epoll_descr *descr)
724e753c 1867{
cdb2a47f
CB
1868 typedef int (*callback)(int, struct lxc_cmd_req *, struct lxc_handler *,
1869 struct lxc_epoll_descr *);
ef6e34ee
DE
1870
1871 callback cb[LXC_CMD_MAX] = {
7e85a2c4 1872 [LXC_CMD_GET_TTY_FD] = lxc_cmd_get_tty_fd_callback,
2a63b5cb
CB
1873 [LXC_CMD_TERMINAL_WINCH] = lxc_cmd_terminal_winch_callback,
1874 [LXC_CMD_STOP] = lxc_cmd_stop_callback,
1875 [LXC_CMD_GET_STATE] = lxc_cmd_get_state_callback,
1876 [LXC_CMD_GET_INIT_PID] = lxc_cmd_get_init_pid_callback,
1877 [LXC_CMD_GET_CLONE_FLAGS] = lxc_cmd_get_clone_flags_callback,
1878 [LXC_CMD_GET_CGROUP] = lxc_cmd_get_cgroup_callback,
1879 [LXC_CMD_GET_CONFIG_ITEM] = lxc_cmd_get_config_item_callback,
1880 [LXC_CMD_GET_NAME] = lxc_cmd_get_name_callback,
1881 [LXC_CMD_GET_LXCPATH] = lxc_cmd_get_lxcpath_callback,
1882 [LXC_CMD_ADD_STATE_CLIENT] = lxc_cmd_add_state_client_callback,
1883 [LXC_CMD_CONSOLE_LOG] = lxc_cmd_console_log_callback,
1884 [LXC_CMD_SERVE_STATE_CLIENTS] = lxc_cmd_serve_state_clients_callback,
1885 [LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER] = lxc_cmd_seccomp_notify_add_listener_callback,
1886 [LXC_CMD_ADD_BPF_DEVICE_CGROUP] = lxc_cmd_add_bpf_device_cgroup_callback,
018051e3
CB
1887 [LXC_CMD_FREEZE] = lxc_cmd_freeze_callback,
1888 [LXC_CMD_UNFREEZE] = lxc_cmd_unfreeze_callback,
bad788b0 1889 [LXC_CMD_GET_CGROUP2_FD] = lxc_cmd_get_cgroup2_fd_callback,
746aab51 1890 [LXC_CMD_GET_INIT_PIDFD] = lxc_cmd_get_init_pidfd_callback,
a9b642ee
CB
1891 [LXC_CMD_GET_LIMIT_CGROUP] = lxc_cmd_get_limit_cgroup_callback,
1892 [LXC_CMD_GET_LIMIT_CGROUP2_FD] = lxc_cmd_get_limit_cgroup2_fd_callback,
f797f05e 1893 [LXC_CMD_GET_DEVPTS_FD] = lxc_cmd_get_devpts_fd_callback,
21405769 1894 [LXC_CMD_GET_SECCOMP_NOTIFY_FD] = lxc_cmd_get_seccomp_notify_fd_callback,
ef6e048a 1895 [LXC_CMD_GET_CGROUP_CTX] = lxc_cmd_get_cgroup_ctx_callback,
c206ac24
CB
1896 [LXC_CMD_GET_CGROUP_FD] = lxc_cmd_get_cgroup_fd_callback,
1897 [LXC_CMD_GET_LIMIT_CGROUP_FD] = lxc_cmd_get_limit_cgroup_fd_callback,
724e753c
MN
1898 };
1899
23a917e5 1900 if (req->cmd >= LXC_CMD_MAX)
ebc548a1 1901 return lxc_cmd_rsp_send_enosys(fd, req->cmd);
23a917e5 1902
cdb2a47f 1903 return cb[req->cmd](fd, req, handler, descr);
724e753c
MN
1904}
1905
ef6e34ee 1906static void lxc_cmd_fd_cleanup(int fd, struct lxc_handler *handler,
cdb2a47f 1907 struct lxc_epoll_descr *descr, const lxc_cmd_t cmd)
724e753c 1908{
3dfe6f8d 1909 lxc_terminal_free(handler->conf, fd);
724e753c 1910 lxc_mainloop_del_handler(descr, fd);
f6fc1565 1911
cd5369b0 1912 if (cmd == LXC_CMD_ADD_STATE_CLIENT) {
ab92468c
CB
1913 struct lxc_list *cur, *next;
1914
cdb2a47f
CB
1915 lxc_list_for_each_safe(cur, &handler->conf->state_clients, next) {
1916 struct lxc_state_client *client = cur->elem;
1917
1918 if (client->clientfd != fd)
1919 continue;
1920
ab92468c
CB
1921 /*
1922 * Only kick client from list so it can't be found
1923 * anymore. The actual close happens, as for all other
1924 * file descriptors, below.
1925 */
cdb2a47f 1926 lxc_list_del(cur);
cdb2a47f
CB
1927 free(cur->elem);
1928 free(cur);
ab92468c 1929
39e2a438
CB
1930 /*
1931 * No need to walk the whole list. If we found the state
cdb2a47f
CB
1932 * client fd there can't be a second one.
1933 */
ea2a070b 1934 TRACE("Found state client fd %d in state client list for command \"%s\"", fd, lxc_cmd_str(cmd));
ab92468c 1935 break;
cdb2a47f 1936 }
39e2a438
CB
1937
1938 /*
1939 * We didn't add the state client to the list. Either because
1940 * we failed to allocate memory (unlikely) or because the state
1941 * was already reached by the time we were ready to add it. So
1942 * fallthrough and clean it up.
1943 */
ea2a070b 1944 TRACE("Closing state client fd %d for command \"%s\"", fd, lxc_cmd_str(cmd));
f6fc1565 1945 }
cd5369b0 1946
ea2a070b 1947 TRACE("Closing client fd %d for command \"%s\"", fd, lxc_cmd_str(cmd));
cd5369b0 1948 close(fd);
724e753c
MN
1949}
1950
84c92abd
DE
1951static int lxc_cmd_handler(int fd, uint32_t events, void *data,
1952 struct lxc_epoll_descr *descr)
724e753c 1953{
5265a60c 1954 __do_free void *reqdata = NULL;
724e753c 1955 int ret;
ef6e34ee 1956 struct lxc_cmd_req req;
724e753c
MN
1957 struct lxc_handler *handler = data;
1958
aae93dd3 1959 ret = lxc_abstract_unix_rcv_credential(fd, &req, sizeof(req));
ded1d23f 1960 if (ret < 0) {
ea2a070b 1961 SYSERROR("Failed to receive data on command socket for command \"%s\"", lxc_cmd_str(req.cmd));
9044b79e 1962
1963 if (errno == EACCES) {
1964 /* We don't care for the peer, just send and close. */
ea2a070b 1965 struct lxc_cmd_rsp rsp = {
f7a97743 1966 .ret = -EPERM,
ea2a070b 1967 };
9044b79e 1968
4b5f4bdc 1969 __lxc_cmd_rsp_send(fd, &rsp);
9044b79e 1970 }
1971
724e753c
MN
1972 goto out_close;
1973 }
1974
fe84a562 1975 if (ret == 0)
724e753c 1976 goto out_close;
724e753c 1977
ef6e34ee 1978 if (ret != sizeof(req)) {
ea2a070b 1979 WARN("Failed to receive full command request. Ignoring request for \"%s\"", lxc_cmd_str(req.cmd));
ef6e34ee
DE
1980 goto out_close;
1981 }
1982
ea2a070b
CB
1983 if ((req.datalen > LXC_CMD_DATA_MAX) && (req.cmd != LXC_CMD_CONSOLE_LOG)) {
1984 ERROR("Received command data length %d is too large for command \"%s\"", req.datalen, lxc_cmd_str(req.cmd));
724e753c
MN
1985 goto out_close;
1986 }
1987
ef6e34ee 1988 if (req.datalen > 0) {
5265a60c 1989 reqdata = must_realloc(NULL, req.datalen);
e3233f26 1990 ret = lxc_recv_nointr(fd, reqdata, req.datalen, 0);
ef6e34ee 1991 if (ret != req.datalen) {
ea2a070b 1992 WARN("Failed to receive full command request. Ignoring request for \"%s\"", lxc_cmd_str(req.cmd));
ef6e34ee
DE
1993 goto out_close;
1994 }
fe84a562 1995
ef6e34ee
DE
1996 req.data = reqdata;
1997 }
1998
cdb2a47f 1999 ret = lxc_cmd_process(fd, &req, handler, descr);
32fd8d4f
CB
2000 if (ret < 0) {
2001 DEBUG("Failed to process command %s; cleaning up client fd %d", lxc_cmd_str(req.cmd), fd);
2002 goto out_close;
2003 } else if (ret == LXC_CMD_REAP_CLIENT_FD) {
2004 TRACE("Processed command %s; cleaning up client fd %d", lxc_cmd_str(req.cmd), fd);
724e753c 2005 goto out_close;
32fd8d4f
CB
2006 } else {
2007 TRACE("Processed command %s; keeping client fd %d", lxc_cmd_str(req.cmd), fd);
724e753c
MN
2008 }
2009
2010out:
f7a97743 2011 return LXC_MAINLOOP_CONTINUE;
fe84a562 2012
724e753c 2013out_close:
f6fc1565 2014 lxc_cmd_fd_cleanup(fd, handler, descr, req.cmd);
724e753c
MN
2015 goto out;
2016}
2017
84c92abd
DE
2018static int lxc_cmd_accept(int fd, uint32_t events, void *data,
2019 struct lxc_epoll_descr *descr)
724e753c 2020{
f62cf1d4 2021 __do_close int connection = -EBADF;
fe84a562 2022 int opt = 1, ret = -1;
724e753c
MN
2023
2024 connection = accept(fd, NULL, 0);
6c6497ea
CB
2025 if (connection < 0)
2026 return log_error_errno(LXC_MAINLOOP_ERROR, errno, "Failed to accept connection to run command");
724e753c 2027
fe84a562 2028 ret = fcntl(connection, F_SETFD, FD_CLOEXEC);
6c6497ea
CB
2029 if (ret < 0)
2030 return log_error_errno(ret, errno, "Failed to set close-on-exec on incoming command connection");
9ccb2dbc 2031
fe84a562 2032 ret = setsockopt(connection, SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt));
6c6497ea
CB
2033 if (ret < 0)
2034 return log_error_errno(ret, errno, "Failed to enable necessary credentials on command socket");
724e753c 2035
ef6e34ee 2036 ret = lxc_mainloop_add_handler(descr, connection, lxc_cmd_handler, data);
6c6497ea
CB
2037 if (ret)
2038 return log_error(ret, "Failed to add command handler");
724e753c 2039
ea2a070b 2040 TRACE("Accepted new client as fd %d on command server fd %d", connection, fd);
240fecd0 2041 move_fd(connection);
724e753c 2042 return ret;
724e753c
MN
2043}
2044
6834acff 2045int lxc_server_init(const char *name, const char *lxcpath, const char *suffix)
724e753c 2046{
f62cf1d4 2047 __do_close int fd = -EBADF;
c13e7111 2048 int ret;
b1234129 2049 char path[LXC_AUDS_ADDR_LEN] = {0};
724e753c 2050
5b46db1a 2051 ret = lxc_make_abstract_socket_name(path, sizeof(path), name, lxcpath, NULL, suffix);
fe84a562 2052 if (ret < 0)
9ba8130c 2053 return -1;
724e753c 2054
aae93dd3 2055 fd = lxc_abstract_unix_open(path, SOCK_STREAM, 0);
724e753c 2056 if (fd < 0) {
08aa08fe 2057 if (errno == EADDRINUSE)
fe84a562 2058 ERROR("Container \"%s\" appears to be already running", name);
6d1400b5 2059
6c6497ea 2060 return log_error_errno(-1, errno, "Failed to create command socket %s", &path[1]);
724e753c
MN
2061 }
2062
fe84a562 2063 ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
6c6497ea
CB
2064 if (ret < 0)
2065 return log_error_errno(-1, errno, "Failed to set FD_CLOEXEC on command socket file descriptor");
91480a0f 2066
6c6497ea 2067 return log_trace(move_fd(fd), "Created abstract unix socket \"%s\"", &path[1]);
d2e30e99
DE
2068}
2069
fe84a562 2070int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr,
ef6e34ee 2071 struct lxc_handler *handler)
d2e30e99 2072{
fe84a562 2073 int ret;
d2e30e99 2074
ea2a070b 2075 ret = lxc_mainloop_add_handler(descr, handler->conf->maincmd_fd, lxc_cmd_accept, handler);
6c6497ea 2076 if (ret < 0)
ea2a070b 2077 return log_error(ret, "Failed to add handler for command socket fd %d", handler->conf->maincmd_fd);
724e753c
MN
2078
2079 return ret;
2080}