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