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