mirror of
https://github.com/systemd/systemd-stable.git
synced 2024-12-24 21:34:08 +03:00
Merge pull request #14099 from keszybz/machine-ref-unref-fix
Fix for the issue when machine cannot be started second time, and better nspawn logging
This commit is contained in:
commit
58c0663b97
@ -754,7 +754,7 @@
|
||||
container, with the exception of the loopback device and those
|
||||
specified with <option>--network-interface=</option> and
|
||||
configured with <option>--network-veth</option>. If this
|
||||
option is specified, the CAP_NET_ADMIN capability will be
|
||||
option is specified, the <constant>CAP_NET_ADMIN</constant> capability will be
|
||||
added to the set of capabilities the container retains. The
|
||||
latter may be disabled by using <option>--drop-capability=</option>.
|
||||
If this option is not specified (or implied by one of the options
|
||||
@ -943,17 +943,27 @@
|
||||
<varlistentry>
|
||||
<term><option>--capability=</option></term>
|
||||
|
||||
<listitem><para>List one or more additional capabilities to grant the container.
|
||||
Takes a comma-separated list of capability names, see
|
||||
<citerefentry project='man-pages'><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
<listitem><para>List one or more additional capabilities to grant the container. Takes a
|
||||
comma-separated list of capability names, see <citerefentry
|
||||
project='man-pages'><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></citerefentry>
|
||||
for more information. Note that the following capabilities will be granted in any way:
|
||||
CAP_AUDIT_CONTROL, CAP_AUDIT_WRITE, CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH,
|
||||
CAP_FOWNER, CAP_FSETID, CAP_IPC_OWNER, CAP_KILL, CAP_LEASE, CAP_LINUX_IMMUTABLE,
|
||||
CAP_MKNOD, CAP_NET_BIND_SERVICE, CAP_NET_BROADCAST, CAP_NET_RAW, CAP_SETFCAP,
|
||||
CAP_SETGID, CAP_SETPCAP, CAP_SETUID, CAP_SYS_ADMIN, CAP_SYS_BOOT, CAP_SYS_CHROOT,
|
||||
CAP_SYS_NICE, CAP_SYS_PTRACE, CAP_SYS_RESOURCE, CAP_SYS_TTY_CONFIG. Also CAP_NET_ADMIN
|
||||
is retained if <option>--private-network</option> is specified. If the special value
|
||||
<literal>all</literal> is passed, all capabilities are retained.</para></listitem>
|
||||
<constant>CAP_AUDIT_CONTROL</constant>, <constant>CAP_AUDIT_WRITE</constant>,
|
||||
<constant>CAP_CHOWN</constant>, <constant>CAP_DAC_OVERRIDE</constant>,
|
||||
<constant>CAP_DAC_READ_SEARCH</constant>, <constant>CAP_FOWNER</constant>,
|
||||
<constant>CAP_FSETID</constant>, <constant>CAP_IPC_OWNER</constant>, <constant>CAP_KILL</constant>,
|
||||
<constant>CAP_LEASE</constant>, <constant>CAP_LINUX_IMMUTABLE</constant>,
|
||||
<constant>CAP_MKNOD</constant>, <constant>CAP_NET_BIND_SERVICE</constant>,
|
||||
<constant>CAP_NET_BROADCAST</constant>, <constant>CAP_NET_RAW</constant>,
|
||||
<constant>CAP_SETFCAP</constant>, <constant>CAP_SETGID</constant>, <constant>CAP_SETPCAP</constant>,
|
||||
<constant>CAP_SETUID</constant>, <constant>CAP_SYS_ADMIN</constant>,
|
||||
<constant>CAP_SYS_BOOT</constant>, <constant>CAP_SYS_CHROOT</constant>,
|
||||
<constant>CAP_SYS_NICE</constant>, <constant>CAP_SYS_PTRACE</constant>,
|
||||
<constant>CAP_SYS_RESOURCE</constant>, <constant>CAP_SYS_TTY_CONFIG</constant>. Also
|
||||
<constant>CAP_NET_ADMIN</constant> is retained if <option>--private-network</option> is specified.
|
||||
If the special value <literal>all</literal> is passed, all capabilities are retained.</para>
|
||||
|
||||
<para>If the special value of <literal>help</literal> is passed, the program will print known
|
||||
capability names and exit.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@ -962,7 +972,10 @@
|
||||
<listitem><para>Specify one or more additional capabilities to
|
||||
drop for the container. This allows running the container with
|
||||
fewer capabilities than the default (see
|
||||
above).</para></listitem>
|
||||
above).</para>
|
||||
|
||||
<para>If the special value of <literal>help</literal> is passed, the program will print known
|
||||
capability names and exit.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -330,36 +330,107 @@ int machine_load(Machine *m) {
|
||||
return r;
|
||||
}
|
||||
|
||||
static int machine_start_scope(Machine *m, sd_bus_message *properties, sd_bus_error *error) {
|
||||
static int machine_start_scope(
|
||||
Machine *machine,
|
||||
sd_bus_message *more_properties,
|
||||
sd_bus_error *error) {
|
||||
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
|
||||
_cleanup_free_ char *escaped = NULL, *unit = NULL;
|
||||
const char *description;
|
||||
int r;
|
||||
|
||||
assert(machine);
|
||||
assert(machine->leader > 0);
|
||||
assert(!machine->unit);
|
||||
|
||||
escaped = unit_name_escape(machine->name);
|
||||
if (!escaped)
|
||||
return log_oom();
|
||||
|
||||
unit = strjoin("machine-", escaped, ".scope");
|
||||
if (!unit)
|
||||
return log_oom();
|
||||
|
||||
r = sd_bus_message_new_method_call(
|
||||
machine->manager->bus,
|
||||
&m,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"StartTransientUnit");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append(m, "ss", unit, "fail");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_open_container(m, 'a', "(sv)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append(m, "(sv)", "Slice", "s", SPECIAL_MACHINE_SLICE);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
description = strjoina(machine->class == MACHINE_VM ? "Virtual Machine " : "Container ", machine->name);
|
||||
r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)(sv)",
|
||||
"PIDs", "au", 1, machine->leader,
|
||||
"Delegate", "b", 1,
|
||||
"CollectMode", "s", "inactive-or-failed",
|
||||
"AddRef", "b", 1,
|
||||
"TasksMax", "t", UINT64_C(16384));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (more_properties) {
|
||||
r = sd_bus_message_copy(m, more_properties, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_bus_message_close_container(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append(m, "a(sa(sv))", 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_call(NULL, m, 0, error, &reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
machine->unit = TAKE_PTR(unit);
|
||||
machine->referenced = true;
|
||||
|
||||
const char *job;
|
||||
r = sd_bus_message_read(reply, "o", &job);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return free_and_strdup(&machine->scope_job, job);
|
||||
}
|
||||
|
||||
static int machine_ensure_scope(Machine *m, sd_bus_message *properties, sd_bus_error *error) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(m->class != MACHINE_HOST);
|
||||
|
||||
if (!m->unit) {
|
||||
_cleanup_free_ char *escaped = NULL, *scope = NULL;
|
||||
char *description, *job = NULL;
|
||||
int r;
|
||||
|
||||
escaped = unit_name_escape(m->name);
|
||||
if (!escaped)
|
||||
return log_oom();
|
||||
|
||||
scope = strjoin("machine-", escaped, ".scope");
|
||||
if (!scope)
|
||||
return log_oom();
|
||||
|
||||
description = strjoina(m->class == MACHINE_VM ? "Virtual Machine " : "Container ", m->name);
|
||||
|
||||
r = manager_start_scope(m->manager, scope, m->leader, SPECIAL_MACHINE_SLICE, description, properties, error, &job);
|
||||
r = machine_start_scope(m, properties, error);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to start machine scope: %s", bus_error_message(error, r));
|
||||
|
||||
m->unit = TAKE_PTR(scope);
|
||||
m->referenced = true;
|
||||
free_and_replace(m->scope_job, job);
|
||||
}
|
||||
|
||||
if (m->unit)
|
||||
hashmap_put(m->manager->machine_units, m->unit, m);
|
||||
assert(m->unit);
|
||||
hashmap_put(m->manager->machine_units, m->unit, m);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -380,7 +451,7 @@ int machine_start(Machine *m, sd_bus_message *properties, sd_bus_error *error) {
|
||||
return r;
|
||||
|
||||
/* Create cgroup */
|
||||
r = machine_start_scope(m, properties, error);
|
||||
r = machine_ensure_scope(m, properties, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -404,49 +475,31 @@ int machine_start(Machine *m, sd_bus_message *properties, sd_bus_error *error) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int machine_stop_scope(Machine *m) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
char *job = NULL;
|
||||
int r, q;
|
||||
|
||||
assert(m);
|
||||
assert(m->class != MACHINE_HOST);
|
||||
|
||||
if (!m->unit)
|
||||
return 0;
|
||||
|
||||
r = manager_stop_unit(m->manager, m->unit, &error, &job);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to stop machine scope: %s", bus_error_message(&error, r));
|
||||
sd_bus_error_free(&error);
|
||||
} else
|
||||
free_and_replace(m->scope_job, job);
|
||||
|
||||
if (m->referenced) {
|
||||
q = manager_unref_unit(m->manager, m->unit, &error);
|
||||
if (q < 0)
|
||||
log_warning_errno(q, "Failed to drop reference to machine scope, ignoring: %s", bus_error_message(&error, r));
|
||||
m->referenced = false;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int machine_stop(Machine *m) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (!IN_SET(m->class, MACHINE_CONTAINER, MACHINE_VM))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
r = machine_stop_scope(m);
|
||||
if (m->unit) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
char *job = NULL;
|
||||
|
||||
r = manager_stop_unit(m->manager, m->unit, &error, &job);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to stop machine scope: %s", bus_error_message(&error, r));
|
||||
|
||||
free_and_replace(m->scope_job, job);
|
||||
}
|
||||
|
||||
m->stopping = true;
|
||||
|
||||
machine_save(m);
|
||||
(void) manager_enqueue_nscd_cache_flush(m->manager);
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int machine_finalize(Machine *m) {
|
||||
@ -583,6 +636,18 @@ void machine_release_unit(Machine *m) {
|
||||
if (!m->unit)
|
||||
return;
|
||||
|
||||
if (m->referenced) {
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
int r;
|
||||
|
||||
r = manager_unref_unit(m->manager, m->unit, &error);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to drop reference to machine scope, ignoring: %s",
|
||||
bus_error_message(&error, r));
|
||||
|
||||
m->referenced = false;
|
||||
}
|
||||
|
||||
(void) hashmap_remove(m->manager->machine_units, m->unit);
|
||||
m->unit = mfree(m->unit);
|
||||
}
|
||||
|
@ -1294,98 +1294,6 @@ int match_reloading(sd_bus_message *message, void *userdata, sd_bus_error *error
|
||||
return 0;
|
||||
}
|
||||
|
||||
int manager_start_scope(
|
||||
Manager *manager,
|
||||
const char *scope,
|
||||
pid_t pid,
|
||||
const char *slice,
|
||||
const char *description,
|
||||
sd_bus_message *more_properties,
|
||||
sd_bus_error *error,
|
||||
char **job) {
|
||||
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
|
||||
int r;
|
||||
|
||||
assert(manager);
|
||||
assert(scope);
|
||||
assert(pid > 1);
|
||||
|
||||
r = sd_bus_message_new_method_call(
|
||||
manager->bus,
|
||||
&m,
|
||||
"org.freedesktop.systemd1",
|
||||
"/org/freedesktop/systemd1",
|
||||
"org.freedesktop.systemd1.Manager",
|
||||
"StartTransientUnit");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_open_container(m, 'a', "(sv)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!isempty(slice)) {
|
||||
r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (!isempty(description)) {
|
||||
r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_bus_message_append(m, "(sv)(sv)(sv)(sv)(sv)",
|
||||
"PIDs", "au", 1, pid,
|
||||
"Delegate", "b", 1,
|
||||
"CollectMode", "s", "inactive-or-failed",
|
||||
"AddRef", "b", 1,
|
||||
"TasksMax", "t", UINT64_C(16384));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (more_properties) {
|
||||
r = sd_bus_message_copy(m, more_properties, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = sd_bus_message_close_container(m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_append(m, "a(sa(sv))", 0);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_call(manager->bus, m, 0, error, &reply);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (job) {
|
||||
const char *j;
|
||||
char *copy;
|
||||
|
||||
r = sd_bus_message_read(reply, "o", &j);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
copy = strdup(j);
|
||||
if (!copy)
|
||||
return -ENOMEM;
|
||||
|
||||
*job = copy;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int manager_unref_unit(
|
||||
Manager *m,
|
||||
const char *unit,
|
||||
|
@ -49,7 +49,6 @@ int match_unit_removed(sd_bus_message *message, void *userdata, sd_bus_error *er
|
||||
int match_properties_changed(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *error);
|
||||
|
||||
int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, sd_bus_message *more_properties, sd_bus_error *error, char **job);
|
||||
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job);
|
||||
int manager_kill_unit(Manager *manager, const char *unit, int signo, sd_bus_error *error);
|
||||
int manager_unref_unit(Manager *m, const char *unit, sd_bus_error *error);
|
||||
|
@ -139,11 +139,10 @@ static int seccomp_add_default_syscall_filter(
|
||||
*/
|
||||
};
|
||||
|
||||
int r;
|
||||
size_t i;
|
||||
char **p;
|
||||
int r;
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(whitelist); i++) {
|
||||
for (size_t i = 0; i < ELEMENTSOF(whitelist); i++) {
|
||||
if (whitelist[i].capability != 0 && (cap_list_retain & (1ULL << whitelist[i].capability)) == 0)
|
||||
continue;
|
||||
|
||||
@ -153,7 +152,7 @@ static int seccomp_add_default_syscall_filter(
|
||||
}
|
||||
|
||||
STRV_FOREACH(p, syscall_whitelist) {
|
||||
r = seccomp_add_syscall_filter_item(ctx, *p, SCMP_ACT_ALLOW, syscall_blacklist, false);
|
||||
r = seccomp_add_syscall_filter_item(ctx, *p, SCMP_ACT_ALLOW, syscall_blacklist, true);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to add rule for system call %s on %s, ignoring: %m",
|
||||
*p, seccomp_arch_to_string(arch));
|
||||
|
@ -492,6 +492,46 @@ static int detect_unified_cgroup_hierarchy_from_image(const char *directory) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int parse_capability_spec(const char *spec, uint64_t *ret_mask) {
|
||||
uint64_t mask = 0;
|
||||
int r;
|
||||
|
||||
for (;;) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
|
||||
r = extract_first_word(&spec, &t, ",", 0);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse capability %s.", t);
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
if (streq(t, "help")) {
|
||||
for (int i = 0; i < capability_list_length(); i++) {
|
||||
const char *name;
|
||||
|
||||
name = capability_to_name(i);
|
||||
if (name)
|
||||
puts(name);
|
||||
}
|
||||
|
||||
return 0; /* quit */
|
||||
}
|
||||
|
||||
if (streq(t, "all"))
|
||||
mask = (uint64_t) -1;
|
||||
else {
|
||||
r = capability_from_name(t);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse capability %s.", t);
|
||||
|
||||
mask |= 1ULL << r;
|
||||
}
|
||||
}
|
||||
|
||||
*ret_mask = mask;
|
||||
return 1; /* continue */
|
||||
}
|
||||
|
||||
static int parse_share_ns_env(const char *name, unsigned long ns_flag) {
|
||||
int r;
|
||||
|
||||
@ -695,7 +735,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
};
|
||||
|
||||
int c, r;
|
||||
const char *p;
|
||||
uint64_t plus = 0, minus = 0;
|
||||
bool mask_all_settings = false, mask_no_settings = false;
|
||||
|
||||
@ -937,37 +976,18 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
|
||||
case ARG_CAPABILITY:
|
||||
case ARG_DROP_CAPABILITY: {
|
||||
p = optarg;
|
||||
for (;;) {
|
||||
_cleanup_free_ char *t = NULL;
|
||||
|
||||
r = extract_first_word(&p, &t, ",", 0);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse capability %s.", t);
|
||||
if (r == 0)
|
||||
break;
|
||||
|
||||
if (streq(t, "all")) {
|
||||
if (c == ARG_CAPABILITY)
|
||||
plus = (uint64_t) -1;
|
||||
else
|
||||
minus = (uint64_t) -1;
|
||||
} else {
|
||||
r = capability_from_name(t);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse capability %s.", t);
|
||||
|
||||
if (c == ARG_CAPABILITY)
|
||||
plus |= 1ULL << r;
|
||||
else
|
||||
minus |= 1ULL << r;
|
||||
}
|
||||
}
|
||||
uint64_t m;
|
||||
r = parse_capability_spec(optarg, &m);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
if (c == ARG_CAPABILITY)
|
||||
plus |= m;
|
||||
else
|
||||
minus |= m;
|
||||
arg_settings_mask |= SETTING_CAPABILITY;
|
||||
break;
|
||||
}
|
||||
|
||||
case ARG_NO_NEW_PRIVILEGES:
|
||||
r = parse_boolean(optarg);
|
||||
if (r < 0)
|
||||
|
@ -9,7 +9,7 @@
|
||||
#include "resolved-dns-stream.h"
|
||||
#include "resolved-dnstls.h"
|
||||
|
||||
#define PRIORTY_STRING "NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2"
|
||||
#define TLS_PROTOCOL_PRIORITY "NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2"
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(gnutls_session_t, gnutls_deinit);
|
||||
|
||||
static ssize_t dnstls_stream_writev(gnutls_transport_ptr_t p, const giovec_t *iov, int iovcnt) {
|
||||
@ -38,7 +38,7 @@ int dnstls_stream_connect_tls(DnsStream *stream, DnsServer *server) {
|
||||
return r;
|
||||
|
||||
/* As DNS-over-TLS is a recent protocol, older TLS versions can be disabled */
|
||||
r = gnutls_priority_set_direct(gs, PRIORTY_STRING, NULL);
|
||||
r = gnutls_priority_set_direct(gs, TLS_PROTOCOL_PRIORITY, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user