]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/commands.c
seccomp: don't close the mainloop, simply remove the handler
[mirror_lxc.git] / src / lxc / commands.c
CommitLineData
cc73685d 1/* SPDX-License-Identifier: LGPL-2.1+ */
724e753c 2
d38dd64a
CB
3#ifndef _GNU_SOURCE
4#define _GNU_SOURCE 1
5#endif
cf685555 6#include <caps.h>
724e753c 7#include <errno.h>
91480a0f 8#include <fcntl.h>
fe84a562 9#include <malloc.h>
37515ebd 10#include <poll.h>
fe84a562
CB
11#include <signal.h>
12#include <stdio.h>
13#include <stdlib.h>
fe84a562 14#include <sys/param.h>
724e753c
MN
15#include <sys/socket.h>
16#include <sys/un.h>
d38dd64a 17#include <unistd.h>
724e753c 18
fe84a562 19#include "af_unix.h"
f2363e38 20#include "cgroup.h"
2a63b5cb 21#include "cgroups/cgroup2_devices.h"
724e753c 22#include "commands.h"
bbf5cf35 23#include "commands_utils.h"
fe84a562 24#include "conf.h"
d38dd64a 25#include "config.h"
ef6e34ee 26#include "confile.h"
fe84a562
CB
27#include "log.h"
28#include "lxc.h"
dbc9832d 29#include "lxclock.h"
cdb2a47f 30#include "lxcseccomp.h"
724e753c 31#include "mainloop.h"
5265a60c 32#include "memory_utils.h"
dbc9832d 33#include "monitor.h"
fe84a562 34#include "start.h"
0ed9b1bc 35#include "terminal.h"
fe84a562 36#include "utils.h"
724e753c 37
ded1d23f 38/*
fe84a562
CB
39 * This file provides the different functions for clients to query/command the
40 * server. The client is typically some lxc tool and the server is typically the
41 * container (ie. lxc-start).
ded1d23f 42 *
fe84a562
CB
43 * Each command is transactional, the clients send a request to the server and
44 * the server answers the request with a message giving the request's status
45 * (zero or a negative errno value). Both the request and response may contain
46 * additional data.
ded1d23f 47 *
fe84a562
CB
48 * Each command is wrapped in a ancillary message in order to pass a credential
49 * making possible to the server to check if the client is allowed to ask for
50 * this command or not.
80bcb053 51 *
fe84a562
CB
52 * IMPORTANTLY: Note that semantics for current commands are fixed. If you wish
53 * to make any changes to how, say, LXC_CMD_GET_CONFIG_ITEM works by adding
54 * information to the end of cmd.data, then you must introduce a new
55 * LXC_CMD_GET_CONFIG_ITEM_V2 define with a new number. You may wish to also
56 * mark LXC_CMD_GET_CONFIG_ITEM deprecated in commands.h.
80bcb053
SH
57 *
58 * This is necessary in order to avoid having a newly compiled lxc command
59 * communicating with a running (old) monitor from crashing the running
60 * container.
ded1d23f
DL
61 */
62
ac2cecc4 63lxc_log_define(commands, lxc);
724e753c 64
ef6e34ee 65static const char *lxc_cmd_str(lxc_cmd_t cmd)
724e753c 66{
fe84a562 67 static const char *const cmdname[LXC_CMD_MAX] = {
2a63b5cb
CB
68 [LXC_CMD_CONSOLE] = "console",
69 [LXC_CMD_TERMINAL_WINCH] = "terminal_winch",
70 [LXC_CMD_STOP] = "stop",
71 [LXC_CMD_GET_STATE] = "get_state",
72 [LXC_CMD_GET_INIT_PID] = "get_init_pid",
73 [LXC_CMD_GET_CLONE_FLAGS] = "get_clone_flags",
74 [LXC_CMD_GET_CGROUP] = "get_cgroup",
75 [LXC_CMD_GET_CONFIG_ITEM] = "get_config_item",
76 [LXC_CMD_GET_NAME] = "get_name",
77 [LXC_CMD_GET_LXCPATH] = "get_lxcpath",
78 [LXC_CMD_ADD_STATE_CLIENT] = "add_state_client",
79 [LXC_CMD_CONSOLE_LOG] = "console_log",
80 [LXC_CMD_SERVE_STATE_CLIENTS] = "serve_state_clients",
81 [LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER] = "seccomp_notify_add_listener",
82 [LXC_CMD_ADD_BPF_DEVICE_CGROUP] = "add_bpf_device_cgroup",
018051e3
CB
83 [LXC_CMD_FREEZE] = "freeze",
84 [LXC_CMD_UNFREEZE] = "unfreeze",
bad788b0 85 [LXC_CMD_GET_CGROUP2_FD] = "get_cgroup2_fd",
746aab51 86 [LXC_CMD_GET_INIT_PIDFD] = "get_init_pidfd",
a900cbaf
WB
87 [LXC_CMD_GET_LIMITING_CGROUP] = "get_limiting_cgroup",
88 [LXC_CMD_GET_LIMITING_CGROUP2_FD] = "get_limiting_cgroup2_fd",
f797f05e 89 [LXC_CMD_GET_DEVPTS_FD] = "get_devpts_fd",
ef6e34ee 90 };
724e753c 91
f371aca9 92 if (cmd >= LXC_CMD_MAX)
a8007512 93 return "Invalid request";
fe84a562 94
ef6e34ee
DE
95 return cmdname[cmd];
96}
97
98/*
99 * lxc_cmd_rsp_recv: Receive a response to a command
100 *
101 * @sock : the socket connected to the container
102 * @cmd : command to put response in
103 *
104 * Returns the size of the response message or < 0 on failure
105 *
106 * Note that if the command response datalen > 0, then data is
107 * a malloc()ed buffer and should be free()ed by the caller. If
108 * the response data is <= a void * worth of data, it will be
109 * stored directly in data and datalen will be 0.
110 *
111 * As a special case, the response for LXC_CMD_CONSOLE is created
36a94ce8 112 * here as it contains an fd for the ptx pty passed through the
0115f8fd 113 * unix socket.
ef6e34ee
DE
114 */
115static int lxc_cmd_rsp_recv(int sock, struct lxc_cmd_rr *cmd)
116{
f62cf1d4 117 __do_close int fd_rsp = -EBADF;
23a917e5 118 int ret;
ef6e34ee
DE
119 struct lxc_cmd_rsp *rsp = &cmd->rsp;
120
23a917e5
CB
121 ret = lxc_abstract_unix_recv_fds(sock, &fd_rsp, 1, rsp, sizeof(*rsp));
122 if (ret < 0)
123 return log_warn_errno(-1,
124 errno, "Failed to receive response for command \"%s\"",
125 lxc_cmd_str(cmd->req.cmd));
fe84a562 126 TRACE("Command \"%s\" received response", lxc_cmd_str(cmd->req.cmd));
ef6e34ee
DE
127
128 if (cmd->req.cmd == LXC_CMD_CONSOLE) {
129 struct lxc_cmd_console_rsp_data *rspdata;
130
0115f8fd
DE
131 /* recv() returns 0 bytes when a tty cannot be allocated,
132 * rsp->ret is < 0 when the peer permission check failed
133 */
134 if (ret == 0 || rsp->ret < 0)
135 return 0;
136
ef6e34ee 137 rspdata = malloc(sizeof(*rspdata));
23a917e5
CB
138 if (!rspdata)
139 return log_warn_errno(-1,
140 ENOMEM, "Failed to receive response for command \"%s\"",
141 lxc_cmd_str(cmd->req.cmd));
2a850b2c 142
36a94ce8 143 rspdata->ptxfd = move_fd(fd_rsp);
ef6e34ee
DE
144 rspdata->ttynum = PTR_TO_INT(rsp->data);
145 rsp->data = rspdata;
146 }
147
a900cbaf
WB
148 if (cmd->req.cmd == LXC_CMD_GET_CGROUP2_FD ||
149 cmd->req.cmd == LXC_CMD_GET_LIMITING_CGROUP2_FD)
150 {
23a917e5
CB
151 int cgroup2_fd = move_fd(fd_rsp);
152 rsp->data = INT_TO_PTR(cgroup2_fd);
860e7c43 153 }
fe84a562 154
746aab51
CB
155 if (cmd->req.cmd == LXC_CMD_GET_INIT_PIDFD) {
156 int init_pidfd = move_fd(fd_rsp);
157 rsp->data = INT_TO_PTR(init_pidfd);
158 }
159
f797f05e
CB
160 if (cmd->req.cmd == LXC_CMD_GET_DEVPTS_FD) {
161 int devpts_fd = move_fd(fd_rsp);
162 rsp->data = INT_TO_PTR(devpts_fd);
163 }
164
23a917e5
CB
165 if (rsp->datalen == 0)
166 return log_debug(ret,
167 "Response data length for command \"%s\" is 0",
168 lxc_cmd_str(cmd->req.cmd));
169
191d43cc 170 if ((rsp->datalen > LXC_CMD_DATA_MAX) &&
23a917e5
CB
171 (cmd->req.cmd != LXC_CMD_CONSOLE_LOG))
172 return log_error(-1, "Response data for command \"%s\" is too long: %d bytes > %d",
173 lxc_cmd_str(cmd->req.cmd), rsp->datalen,
174 LXC_CMD_DATA_MAX);
ef6e34ee 175
191d43cc
CB
176 if (cmd->req.cmd == LXC_CMD_CONSOLE_LOG) {
177 rsp->data = malloc(rsp->datalen + 1);
178 ((char *)rsp->data)[rsp->datalen] = '\0';
179 } else {
180 rsp->data = malloc(rsp->datalen);
181 }
23a917e5
CB
182 if (!rsp->data)
183 return log_error_errno(-1,
184 ENOMEM, "Failed to allocate response buffer for command \"%s\"",
185 lxc_cmd_str(cmd->req.cmd));
fe84a562 186
2a850b2c 187 ret = lxc_recv_nointr(sock, rsp->data, rsp->datalen, 0);
23a917e5
CB
188 if (ret != rsp->datalen)
189 return log_error_errno(-1,
190 errno, "Failed to receive response data for command \"%s\"",
191 lxc_cmd_str(cmd->req.cmd));
724e753c
MN
192
193 return ret;
194}
195
ef6e34ee
DE
196/*
197 * lxc_cmd_rsp_send: Send a command response
198 *
199 * @fd : file descriptor of socket to send response on
200 * @rsp : response to send
201 *
202 * Returns 0 on success, < 0 on failure
203 */
204static int lxc_cmd_rsp_send(int fd, struct lxc_cmd_rsp *rsp)
205{
fe84a562 206 ssize_t ret;
ef6e34ee 207
7fbb15ec
CB
208 errno = EMSGSIZE;
209 ret = lxc_send_nointr(fd, rsp, sizeof(*rsp), MSG_NOSIGNAL);
6c6497ea
CB
210 if (ret < 0 || (size_t)ret != sizeof(*rsp))
211 return log_error_errno(-1, errno, "Failed to send command response %zd", ret);
ef6e34ee 212
a674dfe1 213 if (!rsp->data || rsp->datalen <= 0)
fe84a562
CB
214 return 0;
215
7fbb15ec
CB
216 errno = EMSGSIZE;
217 ret = lxc_send_nointr(fd, rsp->data, rsp->datalen, MSG_NOSIGNAL);
6c6497ea
CB
218 if (ret < 0 || ret != (ssize_t)rsp->datalen)
219 return log_warn_errno(-1, errno, "Failed to send command response data %zd", ret);
fe84a562 220
ef6e34ee
DE
221 return 0;
222}
223
c01c2be6 224static int lxc_cmd_send(const char *name, struct lxc_cmd_rr *cmd,
fe84a562 225 const char *lxcpath, const char *hashed_sock_name)
c01c2be6 226{
f62cf1d4 227 __do_close int client_fd = -EBADF;
fe84a562 228 ssize_t ret = -1;
c01c2be6 229
9dfa4041 230 client_fd = lxc_cmd_connect(name, lxcpath, hashed_sock_name, "command");
2a850b2c 231 if (client_fd < 0)
fe84a562 232 return -1;
c01c2be6 233
fe84a562
CB
234 ret = lxc_abstract_unix_send_credential(client_fd, &cmd->req,
235 sizeof(cmd->req));
2a850b2c 236 if (ret < 0 || (size_t)ret != sizeof(cmd->req))
e96f9291 237 return -1;
9044b79e 238
cdb2a47f
CB
239 if (cmd->req.cmd == LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER) {
240 int notify_fd = PTR_TO_INT(cmd->req.data);
241 ret = lxc_abstract_unix_send_fds(client_fd, &notify_fd, 1, NULL, 0);
242 if (ret <= 0)
243 return -1;
244 } else {
245 if (cmd->req.datalen <= 0)
246 return move_fd(client_fd);
c01c2be6 247
cdb2a47f
CB
248 errno = EMSGSIZE;
249 ret = lxc_send_nointr(client_fd, (void *)cmd->req.data,
250 cmd->req.datalen, MSG_NOSIGNAL);
251 if (ret < 0 || ret != (ssize_t)cmd->req.datalen)
252 return -1;
253 }
c01c2be6 254
240fecd0 255 return move_fd(client_fd);
c01c2be6
CB
256}
257
ef6e34ee
DE
258/*
259 * lxc_cmd: Connect to the specified running container, send it a command
260 * request and collect the response
261 *
262 * @name : name of container to connect to
1e8cfdf6 263 * @cmd : command with initialized request to send
ef6e34ee
DE
264 * @stopped : output indicator if the container was not running
265 * @lxcpath : the lxcpath in which the container is running
266 *
267 * Returns the size of the response message on success, < 0 on failure
268 *
269 * Note that there is a special case for LXC_CMD_CONSOLE. For this command
270 * the fd cannot be closed because it is used as a placeholder to indicate
271 * that a particular tty slot is in use. The fd is also used as a signal to
272 * the container that when the caller dies or closes the fd, the container
0115f8fd
DE
273 * will notice the fd on its side of the socket in its mainloop select and
274 * then free the slot with lxc_cmd_fd_cleanup(). The socket fd will be
275 * returned in the cmd response structure.
ef6e34ee
DE
276 */
277static int lxc_cmd(const char *name, struct lxc_cmd_rr *cmd, int *stopped,
88556fd7 278 const char *lxcpath, const char *hashed_sock_name)
724e753c 279{
f62cf1d4 280 __do_close int client_fd = -EBADF;
fe84a562 281 int ret = -1;
dbc9832d
CB
282 bool stay_connected = false;
283
284 if (cmd->req.cmd == LXC_CMD_CONSOLE ||
54446942 285 cmd->req.cmd == LXC_CMD_ADD_STATE_CLIENT)
dbc9832d 286 stay_connected = true;
724e753c 287
0ecf64b5
SH
288 *stopped = 0;
289
c01c2be6
CB
290 client_fd = lxc_cmd_send(name, cmd, lxcpath, hashed_sock_name);
291 if (client_fd < 0) {
00e5ca13 292 if (errno == ECONNREFUSED || errno == EPIPE)
ef6e34ee 293 *stopped = 1;
3f903c04 294
6c6497ea
CB
295 return log_trace_errno(-1, errno, "Command \"%s\" failed to connect command socket",
296 lxc_cmd_str(cmd->req.cmd));
724e753c
MN
297 }
298
c01c2be6 299 ret = lxc_cmd_rsp_recv(client_fd, cmd);
2a850b2c 300 if (ret < 0 && errno == ECONNRESET)
6b7f85cb 301 *stopped = 1;
6a93ae77 302
ea2a070b
CB
303 TRACE("Opened new command socket connection fd %d for command \"%s\"",
304 client_fd, lxc_cmd_str(cmd->req.cmd));
305
c34ff119 306 if (stay_connected && ret > 0)
240fecd0 307 cmd->rsp.ret = move_fd(client_fd);
43eb6f29 308
1362f2eb 309 return ret;
724e753c
MN
310}
311
b494d2dd
SH
312int lxc_try_cmd(const char *name, const char *lxcpath)
313{
0ecf64b5 314 int stopped, ret;
b494d2dd
SH
315 struct lxc_cmd_rr cmd = {
316 .req = { .cmd = LXC_CMD_GET_INIT_PID },
317 };
318
88556fd7 319 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
b494d2dd
SH
320 if (stopped)
321 return 0;
322 if (ret > 0 && cmd.rsp.ret < 0) {
323 errno = cmd.rsp.ret;
324 return -1;
325 }
326 if (ret > 0)
327 return 0;
328
fe84a562
CB
329 /* At this point we weren't denied access, and the container *was*
330 * started. There was some inexplicable error in the protocol. I'm not
331 * clear on whether we should return -1 here, but we didn't receive a
332 * -EACCES, so technically it's not that we're not allowed to control
333 * the container - it's just not behaving.
b494d2dd
SH
334 */
335 return 0;
336}
337
e6bc68d6
WB
338/*
339 * Validate that the input is a proper string parameter. If not,
340 * send an EINVAL response and return -1.
341 *
342 * Precondition: there is non-zero-length data available.
343 */
344static int validate_string_request(int fd, const struct lxc_cmd_req *req)
345{
346 int ret;
347 size_t maxlen = req->datalen - 1;
348 const char *data = req->data;
349
350 if (data[maxlen] == 0 && strnlen(data, maxlen) == maxlen)
351 return 0;
352
353 struct lxc_cmd_rsp rsp = {
354 .ret = -EINVAL,
355 .datalen = 0,
356 .data = NULL,
357 };
358
359 ret = lxc_cmd_rsp_send(fd, &rsp);
360 if (ret < 0)
361 return LXC_CMD_REAP_CLIENT_FD;
362
363 return -1;
364}
365
cc4c0832 366/* Implementations of the commands and their callbacks */
ef6e34ee
DE
367
368/*
369 * lxc_cmd_get_init_pid: Get pid of the container's init process
370 *
371 * @name : name of container to connect to
372 * @lxcpath : the lxcpath in which the container is running
373 *
374 * Returns the pid on success, < 0 on failure
375 */
376pid_t lxc_cmd_get_init_pid(const char *name, const char *lxcpath)
43eb6f29 377{
0ecf64b5 378 int ret, stopped;
565eb353 379 pid_t pid = -1;
ef6e34ee 380 struct lxc_cmd_rr cmd = {
e8cd1208
CB
381 .req = {
382 .cmd = LXC_CMD_GET_INIT_PID
383 },
384 .rsp = {
565eb353 385 .data = PID_TO_PTR(pid)
e8cd1208 386 }
ef6e34ee
DE
387 };
388
88556fd7 389 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ef6e34ee 390 if (ret < 0)
8ed8a626 391 return -1;
ef6e34ee 392
565eb353 393 pid = PTR_TO_PID(cmd.rsp.data);
9234406b
CB
394 if (pid < 0)
395 return -1;
396
397 /* We need to assume that pid_t can actually hold any pid given to us
398 * by the kernel. If it can't it's a libc bug.
399 */
400 return (pid_t)pid;
43eb6f29
DL
401}
402
ef6e34ee 403static int lxc_cmd_get_init_pid_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
404 struct lxc_handler *handler,
405 struct lxc_epoll_descr *descr)
43eb6f29 406{
ea2a070b 407 int ret;
9234406b 408 struct lxc_cmd_rsp rsp = {
565eb353 409 .data = PID_TO_PTR(handler->pid)
9234406b 410 };
ef6e34ee 411
ea2a070b
CB
412 ret = lxc_cmd_rsp_send(fd, &rsp);
413 if (ret < 0)
414 return LXC_CMD_REAP_CLIENT_FD;
415
416 return 0;
43eb6f29
DL
417}
418
746aab51
CB
419int lxc_cmd_get_init_pidfd(const char *name, const char *lxcpath)
420{
421 int ret, stopped;
422 struct lxc_cmd_rr cmd = {
423 .req = {
424 .cmd = LXC_CMD_GET_INIT_PIDFD,
425 },
426 };
427
428 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
429 if (ret < 0)
430 return log_debug_errno(-1, errno, "Failed to process init pidfd command");
431
432 if (cmd.rsp.ret < 0)
433 return log_debug_errno(-EBADF, errno, "Failed to receive init pidfd");
434
435 return PTR_TO_INT(cmd.rsp.data);
436}
437
438static int lxc_cmd_get_init_pidfd_callback(int fd, struct lxc_cmd_req *req,
439 struct lxc_handler *handler,
440 struct lxc_epoll_descr *descr)
441{
442 struct lxc_cmd_rsp rsp = {
443 .ret = 0,
444 };
445 int ret;
446
447 if (handler->pidfd < 0)
448 rsp.ret = -EBADF;
449 ret = lxc_abstract_unix_send_fds(fd, &handler->pidfd, 1, &rsp, sizeof(rsp));
450 if (ret < 0)
451 return log_error(LXC_CMD_REAP_CLIENT_FD, "Failed to send init pidfd");
452
453 return 0;
454}
455
f797f05e
CB
456int lxc_cmd_get_devpts_fd(const char *name, const char *lxcpath)
457{
458 int ret, stopped;
459 struct lxc_cmd_rr cmd = {
460 .req = {
461 .cmd = LXC_CMD_GET_DEVPTS_FD,
462 },
463 };
464
465 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
466 if (ret < 0)
467 return log_debug_errno(-1, errno, "Failed to process devpts fd command");
468
469 if (cmd.rsp.ret < 0)
470 return log_debug_errno(-EBADF, errno, "Failed to receive devpts fd");
471
472 return PTR_TO_INT(cmd.rsp.data);
473}
474
475static int lxc_cmd_get_devpts_fd_callback(int fd, struct lxc_cmd_req *req,
476 struct lxc_handler *handler,
477 struct lxc_epoll_descr *descr)
478{
479 struct lxc_cmd_rsp rsp = {
480 .ret = 0,
481 };
482 int ret;
483
484 if (!handler->conf || handler->conf->devpts_fd < 0)
485 rsp.ret = -EBADF;
486 ret = lxc_abstract_unix_send_fds(fd, &handler->conf->devpts_fd, 1, &rsp, sizeof(rsp));
487 if (ret < 0)
488 return log_error(LXC_CMD_REAP_CLIENT_FD, "Failed to send devpts fd");
489
490 return 0;
491}
492
ef6e34ee
DE
493/*
494 * lxc_cmd_get_clone_flags: Get clone flags container was spawned with
495 *
496 * @name : name of container to connect to
497 * @lxcpath : the lxcpath in which the container is running
498 *
499 * Returns the clone flags on success, < 0 on failure
500 */
501int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath)
502{
0ecf64b5 503 int ret, stopped;
ef6e34ee 504 struct lxc_cmd_rr cmd = {
6c6497ea
CB
505 .req = {
506 .cmd = LXC_CMD_GET_CLONE_FLAGS,
507 },
ef6e34ee
DE
508 };
509
88556fd7 510 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ef6e34ee
DE
511 if (ret < 0)
512 return ret;
43eb6f29 513
ef6e34ee
DE
514 return PTR_TO_INT(cmd.rsp.data);
515}
516
517static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
518 struct lxc_handler *handler,
519 struct lxc_epoll_descr *descr)
26b2d152 520{
ea2a070b 521 int ret;
6c6497ea
CB
522 struct lxc_cmd_rsp rsp = {
523 .data = INT_TO_PTR(handler->ns_clone_flags),
524 };
ef6e34ee 525
ea2a070b
CB
526 ret = lxc_cmd_rsp_send(fd, &rsp);
527 if (ret < 0)
528 return LXC_CMD_REAP_CLIENT_FD;
529
530 return 0;
ef6e34ee
DE
531}
532
a900cbaf
WB
533static char *lxc_cmd_get_cgroup_path_do(const char *name, const char *lxcpath,
534 const char *subsystem,
535 lxc_cmd_t command)
ef6e34ee 536{
0ecf64b5 537 int ret, stopped;
ef6e34ee 538 struct lxc_cmd_rr cmd = {
b98f7d6e 539 .req = {
a900cbaf 540 .cmd = command,
b98f7d6e 541 .data = subsystem,
c2aed66d 542 .datalen = 0,
b98f7d6e 543 },
26b2d152
MN
544 };
545
c2aed66d
CB
546 cmd.req.data = subsystem;
547 cmd.req.datalen = 0;
548 if (subsystem)
549 cmd.req.datalen = strlen(subsystem) + 1;
550
88556fd7 551 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
fe84a562 552 if (ret < 0)
ef6e34ee
DE
553 return NULL;
554
400d579e
WB
555 if (ret == 0) {
556 if (command == LXC_CMD_GET_LIMITING_CGROUP) {
557 /*
558 * This may indicate that the container was started
559 * under an ealier version before
560 * `cgroup_advanced_isolation` as implemented, there
561 * it sees an unknown command and just closes the
562 * socket, sending us an EOF.
563 */
564 return lxc_cmd_get_cgroup_path_do(name, lxcpath,
565 subsystem,
566 LXC_CMD_GET_CGROUP);
567 }
ef6e34ee 568 return NULL;
400d579e 569 }
ef6e34ee 570
fe84a562 571 if (cmd.rsp.ret < 0 || cmd.rsp.datalen < 0)
ef6e34ee 572 return NULL;
3f903c04 573
ef6e34ee
DE
574 return cmd.rsp.data;
575}
576
a900cbaf
WB
577/*
578 * lxc_cmd_get_cgroup_path: Calculate a container's cgroup path for a
579 * particular subsystem. This is the cgroup path relative to the root
580 * of the cgroup filesystem.
581 *
582 * @name : name of container to connect to
583 * @lxcpath : the lxcpath in which the container is running
584 * @subsystem : the subsystem being asked about
585 *
586 * Returns the path on success, NULL on failure. The caller must free() the
587 * returned path.
588 */
589char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath,
590 const char *subsystem)
591{
592 return lxc_cmd_get_cgroup_path_do(name, lxcpath, subsystem,
593 LXC_CMD_GET_CGROUP);
594}
595
596/*
597 * lxc_cmd_get_limiting_cgroup_path: Calculate a container's limiting cgroup
598 * path for a particular subsystem. This is the cgroup path relative to the
599 * root of the cgroup filesystem. This may be the same as the path returned by
600 * lxc_cmd_get_cgroup_path if the container doesn't have a limiting path prefix
601 * set.
602 *
603 * @name : name of container to connect to
604 * @lxcpath : the lxcpath in which the container is running
605 * @subsystem : the subsystem being asked about
606 *
607 * Returns the path on success, NULL on failure. The caller must free() the
608 * returned path.
609 */
610char *lxc_cmd_get_limiting_cgroup_path(const char *name, const char *lxcpath,
611 const char *subsystem)
612{
613 return lxc_cmd_get_cgroup_path_do(name, lxcpath, subsystem,
614 LXC_CMD_GET_LIMITING_CGROUP);
615}
616
617static int lxc_cmd_get_cgroup_callback_do(int fd, struct lxc_cmd_req *req,
618 struct lxc_handler *handler,
619 struct lxc_epoll_descr *descr,
620 bool limiting_cgroup)
ef6e34ee 621{
ea2a070b 622 int ret;
4fb3cba5 623 const char *path;
a900cbaf 624 const void *reqdata;
fe84a562 625 struct lxc_cmd_rsp rsp;
2202afc9 626 struct cgroup_ops *cgroup_ops = handler->cgroup_ops;
a900cbaf 627 const char *(*get_fn)(struct cgroup_ops *ops, const char *controller);
b98f7d6e 628
e6bc68d6
WB
629 if (req->datalen > 0) {
630 ret = validate_string_request(fd, req);
631 if (ret != 0)
632 return ret;
a900cbaf 633 reqdata = req->data;
e6bc68d6 634 } else {
a900cbaf 635 reqdata = NULL;
e6bc68d6 636 }
a900cbaf 637
29d652a9
WB
638 get_fn = (limiting_cgroup ? cgroup_ops->get_limiting_cgroup
639 : cgroup_ops->get_cgroup);
a900cbaf
WB
640
641 path = get_fn(cgroup_ops, reqdata);
642
b98f7d6e
SH
643 if (!path)
644 return -1;
fe84a562 645
4f17323e 646 rsp.ret = 0;
fe84a562
CB
647 rsp.datalen = strlen(path) + 1;
648 rsp.data = (char *)path;
ef6e34ee 649
ea2a070b
CB
650 ret = lxc_cmd_rsp_send(fd, &rsp);
651 if (ret < 0)
652 return LXC_CMD_REAP_CLIENT_FD;
653
654 return 0;
ef6e34ee
DE
655}
656
a900cbaf
WB
657static int lxc_cmd_get_cgroup_callback(int fd, struct lxc_cmd_req *req,
658 struct lxc_handler *handler,
659 struct lxc_epoll_descr *descr)
660{
661 return lxc_cmd_get_cgroup_callback_do(fd, req, handler, descr, false);
662}
663
664static int lxc_cmd_get_limiting_cgroup_callback(int fd, struct lxc_cmd_req *req,
665 struct lxc_handler *handler,
666 struct lxc_epoll_descr *descr)
667{
668 return lxc_cmd_get_cgroup_callback_do(fd, req, handler, descr, true);
669}
670
ef6e34ee
DE
671/*
672 * lxc_cmd_get_config_item: Get config item the running container
673 *
674 * @name : name of container to connect to
7fa3f2e9 675 * @item : the configuration item to retrieve (ex: lxc.net.0.veth.pair)
ef6e34ee
DE
676 * @lxcpath : the lxcpath in which the container is running
677 *
678 * Returns the item on success, NULL on failure. The caller must free() the
679 * returned item.
680 */
681char *lxc_cmd_get_config_item(const char *name, const char *item,
682 const char *lxcpath)
683{
0ecf64b5 684 int ret, stopped;
ef6e34ee
DE
685 struct lxc_cmd_rr cmd = {
686 .req = { .cmd = LXC_CMD_GET_CONFIG_ITEM,
687 .data = item,
fe84a562 688 .datalen = strlen(item) + 1,
ef6e34ee
DE
689 },
690 };
691
88556fd7 692 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ef6e34ee
DE
693 if (ret < 0)
694 return NULL;
695
696 if (cmd.rsp.ret == 0)
697 return cmd.rsp.data;
fe84a562 698
ef6e34ee
DE
699 return NULL;
700}
701
702static int lxc_cmd_get_config_item_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
703 struct lxc_handler *handler,
704 struct lxc_epoll_descr *descr)
ef6e34ee 705{
5265a60c 706 __do_free char *cidata = NULL;
ef6e34ee 707 int cilen;
30aec088 708 struct lxc_config_t *item;
fe84a562 709 struct lxc_cmd_rsp rsp;
ef6e34ee
DE
710
711 memset(&rsp, 0, sizeof(rsp));
300df83e 712 item = lxc_get_config(req->data);
30aec088
CB
713 if (!item)
714 goto err1;
fe84a562 715
cccd2219 716 cilen = item->get(req->data, NULL, 0, handler->conf, NULL);
ef6e34ee
DE
717 if (cilen <= 0)
718 goto err1;
719
5265a60c 720 cidata = must_realloc(NULL, cilen + 1);
cccd2219 721 if (item->get(req->data, cidata, cilen + 1, handler->conf, NULL) != cilen)
ef6e34ee 722 goto err1;
fe84a562 723
ef6e34ee
DE
724 cidata[cilen] = '\0';
725 rsp.data = cidata;
726 rsp.datalen = cilen + 1;
727 rsp.ret = 0;
728 goto out;
729
730err1:
731 rsp.ret = -1;
732out:
ea2a070b
CB
733 cilen = lxc_cmd_rsp_send(fd, &rsp);
734 if (cilen < 0)
735 return LXC_CMD_REAP_CLIENT_FD;
736
737 return 0;
ef6e34ee
DE
738}
739
740/*
741 * lxc_cmd_get_state: Get current state of the container
742 *
743 * @name : name of container to connect to
744 * @lxcpath : the lxcpath in which the container is running
745 *
746 * Returns the state on success, < 0 on failure
747 */
dbc9832d 748int lxc_cmd_get_state(const char *name, const char *lxcpath)
ef6e34ee 749{
0ecf64b5 750 int ret, stopped;
ef6e34ee 751 struct lxc_cmd_rr cmd = {
6c6497ea
CB
752 .req = {
753 .cmd = LXC_CMD_GET_STATE,
754 },
ef6e34ee 755 };
26b2d152 756
88556fd7 757 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ebdd307d 758 if (ret < 0 && stopped)
ef6e34ee
DE
759 return STOPPED;
760
761 if (ret < 0)
26b2d152 762 return -1;
26b2d152 763
6c6497ea
CB
764 if (!ret)
765 return log_warn(-1, "Container \"%s\" has stopped before sending its state", name);
fe84a562 766
6c6497ea
CB
767 return log_debug(PTR_TO_INT(cmd.rsp.data),
768 "Container \"%s\" is in \"%s\" state", name,
769 lxc_state2str(PTR_TO_INT(cmd.rsp.data)));
ef6e34ee
DE
770}
771
772static int lxc_cmd_get_state_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
773 struct lxc_handler *handler,
774 struct lxc_epoll_descr *descr)
ef6e34ee 775{
ea2a070b 776 int ret;
6c6497ea
CB
777 struct lxc_cmd_rsp rsp = {
778 .data = INT_TO_PTR(handler->state),
779 };
ef6e34ee 780
ea2a070b
CB
781 ret = lxc_cmd_rsp_send(fd, &rsp);
782 if (ret < 0)
783 return LXC_CMD_REAP_CLIENT_FD;
784
785 return 0;
ef6e34ee
DE
786}
787
788/*
789 * lxc_cmd_stop: Stop the container previously started with lxc_start. All
790 * the processes running inside this container will be killed.
791 *
792 * @name : name of container to connect to
793 * @lxcpath : the lxcpath in which the container is running
794 *
795 * Returns 0 on success, < 0 on failure
796 */
797int lxc_cmd_stop(const char *name, const char *lxcpath)
798{
0ecf64b5 799 int ret, stopped;
ef6e34ee 800 struct lxc_cmd_rr cmd = {
6c6497ea
CB
801 .req = {
802 .cmd = LXC_CMD_STOP,
803 },
ef6e34ee
DE
804 };
805
88556fd7 806 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
26b2d152 807 if (ret < 0) {
6c6497ea
CB
808 if (stopped)
809 return log_info(0, "Container \"%s\" is already stopped", name);
fe84a562 810
26b2d152
MN
811 return -1;
812 }
813
fe84a562
CB
814 /* We do not expect any answer, because we wait for the connection to be
815 * closed.
95d5b147 816 */
6c6497ea
CB
817 if (ret > 0)
818 return log_error_errno(-1, -cmd.rsp.ret, "Failed to stop container \"%s\"", name);
26b2d152 819
6c6497ea 820 return log_info(0, "Container \"%s\" has stopped", name);
26b2d152
MN
821}
822
ef6e34ee 823static int lxc_cmd_stop_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
824 struct lxc_handler *handler,
825 struct lxc_epoll_descr *descr)
d5088cf2 826{
ef6e34ee 827 struct lxc_cmd_rsp rsp;
ef6e34ee 828 int stopsignal = SIGKILL;
2202afc9 829 struct cgroup_ops *cgroup_ops = handler->cgroup_ops;
ea2a070b 830 int ret;
ef6e34ee
DE
831
832 if (handler->conf->stopsignal)
833 stopsignal = handler->conf->stopsignal;
834 memset(&rsp, 0, sizeof(rsp));
9837ee46 835
8ad4fa68 836 if (handler->pidfd >= 0)
9837ee46
CB
837 rsp.ret = lxc_raw_pidfd_send_signal(handler->pidfd, stopsignal, NULL, 0);
838 else
839 rsp.ret = kill(handler->pid, stopsignal);
ef6e34ee 840 if (!rsp.ret) {
9837ee46
CB
841 if (handler->pidfd >= 0)
842 TRACE("Sent signal %d to pidfd %d", stopsignal, handler->pidfd);
843 else
844 TRACE("Sent signal %d to pidfd %d", stopsignal, handler->pid);
845
018051e3
CB
846 rsp.ret = cgroup_ops->unfreeze(cgroup_ops, -1);
847 if (!rsp.ret)
95d5b147 848 return 0;
fe84a562
CB
849
850 ERROR("Failed to unfreeze container \"%s\"", handler->name);
018051e3
CB
851 rsp.ret = -errno;
852 } else {
853 rsp.ret = -errno;
ef6e34ee
DE
854 }
855
ea2a070b
CB
856 ret = lxc_cmd_rsp_send(fd, &rsp);
857 if (ret < 0)
858 return LXC_CMD_REAP_CLIENT_FD;
859
860 return 0;
ef6e34ee 861}
d5088cf2 862
b5159817 863/*
2bd158cc 864 * lxc_cmd_terminal_winch: noop
b5159817
DE
865 *
866 * @name : name of container to connect to
867 * @lxcpath : the lxcpath in which the container is running
868 *
869 * Returns 0 on success, < 0 on failure
870 */
8ccbbf94 871int lxc_cmd_terminal_winch(const char *name, const char *lxcpath)
b5159817 872{
b5159817
DE
873 return 0;
874}
875
8ccbbf94 876static int lxc_cmd_terminal_winch_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
877 struct lxc_handler *handler,
878 struct lxc_epoll_descr *descr)
b5159817 879{
2bd158cc 880 /* should never be called */
6c6497ea 881 return log_error_errno(-1, ENOSYS, "Called lxc_cmd_terminal_winch_callback()");
b5159817
DE
882}
883
ef6e34ee
DE
884/*
885 * lxc_cmd_console: Open an fd to a tty in the container
886 *
887 * @name : name of container to connect to
888 * @ttynum : in: the tty to open or -1 for next available
889 * : out: the tty allocated
36a94ce8 890 * @fd : out: file descriptor for ptx side of pty
ef6e34ee
DE
891 * @lxcpath : the lxcpath in which the container is running
892 *
0115f8fd 893 * Returns fd holding tty allocated on success, < 0 on failure
ef6e34ee
DE
894 */
895int lxc_cmd_console(const char *name, int *ttynum, int *fd, const char *lxcpath)
896{
8259d86d 897 __do_free struct lxc_cmd_console_rsp_data *rspdata = NULL;
0ecf64b5 898 int ret, stopped;
ef6e34ee 899 struct lxc_cmd_rr cmd = {
6c6497ea
CB
900 .req = {
901 .cmd = LXC_CMD_CONSOLE,
902 .data = INT_TO_PTR(*ttynum),
903 },
ef6e34ee 904 };
d5088cf2 905
88556fd7 906 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
ef6e34ee
DE
907 if (ret < 0)
908 return ret;
0115f8fd 909
8259d86d 910 rspdata = cmd.rsp.data;
6c6497ea
CB
911 if (cmd.rsp.ret < 0)
912 return log_error_errno(-1, -cmd.rsp.ret, "Denied access to tty");
d5088cf2 913
6c6497ea
CB
914 if (ret == 0)
915 return log_error(-1, "tty number %d invalid, busy or all ttys busy", *ttynum);
ef6e34ee 916
36a94ce8 917 if (rspdata->ptxfd < 0)
6c6497ea 918 return log_error(-1, "Unable to allocate fd for tty %d", rspdata->ttynum);
ef6e34ee 919
fe84a562 920 ret = cmd.rsp.ret; /* socket fd */
36a94ce8 921 *fd = rspdata->ptxfd;
ef6e34ee 922 *ttynum = rspdata->ttynum;
fe84a562 923
6c6497ea 924 return log_info(ret, "Alloced fd %d for tty %d via socket %d", *fd, rspdata->ttynum, ret);
ef6e34ee
DE
925}
926
927static int lxc_cmd_console_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
928 struct lxc_handler *handler,
929 struct lxc_epoll_descr *descr)
ef6e34ee 930{
36a94ce8 931 int ptxfd, ret;
ef6e34ee 932 struct lxc_cmd_rsp rsp;
fe84a562 933 int ttynum = PTR_TO_INT(req->data);
ef6e34ee 934
36a94ce8
CB
935 ptxfd = lxc_terminal_allocate(handler->conf, fd, &ttynum);
936 if (ptxfd < 0)
ea2a070b 937 return LXC_CMD_REAP_CLIENT_FD;
ef6e34ee 938
ef6e34ee
DE
939 memset(&rsp, 0, sizeof(rsp));
940 rsp.data = INT_TO_PTR(ttynum);
36a94ce8 941 ret = lxc_abstract_unix_send_fds(fd, &ptxfd, 1, &rsp, sizeof(rsp));
fe84a562 942 if (ret < 0) {
3dfe6f8d 943 lxc_terminal_free(handler->conf, fd);
ea2a070b
CB
944 return log_error_errno(LXC_CMD_REAP_CLIENT_FD, errno,
945 "Failed to send tty to client");
ef6e34ee
DE
946 }
947
ef6e34ee 948 return 0;
d5088cf2
CS
949}
950
88556fd7
ÇO
951/*
952 * lxc_cmd_get_name: Returns the name of the container
953 *
954 * @hashed_sock_name: hashed socket name
955 *
956 * Returns the name on success, NULL on failure.
957 */
958char *lxc_cmd_get_name(const char *hashed_sock_name)
959{
960 int ret, stopped;
961 struct lxc_cmd_rr cmd = {
6c6497ea
CB
962 .req = {
963 .cmd = LXC_CMD_GET_NAME,
964 },
88556fd7
ÇO
965 };
966
967 ret = lxc_cmd(NULL, &cmd, &stopped, NULL, hashed_sock_name);
fe84a562 968 if (ret < 0)
88556fd7 969 return NULL;
88556fd7
ÇO
970
971 if (cmd.rsp.ret == 0)
972 return cmd.rsp.data;
fe84a562 973
88556fd7
ÇO
974 return NULL;
975}
976
977static int lxc_cmd_get_name_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
978 struct lxc_handler *handler,
979 struct lxc_epoll_descr *descr)
88556fd7 980{
ea2a070b 981 int ret;
88556fd7
ÇO
982 struct lxc_cmd_rsp rsp;
983
984 memset(&rsp, 0, sizeof(rsp));
985
f0ecc19d 986 rsp.data = (char *)handler->name;
88556fd7
ÇO
987 rsp.datalen = strlen(handler->name) + 1;
988 rsp.ret = 0;
989
ea2a070b
CB
990 ret = lxc_cmd_rsp_send(fd, &rsp);
991 if (ret < 0)
992 return LXC_CMD_REAP_CLIENT_FD;
993
994 return 0;
88556fd7
ÇO
995}
996
997/*
998 * lxc_cmd_get_lxcpath: Returns the lxcpath of the container
999 *
1000 * @hashed_sock_name: hashed socket name
1001 *
1002 * Returns the lxcpath on success, NULL on failure.
1003 */
1004char *lxc_cmd_get_lxcpath(const char *hashed_sock_name)
1005{
1006 int ret, stopped;
1007 struct lxc_cmd_rr cmd = {
6c6497ea
CB
1008 .req = {
1009 .cmd = LXC_CMD_GET_LXCPATH,
1010 },
88556fd7 1011 };
724e753c 1012
88556fd7 1013 ret = lxc_cmd(NULL, &cmd, &stopped, NULL, hashed_sock_name);
fe84a562 1014 if (ret < 0)
88556fd7 1015 return NULL;
88556fd7
ÇO
1016
1017 if (cmd.rsp.ret == 0)
1018 return cmd.rsp.data;
fe84a562 1019
88556fd7
ÇO
1020 return NULL;
1021}
1022
1023static int lxc_cmd_get_lxcpath_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1024 struct lxc_handler *handler,
1025 struct lxc_epoll_descr *descr)
88556fd7 1026{
ea2a070b 1027 int ret;
6c6497ea
CB
1028 struct lxc_cmd_rsp rsp = {
1029 .ret = 0,
1030 .data = (char *)handler->lxcpath,
1031 .datalen = strlen(handler->lxcpath) + 1,
1032 };
88556fd7 1033
ea2a070b
CB
1034 ret = lxc_cmd_rsp_send(fd, &rsp);
1035 if (ret < 0)
1036 return LXC_CMD_REAP_CLIENT_FD;
1037
1038 return 0;
88556fd7 1039}
ef6e34ee 1040
54446942 1041int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
92e35018
CB
1042 lxc_state_t states[MAX_STATE],
1043 int *state_client_fd)
dbc9832d 1044{
f62cf1d4 1045 __do_close int clientfd = -EBADF;
bc631984 1046 int state, stopped;
dbc9832d 1047 ssize_t ret;
dbc9832d 1048 struct lxc_cmd_rr cmd = {
6c6497ea
CB
1049 .req = {
1050 .cmd = LXC_CMD_ADD_STATE_CLIENT,
1051 .data = states,
1052 .datalen = (sizeof(lxc_state_t) * MAX_STATE)
1053 },
dbc9832d
CB
1054 };
1055
dbc9832d 1056 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
bc631984
CB
1057 if (states[STOPPED] != 0 && stopped != 0)
1058 return STOPPED;
1059
dbc9832d 1060 if (ret < 0) {
f577e061 1061 if (errno != ECONNREFUSED)
6d1400b5 1062 SYSERROR("Failed to execute command");
1063
dbc9832d
CB
1064 return -1;
1065 }
fe84a562 1066
dbc9832d
CB
1067 /* We should now be guaranteed to get an answer from the state sending
1068 * function.
1069 */
cd889e57 1070 clientfd = cmd.rsp.ret;
6c6497ea
CB
1071 if (clientfd < 0)
1072 return log_error_errno(-1, -clientfd, "Failed to receive socket fd");
dbc9832d 1073
bc631984 1074 state = PTR_TO_INT(cmd.rsp.data);
6c6497ea
CB
1075 if (state < MAX_STATE)
1076 return log_trace(state, "Container is already in requested state %s", lxc_state2str(state));
bc631984 1077
240fecd0 1078 *state_client_fd = move_fd(clientfd);
ea2a070b
CB
1079 TRACE("State connection fd %d ready to listen for container state changes", *state_client_fd);
1080 return MAX_STATE;
dbc9832d
CB
1081}
1082
ebbca852 1083static int lxc_cmd_add_state_client_callback(__owns int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1084 struct lxc_handler *handler,
1085 struct lxc_epoll_descr *descr)
dbc9832d 1086{
44552fb2 1087 int ret;
dbc9832d 1088 struct lxc_cmd_rsp rsp = {0};
dbc9832d 1089
fe84a562 1090 if (req->datalen < 0)
ea2a070b 1091 return LXC_CMD_REAP_CLIENT_FD;
dbc9832d 1092
71fc9c04 1093 if (req->datalen != (sizeof(lxc_state_t) * MAX_STATE))
ea2a070b 1094 return LXC_CMD_REAP_CLIENT_FD;
dbc9832d 1095
fe84a562 1096 if (!req->data)
ea2a070b 1097 return LXC_CMD_REAP_CLIENT_FD;
dbc9832d 1098
c01c2be6 1099 rsp.ret = lxc_add_state_client(fd, handler, (lxc_state_t *)req->data);
44552fb2 1100 if (rsp.ret < 0)
ea2a070b 1101 return LXC_CMD_REAP_CLIENT_FD;
44552fb2 1102
bc631984 1103 rsp.data = INT_TO_PTR(rsp.ret);
dbc9832d 1104
44552fb2
CB
1105 ret = lxc_cmd_rsp_send(fd, &rsp);
1106 if (ret < 0)
ea2a070b 1107 return LXC_CMD_REAP_CLIENT_FD;
44552fb2
CB
1108
1109 return 0;
dbc9832d
CB
1110}
1111
2a63b5cb
CB
1112int lxc_cmd_add_bpf_device_cgroup(const char *name, const char *lxcpath,
1113 struct device_item *device)
1114{
1115#ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX
1116 int stopped = 0;
1117 struct lxc_cmd_rr cmd = {
6c6497ea
CB
1118 .req = {
1119 .cmd = LXC_CMD_ADD_BPF_DEVICE_CGROUP,
1120 .data = device,
1121 .datalen = sizeof(struct device_item),
1122 },
2a63b5cb
CB
1123 };
1124 int ret;
1125
1126 if (strlen(device->access) > STRLITERALLEN("rwm"))
3d0327ed 1127 return log_error_errno(-1, EINVAL, "Invalid access mode specified %s",
2a63b5cb
CB
1128 device->access);
1129
1130 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
1131 if (ret < 0 || cmd.rsp.ret < 0)
3d0327ed 1132 return log_error_errno(-1, errno, "Failed to add new bpf device cgroup rule");
2a63b5cb
CB
1133
1134 return 0;
1135#else
3d0327ed 1136 return ret_set_errno(-1, ENOSYS);
2a63b5cb
CB
1137#endif
1138}
1139
1140static int lxc_cmd_add_bpf_device_cgroup_callback(int fd, struct lxc_cmd_req *req,
1141 struct lxc_handler *handler,
1142 struct lxc_epoll_descr *descr)
1143{
1144#ifdef HAVE_STRUCT_BPF_CGROUP_DEV_CTX
1145 __do_bpf_program_free struct bpf_program *devices = NULL;
1146 struct lxc_cmd_rsp rsp = {0};
1147 struct lxc_conf *conf = handler->conf;
1148 struct hierarchy *unified = handler->cgroup_ops->unified;
2a63b5cb
CB
1149 int ret;
1150 struct lxc_list *it;
1151 struct device_item *device;
1152 struct bpf_program *devices_old;
1153
1154 if (req->datalen <= 0)
ea2a070b 1155 return LXC_CMD_REAP_CLIENT_FD;
2a63b5cb
CB
1156
1157 if (req->datalen != sizeof(struct device_item))
ea2a070b 1158 return LXC_CMD_REAP_CLIENT_FD;
2a63b5cb
CB
1159
1160 if (!req->data)
ea2a070b 1161 return LXC_CMD_REAP_CLIENT_FD;
2a63b5cb
CB
1162 device = (struct device_item *)req->data;
1163
1164 rsp.ret = -1;
1165 if (!unified)
1166 goto respond;
1167
1168 ret = bpf_list_add_device(conf, device);
1169 if (ret < 0)
1170 goto respond;
1171
1172 devices = bpf_program_new(BPF_PROG_TYPE_CGROUP_DEVICE);
1173 if (!devices)
1174 goto respond;
1175
1176 ret = bpf_program_init(devices);
1177 if (ret)
1178 goto respond;
1179
1180 lxc_list_for_each(it, &conf->devices) {
1181 struct device_item *cur = it->elem;
1182
1183 ret = bpf_program_append_device(devices, cur);
1184 if (ret)
1185 goto respond;
1186 }
1187
1188 ret = bpf_program_finalize(devices);
1189 if (ret)
1190 goto respond;
1191
1192 ret = bpf_program_cgroup_attach(devices, BPF_CGROUP_DEVICE,
1193 unified->container_full_path,
1194 BPF_F_ALLOW_MULTI);
1195 if (ret)
1196 goto respond;
1197
1198 /* Replace old bpf program. */
1199 devices_old = move_ptr(conf->cgroup2_devices);
1200 conf->cgroup2_devices = move_ptr(devices);
1201 devices = move_ptr(devices_old);
1202
1203 rsp.ret = 0;
1204
1205respond:
1206 ret = lxc_cmd_rsp_send(fd, &rsp);
1207 if (ret < 0)
ea2a070b 1208 return LXC_CMD_REAP_CLIENT_FD;
2a63b5cb
CB
1209
1210 return 0;
2a63b5cb 1211#else
3d0327ed 1212 return ret_set_errno(-1, ENOSYS);
2a63b5cb
CB
1213#endif
1214}
1215
191d43cc
CB
1216int lxc_cmd_console_log(const char *name, const char *lxcpath,
1217 struct lxc_console_log *log)
1218{
1219 int ret, stopped;
1220 struct lxc_cmd_console_log data;
1221 struct lxc_cmd_rr cmd;
1222
1223 data.clear = log->clear;
1224 data.read = log->read;
1225 data.read_max = *log->read_max;
1226
1227 cmd.req.cmd = LXC_CMD_CONSOLE_LOG;
1228 cmd.req.data = &data;
1229 cmd.req.datalen = sizeof(struct lxc_cmd_console_log);
1230
1231 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
1232 if (ret < 0)
1233 return ret;
1234
1235 /* There is nothing to be read from the buffer. So clear any values we
1236 * where passed to clearly indicate to the user that nothing went wrong.
1237 */
63b74cda 1238 if (cmd.rsp.ret == -ENODATA || cmd.rsp.ret == -EFAULT || cmd.rsp.ret == -ENOENT) {
191d43cc
CB
1239 *log->read_max = 0;
1240 log->data = NULL;
1241 }
1242
1243 /* This is a proper error so don't touch any values we were passed. */
1244 if (cmd.rsp.ret < 0)
1245 return cmd.rsp.ret;
1246
1247 *log->read_max = cmd.rsp.datalen;
1248 log->data = cmd.rsp.data;
1249
1250 return 0;
1251}
1252
1253static int lxc_cmd_console_log_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1254 struct lxc_handler *handler,
1255 struct lxc_epoll_descr *descr)
191d43cc
CB
1256{
1257 struct lxc_cmd_rsp rsp;
28f3b1cd 1258 uint64_t buffer_size = handler->conf->console.buffer_size;
191d43cc
CB
1259 const struct lxc_cmd_console_log *log = req->data;
1260 struct lxc_ringbuf *buf = &handler->conf->console.ringbuf;
1261
1262 rsp.ret = -EFAULT;
1263 rsp.datalen = 0;
1264 rsp.data = NULL;
28f3b1cd 1265 if (buffer_size <= 0)
191d43cc
CB
1266 goto out;
1267
5928191e
CB
1268 if (log->read || log->write_logfile)
1269 rsp.datalen = lxc_ringbuf_used(buf);
1270
191d43cc
CB
1271 if (log->read)
1272 rsp.data = lxc_ringbuf_get_read_addr(buf);
1273
1274 if (log->read_max > 0 && (log->read_max <= rsp.datalen))
1275 rsp.datalen = log->read_max;
1276
1277 /* there's nothing to read */
63b74cda 1278 rsp.ret = -ENODATA;
191d43cc 1279 if (log->read && (buf->r_off == buf->w_off))
63b74cda
CB
1280 goto out;
1281
63b74cda 1282 rsp.ret = 0;
23e0d9af 1283 if (log->clear)
43366ca2 1284 lxc_ringbuf_clear(buf); /* clear the ringbuffer */
23e0d9af 1285 else if (rsp.datalen > 0)
191d43cc
CB
1286 lxc_ringbuf_move_read_addr(buf, rsp.datalen);
1287
1288out:
1289 return lxc_cmd_rsp_send(fd, &rsp);
1290}
1291
974a8aba
CB
1292int lxc_cmd_serve_state_clients(const char *name, const char *lxcpath,
1293 lxc_state_t state)
1294{
1295 int stopped;
1296 ssize_t ret;
1297 struct lxc_cmd_rr cmd = {
6c6497ea
CB
1298 .req = {
1299 .cmd = LXC_CMD_SERVE_STATE_CLIENTS,
1300 .data = INT_TO_PTR(state)
1301 },
974a8aba
CB
1302 };
1303
1304 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
6c6497ea
CB
1305 if (ret < 0)
1306 return log_error_errno(-1, errno, "Failed to serve state clients");
974a8aba
CB
1307
1308 return 0;
1309}
1310
1311static int lxc_cmd_serve_state_clients_callback(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1312 struct lxc_handler *handler,
1313 struct lxc_epoll_descr *descr)
974a8aba
CB
1314{
1315 int ret;
1316 lxc_state_t state = PTR_TO_INT(req->data);
1317 struct lxc_cmd_rsp rsp = {0};
1318
1319 ret = lxc_serve_state_clients(handler->name, handler, state);
1320 if (ret < 0)
ea2a070b 1321 return LXC_CMD_REAP_CLIENT_FD;
974a8aba
CB
1322
1323 ret = lxc_cmd_rsp_send(fd, &rsp);
1324 if (ret < 0)
ea2a070b 1325 return LXC_CMD_REAP_CLIENT_FD;
974a8aba
CB
1326
1327 return 0;
974a8aba
CB
1328}
1329
cdb2a47f
CB
1330int lxc_cmd_seccomp_notify_add_listener(const char *name, const char *lxcpath,
1331 int fd,
1332 /* unused */ unsigned int command,
1333 /* unused */ unsigned int flags)
1334{
1335
c3e3c21a 1336#ifdef HAVE_SECCOMP_NOTIFY
cdb2a47f
CB
1337 int ret, stopped;
1338 struct lxc_cmd_rr cmd = {
1339 .req = {
1340 .cmd = LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER,
1341 .data = INT_TO_PTR(fd),
1342 },
1343 };
1344
1345 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
6c6497ea
CB
1346 if (ret < 0)
1347 return log_error_errno(-1, errno, "Failed to add seccomp listener");
cdb2a47f
CB
1348
1349 return cmd.rsp.ret;
1350#else
3d0327ed 1351 return ret_set_errno(-1, ENOSYS);
cdb2a47f
CB
1352#endif
1353}
1354
1355static int lxc_cmd_seccomp_notify_add_listener_callback(int fd,
1356 struct lxc_cmd_req *req,
1357 struct lxc_handler *handler,
1358 struct lxc_epoll_descr *descr)
1359{
1360 struct lxc_cmd_rsp rsp = {0};
cdb2a47f 1361
c3e3c21a
CB
1362#ifdef HAVE_SECCOMP_NOTIFY
1363 int ret;
f62cf1d4 1364 __do_close int recv_fd = -EBADF;
cdb2a47f 1365
c3e3c21a
CB
1366 ret = lxc_abstract_unix_recv_fds(fd, &recv_fd, 1, NULL, 0);
1367 if (ret <= 0) {
1368 rsp.ret = -errno;
1369 goto out;
cdb2a47f
CB
1370 }
1371
c3e3c21a
CB
1372 if (!handler->conf->seccomp.notifier.wants_supervision ||
1373 handler->conf->seccomp.notifier.proxy_fd < 0) {
1374 SYSERROR("No seccomp proxy fd specified");
1375 rsp.ret = -EINVAL;
1376 goto out;
1377 }
cdb2a47f 1378
c3e3c21a 1379 ret = lxc_mainloop_add_handler(descr, recv_fd, seccomp_notify_handler,
cdb2a47f 1380 handler);
c3e3c21a
CB
1381 if (ret < 0) {
1382 rsp.ret = -errno;
1383 goto out;
1384 }
68a9e3eb 1385 move_fd(recv_fd);
cdb2a47f 1386
c3e3c21a 1387out:
cdb2a47f
CB
1388#else
1389 rsp.ret = -ENOSYS;
cdb2a47f 1390
c3e3c21a
CB
1391#endif
1392 return lxc_cmd_rsp_send(fd, &rsp);
cdb2a47f
CB
1393}
1394
018051e3
CB
1395int lxc_cmd_freeze(const char *name, const char *lxcpath, int timeout)
1396{
1397 int ret, stopped;
1398 struct lxc_cmd_rr cmd = {
1399 .req = {
1400 .cmd = LXC_CMD_FREEZE,
1401 .data = INT_TO_PTR(timeout),
1402 },
1403 };
1404
1405 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
1406 if (ret <= 0 || cmd.rsp.ret < 0)
3d0327ed 1407 return log_error_errno(-1, errno, "Failed to freeze container");
018051e3
CB
1408
1409 return cmd.rsp.ret;
1410}
1411
1412static int lxc_cmd_freeze_callback(int fd, struct lxc_cmd_req *req,
1413 struct lxc_handler *handler,
1414 struct lxc_epoll_descr *descr)
1415{
1416 int timeout = PTR_TO_INT(req->data);
1417 struct lxc_cmd_rsp rsp = {
6c6497ea 1418 .ret = -ENOENT,
018051e3
CB
1419 };
1420 struct cgroup_ops *ops = handler->cgroup_ops;
1421
1973b62a 1422 if (pure_unified_layout(ops))
018051e3
CB
1423 rsp.ret = ops->freeze(ops, timeout);
1424
1425 return lxc_cmd_rsp_send(fd, &rsp);
1426}
1427
1428int lxc_cmd_unfreeze(const char *name, const char *lxcpath, int timeout)
1429{
1430 int ret, stopped;
1431 struct lxc_cmd_rr cmd = {
1432 .req = {
1433 .cmd = LXC_CMD_UNFREEZE,
1434 .data = INT_TO_PTR(timeout),
1435 },
1436 };
1437
1438 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
1439 if (ret <= 0 || cmd.rsp.ret < 0)
3d0327ed 1440 return log_error_errno(-1, errno, "Failed to unfreeze container");
018051e3
CB
1441
1442 return cmd.rsp.ret;
1443}
1444
1445static int lxc_cmd_unfreeze_callback(int fd, struct lxc_cmd_req *req,
1446 struct lxc_handler *handler,
1447 struct lxc_epoll_descr *descr)
1448{
1449 int timeout = PTR_TO_INT(req->data);
1450 struct lxc_cmd_rsp rsp = {
6c6497ea 1451 .ret = -ENOENT,
018051e3
CB
1452 };
1453 struct cgroup_ops *ops = handler->cgroup_ops;
1454
1973b62a 1455 if (pure_unified_layout(ops))
018051e3
CB
1456 rsp.ret = ops->unfreeze(ops, timeout);
1457
1458 return lxc_cmd_rsp_send(fd, &rsp);
1459}
1460
bad788b0
CB
1461int lxc_cmd_get_cgroup2_fd(const char *name, const char *lxcpath)
1462{
1463 int ret, stopped;
1464 struct lxc_cmd_rr cmd = {
1465 .req = {
1466 .cmd = LXC_CMD_GET_CGROUP2_FD,
1467 },
1468 };
1469
1470 ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
23a917e5
CB
1471 if (ret < 0)
1472 return -1;
1473
1474 if (cmd.rsp.ret < 0)
a5263e59 1475 return log_debug_errno(cmd.rsp.ret, -cmd.rsp.ret, "Failed to receive cgroup2 fd");
bad788b0
CB
1476
1477 return PTR_TO_INT(cmd.rsp.data);
1478}
1479
a900cbaf
WB
1480static int lxc_cmd_get_cgroup2_fd_callback_do(int fd, struct lxc_cmd_req *req,
1481 struct lxc_handler *handler,
1482 struct lxc_epoll_descr *descr,
1483 bool limiting_cgroup)
bad788b0
CB
1484{
1485 struct lxc_cmd_rsp rsp = {
1486 .ret = -EINVAL,
1487 };
1488 struct cgroup_ops *ops = handler->cgroup_ops;
a900cbaf 1489 int ret, send_fd;
bad788b0 1490
1973b62a 1491 if (!pure_unified_layout(ops) || !ops->unified)
bad788b0
CB
1492 return lxc_cmd_rsp_send(fd, &rsp);
1493
a900cbaf
WB
1494 send_fd = limiting_cgroup ? ops->unified->cgfd_limit
1495 : ops->unified->cgfd_con;
1496
bad788b0 1497 rsp.ret = 0;
a900cbaf 1498 ret = lxc_abstract_unix_send_fds(fd, &send_fd, 1, &rsp, sizeof(rsp));
bad788b0 1499 if (ret < 0)
a804c19b 1500 return log_error(LXC_CMD_REAP_CLIENT_FD, "Failed to send cgroup2 fd");
bad788b0
CB
1501
1502 return 0;
1503}
1504
a900cbaf
WB
1505static int lxc_cmd_get_cgroup2_fd_callback(int fd, struct lxc_cmd_req *req,
1506 struct lxc_handler *handler,
1507 struct lxc_epoll_descr *descr)
1508{
1509 return lxc_cmd_get_cgroup2_fd_callback_do(fd, req, handler, descr,
1510 false);
1511}
1512
1513static int lxc_cmd_get_limiting_cgroup2_fd_callback(int fd,
1514 struct lxc_cmd_req *req,
1515 struct lxc_handler *handler,
1516 struct lxc_epoll_descr *descr)
1517{
1518 return lxc_cmd_get_cgroup2_fd_callback_do(fd, req, handler, descr,
1519 true);
1520}
1521
ef6e34ee 1522static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
cdb2a47f
CB
1523 struct lxc_handler *handler,
1524 struct lxc_epoll_descr *descr)
724e753c 1525{
cdb2a47f
CB
1526 typedef int (*callback)(int, struct lxc_cmd_req *, struct lxc_handler *,
1527 struct lxc_epoll_descr *);
ef6e34ee
DE
1528
1529 callback cb[LXC_CMD_MAX] = {
2a63b5cb
CB
1530 [LXC_CMD_CONSOLE] = lxc_cmd_console_callback,
1531 [LXC_CMD_TERMINAL_WINCH] = lxc_cmd_terminal_winch_callback,
1532 [LXC_CMD_STOP] = lxc_cmd_stop_callback,
1533 [LXC_CMD_GET_STATE] = lxc_cmd_get_state_callback,
1534 [LXC_CMD_GET_INIT_PID] = lxc_cmd_get_init_pid_callback,
1535 [LXC_CMD_GET_CLONE_FLAGS] = lxc_cmd_get_clone_flags_callback,
1536 [LXC_CMD_GET_CGROUP] = lxc_cmd_get_cgroup_callback,
1537 [LXC_CMD_GET_CONFIG_ITEM] = lxc_cmd_get_config_item_callback,
1538 [LXC_CMD_GET_NAME] = lxc_cmd_get_name_callback,
1539 [LXC_CMD_GET_LXCPATH] = lxc_cmd_get_lxcpath_callback,
1540 [LXC_CMD_ADD_STATE_CLIENT] = lxc_cmd_add_state_client_callback,
1541 [LXC_CMD_CONSOLE_LOG] = lxc_cmd_console_log_callback,
1542 [LXC_CMD_SERVE_STATE_CLIENTS] = lxc_cmd_serve_state_clients_callback,
1543 [LXC_CMD_SECCOMP_NOTIFY_ADD_LISTENER] = lxc_cmd_seccomp_notify_add_listener_callback,
1544 [LXC_CMD_ADD_BPF_DEVICE_CGROUP] = lxc_cmd_add_bpf_device_cgroup_callback,
018051e3
CB
1545 [LXC_CMD_FREEZE] = lxc_cmd_freeze_callback,
1546 [LXC_CMD_UNFREEZE] = lxc_cmd_unfreeze_callback,
bad788b0 1547 [LXC_CMD_GET_CGROUP2_FD] = lxc_cmd_get_cgroup2_fd_callback,
746aab51 1548 [LXC_CMD_GET_INIT_PIDFD] = lxc_cmd_get_init_pidfd_callback,
a900cbaf
WB
1549 [LXC_CMD_GET_LIMITING_CGROUP] = lxc_cmd_get_limiting_cgroup_callback,
1550 [LXC_CMD_GET_LIMITING_CGROUP2_FD] = lxc_cmd_get_limiting_cgroup2_fd_callback,
f797f05e 1551 [LXC_CMD_GET_DEVPTS_FD] = lxc_cmd_get_devpts_fd_callback,
724e753c
MN
1552 };
1553
23a917e5 1554 if (req->cmd >= LXC_CMD_MAX)
769b88ea 1555 return log_trace_errno(-1, EINVAL, "Invalid command id %d", req->cmd);
23a917e5 1556
cdb2a47f 1557 return cb[req->cmd](fd, req, handler, descr);
724e753c
MN
1558}
1559
ef6e34ee 1560static void lxc_cmd_fd_cleanup(int fd, struct lxc_handler *handler,
cdb2a47f 1561 struct lxc_epoll_descr *descr, const lxc_cmd_t cmd)
724e753c 1562{
3dfe6f8d 1563 lxc_terminal_free(handler->conf, fd);
724e753c 1564 lxc_mainloop_del_handler(descr, fd);
f6fc1565 1565
cd5369b0 1566 if (cmd == LXC_CMD_ADD_STATE_CLIENT) {
ab92468c
CB
1567 struct lxc_list *cur, *next;
1568
cdb2a47f
CB
1569 lxc_list_for_each_safe(cur, &handler->conf->state_clients, next) {
1570 struct lxc_state_client *client = cur->elem;
1571
1572 if (client->clientfd != fd)
1573 continue;
1574
ab92468c
CB
1575 /*
1576 * Only kick client from list so it can't be found
1577 * anymore. The actual close happens, as for all other
1578 * file descriptors, below.
1579 */
cdb2a47f 1580 lxc_list_del(cur);
cdb2a47f
CB
1581 free(cur->elem);
1582 free(cur);
ab92468c 1583
39e2a438
CB
1584 /*
1585 * No need to walk the whole list. If we found the state
cdb2a47f
CB
1586 * client fd there can't be a second one.
1587 */
ea2a070b 1588 TRACE("Found state client fd %d in state client list for command \"%s\"", fd, lxc_cmd_str(cmd));
ab92468c 1589 break;
cdb2a47f 1590 }
39e2a438
CB
1591
1592 /*
1593 * We didn't add the state client to the list. Either because
1594 * we failed to allocate memory (unlikely) or because the state
1595 * was already reached by the time we were ready to add it. So
1596 * fallthrough and clean it up.
1597 */
ea2a070b 1598 TRACE("Closing state client fd %d for command \"%s\"", fd, lxc_cmd_str(cmd));
f6fc1565 1599 }
cd5369b0 1600
ea2a070b 1601 TRACE("Closing client fd %d for command \"%s\"", fd, lxc_cmd_str(cmd));
cd5369b0 1602 close(fd);
724e753c
MN
1603}
1604
84c92abd
DE
1605static int lxc_cmd_handler(int fd, uint32_t events, void *data,
1606 struct lxc_epoll_descr *descr)
724e753c 1607{
5265a60c 1608 __do_free void *reqdata = NULL;
724e753c 1609 int ret;
ef6e34ee 1610 struct lxc_cmd_req req;
724e753c
MN
1611 struct lxc_handler *handler = data;
1612
aae93dd3 1613 ret = lxc_abstract_unix_rcv_credential(fd, &req, sizeof(req));
ded1d23f 1614 if (ret < 0) {
ea2a070b 1615 SYSERROR("Failed to receive data on command socket for command \"%s\"", lxc_cmd_str(req.cmd));
9044b79e 1616
1617 if (errno == EACCES) {
1618 /* We don't care for the peer, just send and close. */
ea2a070b 1619 struct lxc_cmd_rsp rsp = {
f7a97743 1620 .ret = -EPERM,
ea2a070b 1621 };
9044b79e 1622
1623 lxc_cmd_rsp_send(fd, &rsp);
1624 }
1625
724e753c
MN
1626 goto out_close;
1627 }
1628
fe84a562 1629 if (ret == 0)
724e753c 1630 goto out_close;
724e753c 1631
ef6e34ee 1632 if (ret != sizeof(req)) {
ea2a070b 1633 WARN("Failed to receive full command request. Ignoring request for \"%s\"", lxc_cmd_str(req.cmd));
ef6e34ee
DE
1634 goto out_close;
1635 }
1636
ea2a070b
CB
1637 if ((req.datalen > LXC_CMD_DATA_MAX) && (req.cmd != LXC_CMD_CONSOLE_LOG)) {
1638 ERROR("Received command data length %d is too large for command \"%s\"", req.datalen, lxc_cmd_str(req.cmd));
724e753c
MN
1639 goto out_close;
1640 }
1641
ef6e34ee 1642 if (req.datalen > 0) {
5265a60c 1643 reqdata = must_realloc(NULL, req.datalen);
e3233f26 1644 ret = lxc_recv_nointr(fd, reqdata, req.datalen, 0);
ef6e34ee 1645 if (ret != req.datalen) {
ea2a070b 1646 WARN("Failed to receive full command request. Ignoring request for \"%s\"", lxc_cmd_str(req.cmd));
ef6e34ee
DE
1647 goto out_close;
1648 }
fe84a562 1649
ef6e34ee
DE
1650 req.data = reqdata;
1651 }
1652
cdb2a47f 1653 ret = lxc_cmd_process(fd, &req, handler, descr);
724e753c 1654 if (ret) {
fe84a562 1655 /* This is not an error, but only a request to close fd. */
724e753c
MN
1656 goto out_close;
1657 }
1658
1659out:
f7a97743 1660 return LXC_MAINLOOP_CONTINUE;
fe84a562 1661
724e753c 1662out_close:
f6fc1565 1663 lxc_cmd_fd_cleanup(fd, handler, descr, req.cmd);
724e753c
MN
1664 goto out;
1665}
1666
84c92abd
DE
1667static int lxc_cmd_accept(int fd, uint32_t events, void *data,
1668 struct lxc_epoll_descr *descr)
724e753c 1669{
f62cf1d4 1670 __do_close int connection = -EBADF;
fe84a562 1671 int opt = 1, ret = -1;
724e753c
MN
1672
1673 connection = accept(fd, NULL, 0);
6c6497ea
CB
1674 if (connection < 0)
1675 return log_error_errno(LXC_MAINLOOP_ERROR, errno, "Failed to accept connection to run command");
724e753c 1676
fe84a562 1677 ret = fcntl(connection, F_SETFD, FD_CLOEXEC);
6c6497ea
CB
1678 if (ret < 0)
1679 return log_error_errno(ret, errno, "Failed to set close-on-exec on incoming command connection");
9ccb2dbc 1680
fe84a562 1681 ret = setsockopt(connection, SOL_SOCKET, SO_PASSCRED, &opt, sizeof(opt));
6c6497ea
CB
1682 if (ret < 0)
1683 return log_error_errno(ret, errno, "Failed to enable necessary credentials on command socket");
724e753c 1684
ef6e34ee 1685 ret = lxc_mainloop_add_handler(descr, connection, lxc_cmd_handler, data);
6c6497ea
CB
1686 if (ret)
1687 return log_error(ret, "Failed to add command handler");
724e753c 1688
ea2a070b 1689 TRACE("Accepted new client as fd %d on command server fd %d", connection, fd);
240fecd0 1690 move_fd(connection);
724e753c 1691 return ret;
724e753c
MN
1692}
1693
9dfa4041 1694int lxc_cmd_init(const char *name, const char *lxcpath, const char *suffix)
724e753c 1695{
f62cf1d4 1696 __do_close int fd = -EBADF;
c13e7111 1697 int ret;
b1234129 1698 char path[LXC_AUDS_ADDR_LEN] = {0};
724e753c 1699
5b46db1a 1700 ret = lxc_make_abstract_socket_name(path, sizeof(path), name, lxcpath, NULL, suffix);
fe84a562 1701 if (ret < 0)
9ba8130c 1702 return -1;
724e753c 1703
aae93dd3 1704 fd = lxc_abstract_unix_open(path, SOCK_STREAM, 0);
724e753c 1705 if (fd < 0) {
08aa08fe 1706 if (errno == EADDRINUSE)
fe84a562 1707 ERROR("Container \"%s\" appears to be already running", name);
6d1400b5 1708
6c6497ea 1709 return log_error_errno(-1, errno, "Failed to create command socket %s", &path[1]);
724e753c
MN
1710 }
1711
fe84a562 1712 ret = fcntl(fd, F_SETFD, FD_CLOEXEC);
6c6497ea
CB
1713 if (ret < 0)
1714 return log_error_errno(-1, errno, "Failed to set FD_CLOEXEC on command socket file descriptor");
91480a0f 1715
6c6497ea 1716 return log_trace(move_fd(fd), "Created abstract unix socket \"%s\"", &path[1]);
d2e30e99
DE
1717}
1718
fe84a562 1719int lxc_cmd_mainloop_add(const char *name, struct lxc_epoll_descr *descr,
ef6e34ee 1720 struct lxc_handler *handler)
d2e30e99 1721{
fe84a562 1722 int ret;
d2e30e99 1723
ea2a070b 1724 ret = lxc_mainloop_add_handler(descr, handler->conf->maincmd_fd, lxc_cmd_accept, handler);
6c6497ea 1725 if (ret < 0)
ea2a070b 1726 return log_error(ret, "Failed to add handler for command socket fd %d", handler->conf->maincmd_fd);
724e753c
MN
1727
1728 return ret;
1729}