test-cpu-set-util.c: fix typo in comment (#6916)
This commit is contained in:
+213
-55
@@ -29,6 +29,7 @@
|
||||
#include <linux/sctp.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "bpf-firewall.h"
|
||||
#include "bus-error.h"
|
||||
#include "bus-util.h"
|
||||
#include "copy.h"
|
||||
@@ -37,6 +38,7 @@
|
||||
#include "exit-status.h"
|
||||
#include "fd-util.h"
|
||||
#include "format-util.h"
|
||||
#include "in-addr-util.h"
|
||||
#include "io-util.h"
|
||||
#include "label.h"
|
||||
#include "log.h"
|
||||
@@ -56,7 +58,6 @@
|
||||
#include "unit-name.h"
|
||||
#include "unit.h"
|
||||
#include "user-util.h"
|
||||
#include "in-addr-util.h"
|
||||
|
||||
struct SocketPeer {
|
||||
unsigned n_ref;
|
||||
@@ -852,6 +853,8 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
|
||||
exec_command_dump_list(s->exec_command[c], f, prefix2);
|
||||
}
|
||||
|
||||
cgroup_context_dump(&s->cgroup_context, f, prefix);
|
||||
}
|
||||
|
||||
static int instance_from_socket(int fd, unsigned nr, char **instance) {
|
||||
@@ -1435,6 +1438,102 @@ no_label:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int socket_address_listen_do(
|
||||
Socket *s,
|
||||
const SocketAddress *address,
|
||||
const char *label) {
|
||||
|
||||
assert(s);
|
||||
assert(address);
|
||||
|
||||
return socket_address_listen(
|
||||
address,
|
||||
SOCK_CLOEXEC|SOCK_NONBLOCK,
|
||||
s->backlog,
|
||||
s->bind_ipv6_only,
|
||||
s->bind_to_device,
|
||||
s->reuse_port,
|
||||
s->free_bind,
|
||||
s->transparent,
|
||||
s->directory_mode,
|
||||
s->socket_mode,
|
||||
label);
|
||||
}
|
||||
|
||||
static int socket_address_listen_in_cgroup(
|
||||
Socket *s,
|
||||
const SocketAddress *address,
|
||||
const char *label) {
|
||||
|
||||
_cleanup_close_pair_ int pair[2] = { -1, -1 };
|
||||
int fd, r;
|
||||
pid_t pid;
|
||||
|
||||
assert(s);
|
||||
assert(address);
|
||||
|
||||
/* This is a wrapper around socket_address_listen(), that forks off a helper process inside the socket's cgroup
|
||||
* in which the socket is actually created. This way we ensure the socket is actually properly attached to the
|
||||
* unit's cgroup for the purpose of BPF filtering and such. */
|
||||
|
||||
if (!IN_SET(address->sockaddr.sa.sa_family, AF_INET, AF_INET6))
|
||||
goto shortcut; /* BPF filtering only applies to IPv4 + IPv6, shortcut things for other protocols */
|
||||
|
||||
r = bpf_firewall_supported();
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) /* If BPF firewalling isn't supported anyway — there's no point in this forking complexity */
|
||||
goto shortcut;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, pair) < 0)
|
||||
return log_unit_error_errno(UNIT(s), errno, "Failed to create communication channel: %m");
|
||||
|
||||
r = unit_fork_helper_process(UNIT(s), &pid);
|
||||
if (r < 0)
|
||||
return log_unit_error_errno(UNIT(s), r, "Failed to fork off listener stub process: %m");
|
||||
if (r == 0) {
|
||||
/* Child */
|
||||
|
||||
pair[0] = safe_close(pair[0]);
|
||||
|
||||
fd = socket_address_listen_do(s, address, label);
|
||||
if (fd < 0) {
|
||||
log_unit_error_errno(UNIT(s), fd, "Failed to create listening socket: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
r = send_one_fd(pair[1], fd, 0);
|
||||
if (r < 0) {
|
||||
log_unit_error_errno(UNIT(s), r, "Failed to send listening socket to parent: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
pair[1] = safe_close(pair[1]);
|
||||
fd = receive_one_fd(pair[0], 0);
|
||||
|
||||
/* We synchronously wait for the helper, as it shouldn't be slow */
|
||||
r = wait_for_terminate_and_warn("listen-cgroup-helper", pid, false);
|
||||
if (r < 0) {
|
||||
safe_close(fd);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (fd < 0)
|
||||
return log_unit_error_errno(UNIT(s), fd, "Failed to receive listening socket: %m");
|
||||
|
||||
return fd;
|
||||
|
||||
shortcut:
|
||||
fd = socket_address_listen_do(s, address, label);
|
||||
if (fd < 0)
|
||||
return log_error_errno(fd, "Failed to create listening socket: %m");
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int socket_open_fds(Socket *s) {
|
||||
_cleanup_(mac_selinux_freep) char *label = NULL;
|
||||
bool know_label = false;
|
||||
@@ -1478,18 +1577,7 @@ static int socket_open_fds(Socket *s) {
|
||||
break;
|
||||
}
|
||||
|
||||
r = socket_address_listen(
|
||||
&p->address,
|
||||
SOCK_CLOEXEC|SOCK_NONBLOCK,
|
||||
s->backlog,
|
||||
s->bind_ipv6_only,
|
||||
s->bind_to_device,
|
||||
s->reuse_port,
|
||||
s->free_bind,
|
||||
s->transparent,
|
||||
s->directory_mode,
|
||||
s->socket_mode,
|
||||
label);
|
||||
r = socket_address_listen_in_cgroup(s, &p->address, label);
|
||||
if (r < 0)
|
||||
goto rollback;
|
||||
|
||||
@@ -1773,9 +1861,10 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) {
|
||||
assert(_pid);
|
||||
|
||||
(void) unit_realize_cgroup(UNIT(s));
|
||||
if (s->reset_cpu_usage) {
|
||||
(void) unit_reset_cpu_usage(UNIT(s));
|
||||
s->reset_cpu_usage = false;
|
||||
if (s->reset_accounting) {
|
||||
(void) unit_reset_cpu_accounting(UNIT(s));
|
||||
(void) unit_reset_ip_accounting(UNIT(s));
|
||||
s->reset_accounting = false;
|
||||
}
|
||||
|
||||
r = unit_setup_exec_runtime(UNIT(s));
|
||||
@@ -1826,27 +1915,23 @@ static int socket_chown(Socket *s, pid_t *_pid) {
|
||||
/* We have to resolve the user names out-of-process, hence
|
||||
* let's fork here. It's messy, but well, what can we do? */
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0)
|
||||
return -errno;
|
||||
|
||||
if (pid == 0) {
|
||||
SocketPort *p;
|
||||
r = unit_fork_helper_process(UNIT(s), &pid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0) {
|
||||
uid_t uid = UID_INVALID;
|
||||
gid_t gid = GID_INVALID;
|
||||
int ret;
|
||||
SocketPort *p;
|
||||
|
||||
(void) default_signals(SIGNALS_CRASH_HANDLER, SIGNALS_IGNORE, -1);
|
||||
(void) ignore_signals(SIGPIPE, -1);
|
||||
log_forget_fds();
|
||||
/* Child */
|
||||
|
||||
if (!isempty(s->user)) {
|
||||
const char *user = s->user;
|
||||
|
||||
r = get_user_creds(&user, &uid, &gid, NULL, NULL);
|
||||
if (r < 0) {
|
||||
ret = EXIT_USER;
|
||||
goto fail_child;
|
||||
log_unit_error_errno(UNIT(s), r, "Failed to resolve user %s: %m", user);
|
||||
_exit(EXIT_USER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1855,8 +1940,8 @@ static int socket_chown(Socket *s, pid_t *_pid) {
|
||||
|
||||
r = get_group_creds(&group, &gid);
|
||||
if (r < 0) {
|
||||
ret = EXIT_GROUP;
|
||||
goto fail_child;
|
||||
log_unit_error_errno(UNIT(s), r, "Failed to resolve group %s: %m", group);
|
||||
_exit(EXIT_GROUP);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1872,19 +1957,12 @@ static int socket_chown(Socket *s, pid_t *_pid) {
|
||||
continue;
|
||||
|
||||
if (chown(path, uid, gid) < 0) {
|
||||
r = -errno;
|
||||
ret = EXIT_CHOWN;
|
||||
goto fail_child;
|
||||
log_unit_error_errno(UNIT(s), errno, "Failed to chown(): %m");
|
||||
_exit(EXIT_CHOWN);
|
||||
}
|
||||
}
|
||||
|
||||
_exit(0);
|
||||
|
||||
fail_child:
|
||||
log_open();
|
||||
log_error_errno(r, "Failed to chown socket at step %s: %m", exit_status_to_string(ret, EXIT_STATUS_SYSTEMD));
|
||||
|
||||
_exit(ret);
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
r = unit_watch_pid(UNIT(s), pid);
|
||||
@@ -2371,7 +2449,7 @@ static int socket_start(Unit *u) {
|
||||
return r;
|
||||
|
||||
s->result = SOCKET_SUCCESS;
|
||||
s->reset_cpu_usage = true;
|
||||
s->reset_accounting = true;
|
||||
|
||||
socket_enter_start_pre(s);
|
||||
return 1;
|
||||
@@ -2696,6 +2774,97 @@ _pure_ static bool socket_check_gc(Unit *u) {
|
||||
return s->n_connections > 0;
|
||||
}
|
||||
|
||||
static int socket_accept_do(Socket *s, int fd) {
|
||||
int cfd;
|
||||
|
||||
assert(s);
|
||||
assert(fd >= 0);
|
||||
|
||||
for (;;) {
|
||||
cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK);
|
||||
if (cfd < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
return -errno;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return cfd;
|
||||
}
|
||||
|
||||
static int socket_accept_in_cgroup(Socket *s, SocketPort *p, int fd) {
|
||||
_cleanup_close_pair_ int pair[2] = { -1, -1 };
|
||||
int cfd, r;
|
||||
pid_t pid;
|
||||
|
||||
assert(s);
|
||||
assert(p);
|
||||
assert(fd >= 0);
|
||||
|
||||
/* Similar to socket_address_listen_in_cgroup(), but for accept() rathern than socket(): make sure that any
|
||||
* connection socket is also properly associated with the cgroup. */
|
||||
|
||||
if (!IN_SET(p->address.sockaddr.sa.sa_family, AF_INET, AF_INET6))
|
||||
goto shortcut;
|
||||
|
||||
r = bpf_firewall_supported();
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
goto shortcut;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, pair) < 0)
|
||||
return log_unit_error_errno(UNIT(s), errno, "Failed to create communication channel: %m");
|
||||
|
||||
r = unit_fork_helper_process(UNIT(s), &pid);
|
||||
if (r < 0)
|
||||
return log_unit_error_errno(UNIT(s), r, "Failed to fork off accept stub process: %m");
|
||||
if (r == 0) {
|
||||
/* Child */
|
||||
|
||||
pair[0] = safe_close(pair[0]);
|
||||
|
||||
cfd = socket_accept_do(s, fd);
|
||||
if (cfd < 0) {
|
||||
log_unit_error_errno(UNIT(s), cfd, "Failed to accept connection socket: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
r = send_one_fd(pair[1], cfd, 0);
|
||||
if (r < 0) {
|
||||
log_unit_error_errno(UNIT(s), r, "Failed to send connection socket to parent: %m");
|
||||
_exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
_exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
pair[1] = safe_close(pair[1]);
|
||||
cfd = receive_one_fd(pair[0], 0);
|
||||
|
||||
/* We synchronously wait for the helper, as it shouldn't be slow */
|
||||
r = wait_for_terminate_and_warn("accept-cgroup-helper", pid, false);
|
||||
if (r < 0) {
|
||||
safe_close(cfd);
|
||||
return r;
|
||||
}
|
||||
|
||||
if (cfd < 0)
|
||||
return log_unit_error_errno(UNIT(s), cfd, "Failed to receive connection socket: %m");
|
||||
|
||||
return cfd;
|
||||
|
||||
shortcut:
|
||||
cfd = socket_accept_do(s, fd);
|
||||
if (cfd < 0)
|
||||
return log_unit_error_errno(UNIT(s), cfd, "Failed to accept connection socket: %m");
|
||||
|
||||
return cfd;
|
||||
}
|
||||
|
||||
static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents, void *userdata) {
|
||||
SocketPort *p = userdata;
|
||||
int cfd = -1;
|
||||
@@ -2721,20 +2890,9 @@ static int socket_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
|
||||
p->type == SOCKET_SOCKET &&
|
||||
socket_address_can_accept(&p->address)) {
|
||||
|
||||
for (;;) {
|
||||
|
||||
cfd = accept4(fd, NULL, NULL, SOCK_NONBLOCK);
|
||||
if (cfd < 0) {
|
||||
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
log_unit_error_errno(UNIT(p->socket), errno, "Failed to accept socket: %m");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
cfd = socket_accept_in_cgroup(p->socket, p, fd);
|
||||
if (cfd < 0)
|
||||
goto fail;
|
||||
|
||||
socket_apply_socket_options(p->socket, cfd);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user