Compare commits
17 Commits
bdf2357c12
...
78af8a798a
Author | SHA1 | Date |
---|---|---|
Zbigniew Jędrzejewski-Szmek | 78af8a798a | |
Zbigniew Jędrzejewski-Szmek | 58c0663b97 | |
Pascal de Bruijn | b4e2236a72 | |
Zbigniew Jędrzejewski-Szmek | 62092b2fae | |
Lennart Poettering | f1194f5d59 | |
Lennart Poettering | c4fe0cbc17 | |
Lennart Poettering | 88a36d3690 | |
Lennart Poettering | a0c41de277 | |
Lennart Poettering | 45a6c96598 | |
Zbigniew Jędrzejewski-Szmek | 698876640d | |
Zbigniew Jędrzejewski-Szmek | eec12b7756 | |
Zbigniew Jędrzejewski-Szmek | a01ecfa982 | |
Zbigniew Jędrzejewski-Szmek | af22794712 | |
Zbigniew Jędrzejewski-Szmek | f47bd09749 | |
Zbigniew Jędrzejewski-Szmek | ec56251533 | |
Zbigniew Jędrzejewski-Szmek | 8a99bd0c46 | |
Zbigniew Jędrzejewski-Szmek | 7f95bb22d3 |
|
@ -754,7 +754,7 @@
|
||||||
container, with the exception of the loopback device and those
|
container, with the exception of the loopback device and those
|
||||||
specified with <option>--network-interface=</option> and
|
specified with <option>--network-interface=</option> and
|
||||||
configured with <option>--network-veth</option>. If this
|
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
|
added to the set of capabilities the container retains. The
|
||||||
latter may be disabled by using <option>--drop-capability=</option>.
|
latter may be disabled by using <option>--drop-capability=</option>.
|
||||||
If this option is not specified (or implied by one of the options
|
If this option is not specified (or implied by one of the options
|
||||||
|
@ -943,17 +943,27 @@
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term><option>--capability=</option></term>
|
<term><option>--capability=</option></term>
|
||||||
|
|
||||||
<listitem><para>List one or more additional capabilities to grant the container.
|
<listitem><para>List one or more additional capabilities to grant the container. Takes a
|
||||||
Takes a comma-separated list of capability names, see
|
comma-separated list of capability names, see <citerefentry
|
||||||
<citerefentry project='man-pages'><refentrytitle>capabilities</refentrytitle><manvolnum>7</manvolnum></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:
|
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,
|
<constant>CAP_AUDIT_CONTROL</constant>, <constant>CAP_AUDIT_WRITE</constant>,
|
||||||
CAP_FOWNER, CAP_FSETID, CAP_IPC_OWNER, CAP_KILL, CAP_LEASE, CAP_LINUX_IMMUTABLE,
|
<constant>CAP_CHOWN</constant>, <constant>CAP_DAC_OVERRIDE</constant>,
|
||||||
CAP_MKNOD, CAP_NET_BIND_SERVICE, CAP_NET_BROADCAST, CAP_NET_RAW, CAP_SETFCAP,
|
<constant>CAP_DAC_READ_SEARCH</constant>, <constant>CAP_FOWNER</constant>,
|
||||||
CAP_SETGID, CAP_SETPCAP, CAP_SETUID, CAP_SYS_ADMIN, CAP_SYS_BOOT, CAP_SYS_CHROOT,
|
<constant>CAP_FSETID</constant>, <constant>CAP_IPC_OWNER</constant>, <constant>CAP_KILL</constant>,
|
||||||
CAP_SYS_NICE, CAP_SYS_PTRACE, CAP_SYS_RESOURCE, CAP_SYS_TTY_CONFIG. Also CAP_NET_ADMIN
|
<constant>CAP_LEASE</constant>, <constant>CAP_LINUX_IMMUTABLE</constant>,
|
||||||
is retained if <option>--private-network</option> is specified. If the special value
|
<constant>CAP_MKNOD</constant>, <constant>CAP_NET_BIND_SERVICE</constant>,
|
||||||
<literal>all</literal> is passed, all capabilities are retained.</para></listitem>
|
<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>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
@ -962,7 +972,10 @@
|
||||||
<listitem><para>Specify one or more additional capabilities to
|
<listitem><para>Specify one or more additional capabilities to
|
||||||
drop for the container. This allows running the container with
|
drop for the container. This allows running the container with
|
||||||
fewer capabilities than the default (see
|
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>
|
||||||
|
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# SPDX-License-Identifier: LGPL-2.1+
|
# SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
|
||||||
project('systemd', 'c',
|
project('systemd', 'c',
|
||||||
version : '243',
|
version : '244',
|
||||||
license : 'LGPLv2+',
|
license : 'LGPLv2+',
|
||||||
default_options: [
|
default_options: [
|
||||||
'c_std=gnu99',
|
'c_std=gnu99',
|
||||||
|
@ -13,8 +13,8 @@ project('systemd', 'c',
|
||||||
meson_version : '>= 0.46',
|
meson_version : '>= 0.46',
|
||||||
)
|
)
|
||||||
|
|
||||||
libsystemd_version = '0.27.0'
|
libsystemd_version = '0.27.1'
|
||||||
libudev_version = '1.6.15'
|
libudev_version = '1.6.16'
|
||||||
|
|
||||||
# We need the same data in two different formats, ugh!
|
# We need the same data in two different formats, ugh!
|
||||||
# Also, for hysterical reasons, we use different variable
|
# Also, for hysterical reasons, we use different variable
|
||||||
|
|
|
@ -330,35 +330,106 @@ int machine_load(Machine *m) {
|
||||||
return r;
|
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);
|
||||||
assert(m->class != MACHINE_HOST);
|
assert(m->class != MACHINE_HOST);
|
||||||
|
|
||||||
if (!m->unit) {
|
if (!m->unit) {
|
||||||
_cleanup_free_ char *escaped = NULL, *scope = NULL;
|
r = machine_start_scope(m, properties, error);
|
||||||
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);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_error_errno(r, "Failed to start machine scope: %s", bus_error_message(error, r));
|
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)
|
assert(m->unit);
|
||||||
hashmap_put(m->manager->machine_units, m->unit, m);
|
hashmap_put(m->manager->machine_units, m->unit, m);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -380,7 +451,7 @@ int machine_start(Machine *m, sd_bus_message *properties, sd_bus_error *error) {
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
/* Create cgroup */
|
/* Create cgroup */
|
||||||
r = machine_start_scope(m, properties, error);
|
r = machine_ensure_scope(m, properties, error);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -404,49 +475,31 @@ int machine_start(Machine *m, sd_bus_message *properties, sd_bus_error *error) {
|
||||||
return 0;
|
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 machine_stop(Machine *m) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
assert(m);
|
assert(m);
|
||||||
|
|
||||||
if (!IN_SET(m->class, MACHINE_CONTAINER, MACHINE_VM))
|
if (!IN_SET(m->class, MACHINE_CONTAINER, MACHINE_VM))
|
||||||
return -EOPNOTSUPP;
|
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;
|
m->stopping = true;
|
||||||
|
|
||||||
machine_save(m);
|
machine_save(m);
|
||||||
(void) manager_enqueue_nscd_cache_flush(m->manager);
|
(void) manager_enqueue_nscd_cache_flush(m->manager);
|
||||||
|
|
||||||
return r;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int machine_finalize(Machine *m) {
|
int machine_finalize(Machine *m) {
|
||||||
|
@ -583,6 +636,18 @@ void machine_release_unit(Machine *m) {
|
||||||
if (!m->unit)
|
if (!m->unit)
|
||||||
return;
|
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);
|
(void) hashmap_remove(m->manager->machine_units, m->unit);
|
||||||
m->unit = mfree(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;
|
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(
|
int manager_unref_unit(
|
||||||
Manager *m,
|
Manager *m,
|
||||||
const char *unit,
|
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_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 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_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_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);
|
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;
|
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)
|
if (whitelist[i].capability != 0 && (cap_list_retain & (1ULL << whitelist[i].capability)) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -153,7 +152,7 @@ static int seccomp_add_default_syscall_filter(
|
||||||
}
|
}
|
||||||
|
|
||||||
STRV_FOREACH(p, syscall_whitelist) {
|
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)
|
if (r < 0)
|
||||||
log_warning_errno(r, "Failed to add rule for system call %s on %s, ignoring: %m",
|
log_warning_errno(r, "Failed to add rule for system call %s on %s, ignoring: %m",
|
||||||
*p, seccomp_arch_to_string(arch));
|
*p, seccomp_arch_to_string(arch));
|
||||||
|
|
|
@ -492,6 +492,46 @@ static int detect_unified_cgroup_hierarchy_from_image(const char *directory) {
|
||||||
return 0;
|
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) {
|
static int parse_share_ns_env(const char *name, unsigned long ns_flag) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -695,7 +735,6 @@ static int parse_argv(int argc, char *argv[]) {
|
||||||
};
|
};
|
||||||
|
|
||||||
int c, r;
|
int c, r;
|
||||||
const char *p;
|
|
||||||
uint64_t plus = 0, minus = 0;
|
uint64_t plus = 0, minus = 0;
|
||||||
bool mask_all_settings = false, mask_no_settings = false;
|
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_CAPABILITY:
|
||||||
case ARG_DROP_CAPABILITY: {
|
case ARG_DROP_CAPABILITY: {
|
||||||
p = optarg;
|
uint64_t m;
|
||||||
for (;;) {
|
r = parse_capability_spec(optarg, &m);
|
||||||
_cleanup_free_ char *t = NULL;
|
if (r <= 0)
|
||||||
|
return r;
|
||||||
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)
|
if (c == ARG_CAPABILITY)
|
||||||
plus |= 1ULL << r;
|
plus |= m;
|
||||||
else
|
else
|
||||||
minus |= 1ULL << r;
|
minus |= m;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
arg_settings_mask |= SETTING_CAPABILITY;
|
arg_settings_mask |= SETTING_CAPABILITY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case ARG_NO_NEW_PRIVILEGES:
|
case ARG_NO_NEW_PRIVILEGES:
|
||||||
r = parse_boolean(optarg);
|
r = parse_boolean(optarg);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include "resolved-dns-stream.h"
|
#include "resolved-dns-stream.h"
|
||||||
#include "resolved-dnstls.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);
|
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) {
|
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;
|
return r;
|
||||||
|
|
||||||
/* As DNS-over-TLS is a recent protocol, older TLS versions can be disabled */
|
/* 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)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ typedef enum VarlinkState {
|
||||||
/* Client side states */
|
/* Client side states */
|
||||||
VARLINK_IDLE_CLIENT,
|
VARLINK_IDLE_CLIENT,
|
||||||
VARLINK_AWAITING_REPLY,
|
VARLINK_AWAITING_REPLY,
|
||||||
|
VARLINK_AWAITING_REPLY_MORE,
|
||||||
VARLINK_CALLING,
|
VARLINK_CALLING,
|
||||||
VARLINK_CALLED,
|
VARLINK_CALLED,
|
||||||
VARLINK_PROCESSING_REPLY,
|
VARLINK_PROCESSING_REPLY,
|
||||||
|
@ -39,7 +40,6 @@ typedef enum VarlinkState {
|
||||||
VARLINK_PROCESSING_METHOD_MORE,
|
VARLINK_PROCESSING_METHOD_MORE,
|
||||||
VARLINK_PROCESSING_METHOD_ONEWAY,
|
VARLINK_PROCESSING_METHOD_ONEWAY,
|
||||||
VARLINK_PROCESSED_METHOD,
|
VARLINK_PROCESSED_METHOD,
|
||||||
VARLINK_PROCESSED_METHOD_MORE,
|
|
||||||
VARLINK_PENDING_METHOD,
|
VARLINK_PENDING_METHOD,
|
||||||
VARLINK_PENDING_METHOD_MORE,
|
VARLINK_PENDING_METHOD_MORE,
|
||||||
|
|
||||||
|
@ -63,6 +63,7 @@ typedef enum VarlinkState {
|
||||||
IN_SET(state, \
|
IN_SET(state, \
|
||||||
VARLINK_IDLE_CLIENT, \
|
VARLINK_IDLE_CLIENT, \
|
||||||
VARLINK_AWAITING_REPLY, \
|
VARLINK_AWAITING_REPLY, \
|
||||||
|
VARLINK_AWAITING_REPLY_MORE, \
|
||||||
VARLINK_CALLING, \
|
VARLINK_CALLING, \
|
||||||
VARLINK_CALLED, \
|
VARLINK_CALLED, \
|
||||||
VARLINK_PROCESSING_REPLY, \
|
VARLINK_PROCESSING_REPLY, \
|
||||||
|
@ -71,7 +72,6 @@ typedef enum VarlinkState {
|
||||||
VARLINK_PROCESSING_METHOD_MORE, \
|
VARLINK_PROCESSING_METHOD_MORE, \
|
||||||
VARLINK_PROCESSING_METHOD_ONEWAY, \
|
VARLINK_PROCESSING_METHOD_ONEWAY, \
|
||||||
VARLINK_PROCESSED_METHOD, \
|
VARLINK_PROCESSED_METHOD, \
|
||||||
VARLINK_PROCESSED_METHOD_MORE, \
|
|
||||||
VARLINK_PENDING_METHOD, \
|
VARLINK_PENDING_METHOD, \
|
||||||
VARLINK_PENDING_METHOD_MORE)
|
VARLINK_PENDING_METHOD_MORE)
|
||||||
|
|
||||||
|
@ -185,6 +185,7 @@ struct VarlinkServer {
|
||||||
static const char* const varlink_state_table[_VARLINK_STATE_MAX] = {
|
static const char* const varlink_state_table[_VARLINK_STATE_MAX] = {
|
||||||
[VARLINK_IDLE_CLIENT] = "idle-client",
|
[VARLINK_IDLE_CLIENT] = "idle-client",
|
||||||
[VARLINK_AWAITING_REPLY] = "awaiting-reply",
|
[VARLINK_AWAITING_REPLY] = "awaiting-reply",
|
||||||
|
[VARLINK_AWAITING_REPLY_MORE] = "awaiting-reply-more",
|
||||||
[VARLINK_CALLING] = "calling",
|
[VARLINK_CALLING] = "calling",
|
||||||
[VARLINK_CALLED] = "called",
|
[VARLINK_CALLED] = "called",
|
||||||
[VARLINK_PROCESSING_REPLY] = "processing-reply",
|
[VARLINK_PROCESSING_REPLY] = "processing-reply",
|
||||||
|
@ -193,7 +194,6 @@ static const char* const varlink_state_table[_VARLINK_STATE_MAX] = {
|
||||||
[VARLINK_PROCESSING_METHOD_MORE] = "processing-method-more",
|
[VARLINK_PROCESSING_METHOD_MORE] = "processing-method-more",
|
||||||
[VARLINK_PROCESSING_METHOD_ONEWAY] = "processing-method-oneway",
|
[VARLINK_PROCESSING_METHOD_ONEWAY] = "processing-method-oneway",
|
||||||
[VARLINK_PROCESSED_METHOD] = "processed-method",
|
[VARLINK_PROCESSED_METHOD] = "processed-method",
|
||||||
[VARLINK_PROCESSED_METHOD_MORE] = "processed-method-more",
|
|
||||||
[VARLINK_PENDING_METHOD] = "pending-method",
|
[VARLINK_PENDING_METHOD] = "pending-method",
|
||||||
[VARLINK_PENDING_METHOD_MORE] = "pending-method-more",
|
[VARLINK_PENDING_METHOD_MORE] = "pending-method-more",
|
||||||
[VARLINK_PENDING_DISCONNECT] = "pending-disconnect",
|
[VARLINK_PENDING_DISCONNECT] = "pending-disconnect",
|
||||||
|
@ -287,6 +287,8 @@ int varlink_connect_address(Varlink **ret, const char *address) {
|
||||||
if (v->fd < 0)
|
if (v->fd < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
|
v->fd = fd_move_above_stdio(v->fd);
|
||||||
|
|
||||||
if (connect(v->fd, &sockaddr.sa, SOCKADDR_UN_LEN(sockaddr.un)) < 0) {
|
if (connect(v->fd, &sockaddr.sa, SOCKADDR_UN_LEN(sockaddr.un)) < 0) {
|
||||||
if (!IN_SET(errno, EAGAIN, EINPROGRESS))
|
if (!IN_SET(errno, EAGAIN, EINPROGRESS))
|
||||||
return -errno;
|
return -errno;
|
||||||
|
@ -341,11 +343,8 @@ static void varlink_detach_event_sources(Varlink *v) {
|
||||||
assert(v);
|
assert(v);
|
||||||
|
|
||||||
v->io_event_source = sd_event_source_disable_unref(v->io_event_source);
|
v->io_event_source = sd_event_source_disable_unref(v->io_event_source);
|
||||||
|
|
||||||
v->time_event_source = sd_event_source_disable_unref(v->time_event_source);
|
v->time_event_source = sd_event_source_disable_unref(v->time_event_source);
|
||||||
|
|
||||||
v->quit_event_source = sd_event_source_disable_unref(v->quit_event_source);
|
v->quit_event_source = sd_event_source_disable_unref(v->quit_event_source);
|
||||||
|
|
||||||
v->defer_event_source = sd_event_source_disable_unref(v->defer_event_source);
|
v->defer_event_source = sd_event_source_disable_unref(v->defer_event_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,7 +404,7 @@ static int varlink_test_disconnect(Varlink *v) {
|
||||||
goto disconnect;
|
goto disconnect;
|
||||||
|
|
||||||
/* If we are waiting for incoming data but the read side is shut down, disconnect. */
|
/* If we are waiting for incoming data but the read side is shut down, disconnect. */
|
||||||
if (IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_CALLING, VARLINK_IDLE_SERVER) && v->read_disconnected)
|
if (IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_AWAITING_REPLY_MORE, VARLINK_CALLING, VARLINK_IDLE_SERVER) && v->read_disconnected)
|
||||||
goto disconnect;
|
goto disconnect;
|
||||||
|
|
||||||
/* Similar, if are a client that hasn't written anything yet but the write side is dead, also
|
/* Similar, if are a client that hasn't written anything yet but the write side is dead, also
|
||||||
|
@ -478,7 +477,7 @@ static int varlink_read(Varlink *v) {
|
||||||
|
|
||||||
assert(v);
|
assert(v);
|
||||||
|
|
||||||
if (!IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_CALLING, VARLINK_IDLE_SERVER))
|
if (!IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_AWAITING_REPLY_MORE, VARLINK_CALLING, VARLINK_IDLE_SERVER))
|
||||||
return 0;
|
return 0;
|
||||||
if (v->connecting) /* read() on a socket while we are in connect() will fail with EINVAL, hence exit early here */
|
if (v->connecting) /* read() on a socket while we are in connect() will fail with EINVAL, hence exit early here */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -596,7 +595,7 @@ static int varlink_parse_message(Varlink *v) {
|
||||||
static int varlink_test_timeout(Varlink *v) {
|
static int varlink_test_timeout(Varlink *v) {
|
||||||
assert(v);
|
assert(v);
|
||||||
|
|
||||||
if (!IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_CALLING))
|
if (!IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_AWAITING_REPLY_MORE, VARLINK_CALLING))
|
||||||
return 0;
|
return 0;
|
||||||
if (v->timeout == USEC_INFINITY)
|
if (v->timeout == USEC_INFINITY)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -673,7 +672,7 @@ static int varlink_dispatch_reply(Varlink *v) {
|
||||||
|
|
||||||
assert(v);
|
assert(v);
|
||||||
|
|
||||||
if (!IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_CALLING))
|
if (!IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_AWAITING_REPLY_MORE, VARLINK_CALLING))
|
||||||
return 0;
|
return 0;
|
||||||
if (!v->current)
|
if (!v->current)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -715,6 +714,11 @@ static int varlink_dispatch_reply(Varlink *v) {
|
||||||
goto invalid;
|
goto invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Replies with 'continue' set are only OK if we set 'more' when the method call was initiated */
|
||||||
|
if (v->state != VARLINK_AWAITING_REPLY_MORE && FLAGS_SET(flags, VARLINK_REPLY_CONTINUES))
|
||||||
|
goto invalid;
|
||||||
|
|
||||||
|
/* An error is final */
|
||||||
if (error && FLAGS_SET(flags, VARLINK_REPLY_CONTINUES))
|
if (error && FLAGS_SET(flags, VARLINK_REPLY_CONTINUES))
|
||||||
goto invalid;
|
goto invalid;
|
||||||
|
|
||||||
|
@ -722,7 +726,7 @@ static int varlink_dispatch_reply(Varlink *v) {
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
goto invalid;
|
goto invalid;
|
||||||
|
|
||||||
if (v->state == VARLINK_AWAITING_REPLY) {
|
if (IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_AWAITING_REPLY_MORE)) {
|
||||||
varlink_set_state(v, VARLINK_PROCESSING_REPLY);
|
varlink_set_state(v, VARLINK_PROCESSING_REPLY);
|
||||||
|
|
||||||
if (v->reply_callback) {
|
if (v->reply_callback) {
|
||||||
|
@ -734,17 +738,18 @@ static int varlink_dispatch_reply(Varlink *v) {
|
||||||
v->current = json_variant_unref(v->current);
|
v->current = json_variant_unref(v->current);
|
||||||
|
|
||||||
if (v->state == VARLINK_PROCESSING_REPLY) {
|
if (v->state == VARLINK_PROCESSING_REPLY) {
|
||||||
|
|
||||||
assert(v->n_pending > 0);
|
assert(v->n_pending > 0);
|
||||||
|
|
||||||
|
if (!FLAGS_SET(flags, VARLINK_REPLY_CONTINUES))
|
||||||
v->n_pending--;
|
v->n_pending--;
|
||||||
|
|
||||||
varlink_set_state(v, v->n_pending == 0 ? VARLINK_IDLE_CLIENT : VARLINK_AWAITING_REPLY);
|
varlink_set_state(v,
|
||||||
|
FLAGS_SET(flags, VARLINK_REPLY_CONTINUES) ? VARLINK_AWAITING_REPLY_MORE :
|
||||||
|
v->n_pending == 0 ? VARLINK_IDLE_CLIENT : VARLINK_AWAITING_REPLY);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(v->state == VARLINK_CALLING);
|
assert(v->state == VARLINK_CALLING);
|
||||||
|
|
||||||
if (FLAGS_SET(flags, VARLINK_REPLY_CONTINUES))
|
|
||||||
goto invalid;
|
|
||||||
|
|
||||||
varlink_set_state(v, VARLINK_CALLED);
|
varlink_set_state(v, VARLINK_CALLED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -878,7 +883,6 @@ static int varlink_dispatch_method(Varlink *v) {
|
||||||
varlink_set_state(v, VARLINK_PENDING_METHOD);
|
varlink_set_state(v, VARLINK_PENDING_METHOD);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VARLINK_PROCESSED_METHOD_MORE: /* One reply for a "more" message was sent, more to come */
|
|
||||||
case VARLINK_PROCESSING_METHOD_MORE: /* No reply for a "more" message was sent, more to come */
|
case VARLINK_PROCESSING_METHOD_MORE: /* No reply for a "more" message was sent, more to come */
|
||||||
varlink_set_state(v, VARLINK_PENDING_METHOD_MORE);
|
varlink_set_state(v, VARLINK_PENDING_METHOD_MORE);
|
||||||
break;
|
break;
|
||||||
|
@ -1073,7 +1077,7 @@ int varlink_get_events(Varlink *v) {
|
||||||
return EPOLLOUT;
|
return EPOLLOUT;
|
||||||
|
|
||||||
if (!v->read_disconnected &&
|
if (!v->read_disconnected &&
|
||||||
IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_CALLING, VARLINK_IDLE_SERVER) &&
|
IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_AWAITING_REPLY_MORE, VARLINK_CALLING, VARLINK_IDLE_SERVER) &&
|
||||||
!v->current &&
|
!v->current &&
|
||||||
v->input_buffer_unscanned <= 0)
|
v->input_buffer_unscanned <= 0)
|
||||||
ret |= EPOLLIN;
|
ret |= EPOLLIN;
|
||||||
|
@ -1091,7 +1095,7 @@ int varlink_get_timeout(Varlink *v, usec_t *ret) {
|
||||||
if (v->state == VARLINK_DISCONNECTED)
|
if (v->state == VARLINK_DISCONNECTED)
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
|
|
||||||
if (IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_CALLING) &&
|
if (IN_SET(v->state, VARLINK_AWAITING_REPLY, VARLINK_AWAITING_REPLY_MORE, VARLINK_CALLING) &&
|
||||||
v->timeout != USEC_INFINITY) {
|
v->timeout != USEC_INFINITY) {
|
||||||
if (ret)
|
if (ret)
|
||||||
*ret = usec_add(v->timestamp, v->timeout);
|
*ret = usec_add(v->timestamp, v->timeout);
|
||||||
|
@ -1259,6 +1263,8 @@ int varlink_send(Varlink *v, const char *method, JsonVariant *parameters) {
|
||||||
|
|
||||||
if (v->state == VARLINK_DISCONNECTED)
|
if (v->state == VARLINK_DISCONNECTED)
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
|
|
||||||
|
/* We allow enqueuing multiple method calls at once! */
|
||||||
if (!IN_SET(v->state, VARLINK_IDLE_CLIENT, VARLINK_AWAITING_REPLY))
|
if (!IN_SET(v->state, VARLINK_IDLE_CLIENT, VARLINK_AWAITING_REPLY))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
|
@ -1308,6 +1314,8 @@ int varlink_invoke(Varlink *v, const char *method, JsonVariant *parameters) {
|
||||||
|
|
||||||
if (v->state == VARLINK_DISCONNECTED)
|
if (v->state == VARLINK_DISCONNECTED)
|
||||||
return -ENOTCONN;
|
return -ENOTCONN;
|
||||||
|
|
||||||
|
/* We allow enqueing multiple method calls at once! */
|
||||||
if (!IN_SET(v->state, VARLINK_IDLE_CLIENT, VARLINK_AWAITING_REPLY))
|
if (!IN_SET(v->state, VARLINK_IDLE_CLIENT, VARLINK_AWAITING_REPLY))
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
|
|
||||||
|
@ -1349,6 +1357,60 @@ int varlink_invokeb(Varlink *v, const char *method, ...) {
|
||||||
return varlink_invoke(v, method, parameters);
|
return varlink_invoke(v, method, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int varlink_observe(Varlink *v, const char *method, JsonVariant *parameters) {
|
||||||
|
_cleanup_(json_variant_unrefp) JsonVariant *m = NULL;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert_return(v, -EINVAL);
|
||||||
|
assert_return(method, -EINVAL);
|
||||||
|
|
||||||
|
if (v->state == VARLINK_DISCONNECTED)
|
||||||
|
return -ENOTCONN;
|
||||||
|
/* Note that we don't allow enqueuing multiple method calls when we are in more/continues mode! We
|
||||||
|
* thus insist on an idle client here. */
|
||||||
|
if (v->state != VARLINK_IDLE_CLIENT)
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
r = varlink_sanitize_parameters(¶meters);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = json_build(&m, JSON_BUILD_OBJECT(
|
||||||
|
JSON_BUILD_PAIR("method", JSON_BUILD_STRING(method)),
|
||||||
|
JSON_BUILD_PAIR("parameters", JSON_BUILD_VARIANT(parameters)),
|
||||||
|
JSON_BUILD_PAIR("more", JSON_BUILD_BOOLEAN(true))));
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
r = varlink_enqueue_json(v, m);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
|
||||||
|
varlink_set_state(v, VARLINK_AWAITING_REPLY_MORE);
|
||||||
|
v->n_pending++;
|
||||||
|
v->timestamp = now(CLOCK_MONOTONIC);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int varlink_observeb(Varlink *v, const char *method, ...) {
|
||||||
|
_cleanup_(json_variant_unrefp) JsonVariant *parameters = NULL;
|
||||||
|
va_list ap;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
assert_return(v, -EINVAL);
|
||||||
|
|
||||||
|
va_start(ap, method);
|
||||||
|
r = json_buildv(¶meters, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
|
||||||
|
return varlink_observe(v, method, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
int varlink_call(
|
int varlink_call(
|
||||||
Varlink *v,
|
Varlink *v,
|
||||||
const char *method,
|
const char *method,
|
||||||
|
@ -1769,6 +1831,7 @@ static int prepare_callback(sd_event_source *s, void *userdata) {
|
||||||
Varlink *v = userdata;
|
Varlink *v = userdata;
|
||||||
int r, e;
|
int r, e;
|
||||||
usec_t until;
|
usec_t until;
|
||||||
|
bool have_timeout;
|
||||||
|
|
||||||
assert(s);
|
assert(s);
|
||||||
assert(v);
|
assert(v);
|
||||||
|
@ -1784,13 +1847,15 @@ static int prepare_callback(sd_event_source *s, void *userdata) {
|
||||||
r = varlink_get_timeout(v, &until);
|
r = varlink_get_timeout(v, &until);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
if (r > 0) {
|
have_timeout = r > 0;
|
||||||
|
|
||||||
|
if (have_timeout) {
|
||||||
r = sd_event_source_set_time(v->time_event_source, until);
|
r = sd_event_source_set_time(v->time_event_source, until);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sd_event_source_set_enabled(v->time_event_source, r > 0 ? SD_EVENT_ON : SD_EVENT_OFF);
|
r = sd_event_source_set_enabled(v->time_event_source, have_timeout ? SD_EVENT_ON : SD_EVENT_OFF);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -2157,6 +2222,8 @@ int varlink_server_listen_address(VarlinkServer *s, const char *address, mode_t
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
|
fd = fd_move_above_stdio(fd);
|
||||||
|
|
||||||
(void) sockaddr_un_unlink(&sockaddr.un);
|
(void) sockaddr_un_unlink(&sockaddr.un);
|
||||||
|
|
||||||
RUN_WITH_UMASK(~m & 0777)
|
RUN_WITH_UMASK(~m & 0777)
|
||||||
|
@ -2339,17 +2406,18 @@ int varlink_server_bind_connect(VarlinkServer *s, VarlinkConnect callback) {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned varlink_server_connections_max(VarlinkServer *s) {
|
unsigned varlink_server_connections_max(VarlinkServer *s) {
|
||||||
struct rlimit rl;
|
int dts;
|
||||||
|
|
||||||
/* If a server is specified, return the setting for that server, otherwise the default value */
|
/* If a server is specified, return the setting for that server, otherwise the default value */
|
||||||
if (s)
|
if (s)
|
||||||
return s->connections_max;
|
return s->connections_max;
|
||||||
|
|
||||||
assert_se(getrlimit(RLIMIT_NOFILE, &rl) >= 0);
|
dts = getdtablesize();
|
||||||
|
assert_se(dts > 0);
|
||||||
|
|
||||||
/* Make sure we never use up more than ¾th of RLIMIT_NOFILE for IPC */
|
/* Make sure we never use up more than ¾th of RLIMIT_NOFILE for IPC */
|
||||||
if (VARLINK_DEFAULT_CONNECTIONS_MAX > rl.rlim_cur / 4 * 3)
|
if (VARLINK_DEFAULT_CONNECTIONS_MAX > (unsigned) dts / 4 * 3)
|
||||||
return rl.rlim_cur / 4 * 3;
|
return dts / 4 * 3;
|
||||||
|
|
||||||
return VARLINK_DEFAULT_CONNECTIONS_MAX;
|
return VARLINK_DEFAULT_CONNECTIONS_MAX;
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,10 @@ int varlink_callb(Varlink *v, const char *method, JsonVariant **ret_parameters,
|
||||||
int varlink_invoke(Varlink *v, const char *method, JsonVariant *parameters);
|
int varlink_invoke(Varlink *v, const char *method, JsonVariant *parameters);
|
||||||
int varlink_invokeb(Varlink *v, const char *method, ...);
|
int varlink_invokeb(Varlink *v, const char *method, ...);
|
||||||
|
|
||||||
|
/* Enqueue method call, expect a reply now, and possibly more later, which are all delivered to the reply callback */
|
||||||
|
int varlink_observe(Varlink *v, const char *method, JsonVariant *parameters);
|
||||||
|
int varlink_observeb(Varlink *v, const char *method, ...);
|
||||||
|
|
||||||
/* Enqueue a final reply */
|
/* Enqueue a final reply */
|
||||||
int varlink_reply(Varlink *v, JsonVariant *parameters);
|
int varlink_reply(Varlink *v, JsonVariant *parameters);
|
||||||
int varlink_replyb(Varlink *v, ...);
|
int varlink_replyb(Varlink *v, ...);
|
||||||
|
|
|
@ -98,7 +98,7 @@ units = [
|
||||||
['systemd-poweroff.service', ''],
|
['systemd-poweroff.service', ''],
|
||||||
['systemd-reboot.service', ''],
|
['systemd-reboot.service', ''],
|
||||||
['systemd-rfkill.socket', 'ENABLE_RFKILL'],
|
['systemd-rfkill.socket', 'ENABLE_RFKILL'],
|
||||||
['systemd-tmpfiles-clean.timer', '',
|
['systemd-tmpfiles-clean.timer', 'ENABLE_TMPFILES',
|
||||||
'timers.target.wants/'],
|
'timers.target.wants/'],
|
||||||
['systemd-udevd-control.socket', '',
|
['systemd-udevd-control.socket', '',
|
||||||
'sockets.target.wants/'],
|
'sockets.target.wants/'],
|
||||||
|
|
Loading…
Reference in New Issue