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