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