mirror of
https://github.com/systemd/systemd-stable.git
synced 2025-01-05 09:17:44 +03:00
Merge pull request #7695 from yuwata/transient-socket
DBus-API: implement transient socket unit
This commit is contained in:
commit
7785da68e6
@ -2,8 +2,8 @@
|
||||
|
||||
Our intention is to make all settings that are available as unit file settings
|
||||
also available for transient units, through the D-Bus API. At the moment, some
|
||||
unit types (socket, swap, path) are not supported at all via unit types, but
|
||||
most others are pretty well supported, with some notable omissions.
|
||||
unit types (device, swap, target) are not supported at all via unit types,
|
||||
but most others are pretty well supported, with some notable omissions.
|
||||
|
||||
The lists below contain all settings currently available in unit files. The
|
||||
ones currently available in transient units are prefixed with `✓`.
|
||||
@ -68,6 +68,7 @@ Only the most important generic unit settings are available for transient units.
|
||||
ConditionACPower=
|
||||
ConditionUser=
|
||||
ConditionGroup=
|
||||
ConditionControlGroupController=
|
||||
AssertPathExists=
|
||||
AssertPathExistsGlob=
|
||||
AssertPathIsDirectory=
|
||||
@ -88,6 +89,7 @@ Only the most important generic unit settings are available for transient units.
|
||||
AssertACPower=
|
||||
AssertUser=
|
||||
AssertGroup=
|
||||
AssertControlGroupController=
|
||||
✓ CollectMode=
|
||||
```
|
||||
|
||||
@ -341,71 +343,71 @@ of their own beyond the generic unit and resource control settings.
|
||||
## Scope Unit Settings
|
||||
|
||||
Scope units are fully supported as transient units (in fact they only exist as
|
||||
such), but they have no settings of their own beyond the generic unit and
|
||||
resource control settings.
|
||||
such), but they have no settings of their own beyond the generic unit,
|
||||
resource control, and process killing settings.
|
||||
|
||||
## Socket Unit Settings
|
||||
|
||||
Socket units are currently not available at all as transient units:
|
||||
Most socket unit settings are available to transient units.
|
||||
|
||||
```
|
||||
ListenStream=
|
||||
ListenDatagram=
|
||||
ListenSequentialPacket=
|
||||
ListenFIFO=
|
||||
ListenNetlink=
|
||||
ListenSpecial=
|
||||
ListenMessageQueue=
|
||||
ListenUSBFunction=
|
||||
SocketProtocol=
|
||||
BindIPv6Only=
|
||||
Backlog=
|
||||
BindToDevice=
|
||||
ExecStartPre=
|
||||
ExecStartPost=
|
||||
ExecStopPre=
|
||||
ExecStopPost=
|
||||
TimeoutSec=
|
||||
SocketUser=
|
||||
SocketGroup=
|
||||
SocketMode=
|
||||
DirectoryMode=
|
||||
Accept=
|
||||
Writable=
|
||||
MaxConnections=
|
||||
MaxConnectionsPerSource=
|
||||
KeepAlive=
|
||||
KeepAliveTimeSec=
|
||||
KeepAliveIntervalSec=
|
||||
KeepAliveProbes=
|
||||
DeferAcceptSec=
|
||||
NoDelay=
|
||||
Priority=
|
||||
ReceiveBuffer=
|
||||
SendBuffer=
|
||||
IPTOS=
|
||||
IPTTL=
|
||||
Mark=
|
||||
PipeSize=
|
||||
FreeBind=
|
||||
Transparent=
|
||||
Broadcast=
|
||||
PassCredentials=
|
||||
PassSecurity=
|
||||
TCPCongestion=
|
||||
ReusePort=
|
||||
MessageQueueMaxMessages=
|
||||
MessageQueueMessageSize=
|
||||
RemoveOnStop=
|
||||
Symlinks=
|
||||
FileDescriptorName=
|
||||
✓ ListenStream=
|
||||
✓ ListenDatagram=
|
||||
✓ ListenSequentialPacket=
|
||||
✓ ListenFIFO=
|
||||
✓ ListenNetlink=
|
||||
✓ ListenSpecial=
|
||||
✓ ListenMessageQueue=
|
||||
✓ ListenUSBFunction=
|
||||
✓ SocketProtocol=
|
||||
✓ BindIPv6Only=
|
||||
✓ Backlog=
|
||||
✓ BindToDevice=
|
||||
✓ ExecStartPre=
|
||||
✓ ExecStartPost=
|
||||
✓ ExecStopPre=
|
||||
✓ ExecStopPost=
|
||||
✓ TimeoutSec=
|
||||
✓ SocketUser=
|
||||
✓ SocketGroup=
|
||||
✓ SocketMode=
|
||||
✓ DirectoryMode=
|
||||
✓ Accept=
|
||||
✓ Writable=
|
||||
✓ MaxConnections=
|
||||
✓ MaxConnectionsPerSource=
|
||||
✓ KeepAlive=
|
||||
✓ KeepAliveTimeSec=
|
||||
✓ KeepAliveIntervalSec=
|
||||
✓ KeepAliveProbes=
|
||||
✓ DeferAcceptSec=
|
||||
✓ NoDelay=
|
||||
✓ Priority=
|
||||
✓ ReceiveBuffer=
|
||||
✓ SendBuffer=
|
||||
✓ IPTOS=
|
||||
✓ IPTTL=
|
||||
✓ Mark=
|
||||
✓ PipeSize=
|
||||
✓ FreeBind=
|
||||
✓ Transparent=
|
||||
✓ Broadcast=
|
||||
✓ PassCredentials=
|
||||
✓ PassSecurity=
|
||||
✓ TCPCongestion=
|
||||
✓ ReusePort=
|
||||
✓ MessageQueueMaxMessages=
|
||||
✓ MessageQueueMessageSize=
|
||||
✓ RemoveOnStop=
|
||||
✓ Symlinks=
|
||||
✓ FileDescriptorName=
|
||||
Service=
|
||||
TriggerLimitIntervalSec=
|
||||
TriggerLimitBurst=
|
||||
SmackLabel=
|
||||
SmackLabelIPIn=
|
||||
SmackLabelIPOut=
|
||||
SELinuxContextFromNet=
|
||||
✓ TriggerLimitIntervalSec=
|
||||
✓ TriggerLimitBurst=
|
||||
✓ SmackLabel=
|
||||
✓ SmackLabelIPIn=
|
||||
✓ SmackLabelIPOut=
|
||||
✓ SELinuxContextFromNet=
|
||||
```
|
||||
|
||||
## Swap Unit Settings
|
||||
|
@ -47,7 +47,7 @@
|
||||
|
||||
<refnamediv>
|
||||
<refname>systemd-run</refname>
|
||||
<refpurpose>Run programs in transient scope units, service units, or timer-scheduled service units</refpurpose>
|
||||
<refpurpose>Run programs in transient scope units, service units, or path-, socket-, or timer-triggered service units</refpurpose>
|
||||
</refnamediv>
|
||||
|
||||
<refsynopsisdiv>
|
||||
@ -58,6 +58,20 @@
|
||||
<arg choice="opt" rep="repeat">ARGS</arg>
|
||||
</arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>systemd-run</command>
|
||||
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||
<arg choice="opt" rep="repeat">PATH OPTIONS</arg>
|
||||
<arg choice="req"><replaceable>COMMAND</replaceable></arg>
|
||||
<arg choice="opt" rep="repeat">ARGS</arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>systemd-run</command>
|
||||
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||
<arg choice="opt" rep="repeat">SOCKET OPTIONS</arg>
|
||||
<arg choice="req"><replaceable>COMMAND</replaceable></arg>
|
||||
<arg choice="opt" rep="repeat">ARGS</arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>systemd-run</command>
|
||||
<arg choice="opt" rep="repeat">OPTIONS</arg>
|
||||
@ -72,8 +86,8 @@
|
||||
|
||||
<para><command>systemd-run</command> may be used to create and start a transient <filename>.service</filename> or
|
||||
<filename>.scope</filename> unit and run the specified <replaceable>COMMAND</replaceable> in it. It may also be
|
||||
used to create and start a transient <filename>.timer</filename> unit, that activates a
|
||||
<filename>.service</filename> unit when elapsing.</para>
|
||||
used to create and start a transient <filename>.path</filename>, <filename>.socket</filename>, or
|
||||
<filename>.timer</filename> unit, that activates a <filename>.service</filename> unit when elapsing.</para>
|
||||
|
||||
<para>If a command is run as transient service unit, it will be started and managed by the service manager like any
|
||||
other service, and thus shows up in the output of <command>systemctl list-units</command> like any other unit. It
|
||||
@ -88,12 +102,13 @@
|
||||
list-units</command>. Execution in this case is synchronous, and will return only when the command finishes. This
|
||||
mode is enabled via the <option>--scope</option> switch (see below). </para>
|
||||
|
||||
<para>If a command is run with timer options such as <option>--on-calendar=</option> (see below), a transient timer
|
||||
unit is created alongside the service unit for the specified command. Only the transient timer unit is started
|
||||
immediately, the transient service unit will be started when the timer elapses. If the <option>--unit=</option>
|
||||
option is specified, the <replaceable>COMMAND</replaceable> may be omitted. In this case,
|
||||
<command>systemd-run</command> creates only a <filename>.timer</filename> unit that invokes the specified unit when
|
||||
elapsing.</para>
|
||||
<para>If a command is run with path, socket, or timer options such as <option>--on-calendar=</option> (see below),
|
||||
a transient path, socket, or timer unit is created alongside the service unit for the specified command. Only the
|
||||
transient path, socket, or timer unit is started immediately, the transient service unit will be triggered by the
|
||||
path, socket, or timer unit. If the <option>--unit=</option> option is specified, the
|
||||
<replaceable>COMMAND</replaceable> may be omitted. In this case, <command>systemd-run</command> creates only a
|
||||
<filename>.path</filename>, <filename>.socket</filename>, or <filename>.timer</filename> unit that triggers the
|
||||
specified unit.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
@ -140,8 +155,8 @@
|
||||
<varlistentry>
|
||||
<term><option>--description=</option></term>
|
||||
|
||||
<listitem><para>Provide a description for the service, scope or timer unit. If not specified, the command
|
||||
itself will be used as a description. See <varname>Description=</varname> in
|
||||
<listitem><para>Provide a description for the service, scope, path, socket, or timer unit. If not specified,
|
||||
the command itself will be used as a description. See <varname>Description=</varname> in
|
||||
<citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
|
||||
</para></listitem>
|
||||
</varlistentry>
|
||||
@ -278,7 +293,8 @@
|
||||
command. See <varname>OnActiveSec=</varname>, <varname>OnBootSec=</varname>, <varname>OnStartupSec=</varname>,
|
||||
<varname>OnUnitActiveSec=</varname> and <varname>OnUnitInactiveSec=</varname> in
|
||||
<citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
|
||||
details. These options may not be combined with <option>--scope</option> or <option>--pty</option>.</para>
|
||||
details. These options are shortcuts for <command>--timer-property=</command> with the relevant properties.
|
||||
These options may not be combined with <option>--scope</option> or <option>--pty</option>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@ -287,20 +303,23 @@
|
||||
|
||||
<listitem><para>Defines a calendar timer for starting the specified command. See <varname>OnCalendar=</varname>
|
||||
in <citerefentry><refentrytitle>systemd.timer</refentrytitle><manvolnum>5</manvolnum></citerefentry>. This
|
||||
option may not be combined with <option>--scope</option> or <option>--pty</option>.</para>
|
||||
option is a shortcut for <command>--timer-property=OnCalendar=</command>. This option may not be combined with
|
||||
<option>--scope</option> or <option>--pty</option>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--path-property=</option></term>
|
||||
<term><option>--socket-property=</option></term>
|
||||
<term><option>--timer-property=</option></term>
|
||||
|
||||
<listitem><para>Sets a property on the timer unit that is created. This option is similar to
|
||||
<option>--property=</option> but applies to the transient timer unit rather than the transient service unit
|
||||
created. This option only has an effect in conjunction with <option>--on-active=</option>,
|
||||
<option>--on-boot=</option>, <option>--on-startup=</option>, <option>--on-unit-active=</option>,
|
||||
<option>--on-unit-inactive=</option> or <option>--on-calendar=</option>. This option takes an assignment in the
|
||||
same format as <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
|
||||
<command>set-property</command> command.</para> </listitem>
|
||||
<listitem><para>Sets a property on the path, socket, or timer unit that is created. This option is similar to
|
||||
<option>--property=</option> but applies to the transient path, socket, or timer unit rather than the
|
||||
transient service unit created. This option takes an assignment in the same format as
|
||||
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
|
||||
<command>set-property</command> command. These options may not be combined with
|
||||
<option>--scope</option> or <option>--pty</option>.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@ -323,7 +342,7 @@
|
||||
completed). On exit, terse information about the unit's runtime is shown, including total runtime (as well as
|
||||
CPU usage, if <option>--property=CPUAccounting=1</option> was set) and the exit code and status of the main
|
||||
process. This output may be suppressed with <option>--quiet</option>. This option may not be combined with
|
||||
<option>--no-block</option>, <option>--scope</option> or the various timer options.</para></listitem>
|
||||
<option>--no-block</option>, <option>--scope</option> or the various path, socket, or timer options.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
5
src/basic/generate-socket-protocol-list.sh
Executable file
5
src/basic/generate-socket-protocol-list.sh
Executable file
@ -0,0 +1,5 @@
|
||||
#!/bin/sh -eu
|
||||
|
||||
$1 -dM -include netinet/in.h - </dev/null | \
|
||||
awk '/^#define[ \t]+IPPROTO_[^ \t]+[ \t]+[^ \t]/ { print $2; }' | \
|
||||
sed -e 's/IPPROTO_//'
|
@ -176,6 +176,8 @@ basic_sources_plain = files('''
|
||||
smack-util.c
|
||||
smack-util.h
|
||||
socket-label.c
|
||||
socket-protocol-list.c
|
||||
socket-protocol-list.h
|
||||
socket-util.c
|
||||
socket-util.h
|
||||
sparse-endian.h
|
||||
@ -255,11 +257,19 @@ errno_list_txt = custom_target(
|
||||
command : [generate_errno_list, cpp],
|
||||
capture : true)
|
||||
|
||||
generate_socket_protocol_list = find_program('generate-socket-protocol-list.sh')
|
||||
socket_protocol_list_txt = custom_target(
|
||||
'socket-protocol-list.txt',
|
||||
output : 'socket-protocol-list.txt',
|
||||
command : [generate_socket_protocol_list, cpp],
|
||||
capture : true)
|
||||
|
||||
generated_gperf_headers = []
|
||||
foreach item : [['af', af_list_txt, 'af', ''],
|
||||
['arphrd', arphrd_list_txt, 'arphrd', 'ARPHRD_'],
|
||||
['cap', cap_list_txt, 'capability', ''],
|
||||
['errno', errno_list_txt, 'errno', '']]
|
||||
['errno', errno_list_txt, 'errno', ''],
|
||||
['socket-protocol', socket_protocol_list_txt, 'socket_protocol', 'IPPROTO_']]
|
||||
|
||||
fname = '@0@-from-name.gperf'.format(item[0])
|
||||
gperf_file = custom_target(
|
||||
|
57
src/basic/socket-protocol-list.c
Normal file
57
src/basic/socket-protocol-list.c
Normal file
@ -0,0 +1,57 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2014 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "socket-protocol-list.h"
|
||||
#include "macro.h"
|
||||
|
||||
static const struct socket_protocol_name* lookup_socket_protocol(register const char *str, register GPERF_LEN_TYPE len);
|
||||
|
||||
#include "socket-protocol-from-name.h"
|
||||
#include "socket-protocol-to-name.h"
|
||||
|
||||
const char *socket_protocol_to_name(int id) {
|
||||
|
||||
if (id < 0)
|
||||
return NULL;
|
||||
|
||||
if (id >= (int) ELEMENTSOF(socket_protocol_names))
|
||||
return NULL;
|
||||
|
||||
return socket_protocol_names[id];
|
||||
}
|
||||
|
||||
int socket_protocol_from_name(const char *name) {
|
||||
const struct socket_protocol_name *sc;
|
||||
|
||||
assert(name);
|
||||
|
||||
sc = lookup_socket_protocol(name, strlen(name));
|
||||
if (!sc)
|
||||
return 0;
|
||||
|
||||
return sc->id;
|
||||
}
|
||||
|
||||
int socket_protocol_max(void) {
|
||||
return ELEMENTSOF(socket_protocol_names);
|
||||
}
|
26
src/basic/socket-protocol-list.h
Normal file
26
src/basic/socket-protocol-list.h
Normal file
@ -0,0 +1,26 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2014 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
const char *socket_protocol_to_name(int id);
|
||||
int socket_protocol_from_name(const char *name);
|
||||
|
||||
int socket_protocol_max(void);
|
9
src/basic/socket-protocol-to-name.awk
Normal file
9
src/basic/socket-protocol-to-name.awk
Normal file
@ -0,0 +1,9 @@
|
||||
BEGIN{
|
||||
print "static const char* const socket_protocol_names[] = { "
|
||||
}
|
||||
!/HOPOPTS/ {
|
||||
printf " [IPPROTO_%s] = \"%s\",\n", $1, tolower($1)
|
||||
}
|
||||
END{
|
||||
print "};"
|
||||
}
|
@ -55,6 +55,17 @@
|
||||
# define IDN_FLAGS 0
|
||||
#endif
|
||||
|
||||
static const char* const socket_address_type_table[] = {
|
||||
[SOCK_STREAM] = "Stream",
|
||||
[SOCK_DGRAM] = "Datagram",
|
||||
[SOCK_RAW] = "Raw",
|
||||
[SOCK_RDM] = "ReliableDatagram",
|
||||
[SOCK_SEQPACKET] = "SequentialPacket",
|
||||
[SOCK_DCCP] = "DatagramCongestionControl",
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(socket_address_type, int);
|
||||
|
||||
int socket_address_parse(SocketAddress *a, const char *s) {
|
||||
char *e, *n;
|
||||
unsigned u;
|
||||
|
@ -72,6 +72,9 @@ typedef enum SocketAddressBindIPv6Only {
|
||||
|
||||
#define socket_address_family(a) ((a)->sockaddr.sa.sa_family)
|
||||
|
||||
const char* socket_address_type_to_string(int t) _const_;
|
||||
int socket_address_type_from_string(const char *s) _pure_;
|
||||
|
||||
int socket_address_parse(SocketAddress *a, const char *s);
|
||||
int socket_address_parse_and_warn(SocketAddress *a, const char *s);
|
||||
int socket_address_parse_netlink(SocketAddress *a, const char *s);
|
||||
|
@ -446,7 +446,7 @@ int bus_cgroup_set_property(
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "CPUWeight")) {
|
||||
} else if (STR_IN_SET(name, "CPUWeight", "StartupCPUWeight")) {
|
||||
uint64_t weight;
|
||||
|
||||
r = sd_bus_message_read(message, "t", &weight);
|
||||
@ -454,43 +454,25 @@ int bus_cgroup_set_property(
|
||||
return r;
|
||||
|
||||
if (!CGROUP_WEIGHT_IS_OK(weight))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "CPUWeight= value out of range");
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= value out of range", name);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
c->cpu_weight = weight;
|
||||
if (streq(name, "CPUWeight"))
|
||||
c->cpu_weight = weight;
|
||||
else /* "StartupCPUWeight" */
|
||||
c->startup_cpu_weight = weight;
|
||||
|
||||
unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
|
||||
|
||||
if (weight == CGROUP_WEIGHT_INVALID)
|
||||
unit_write_setting(u, flags, name, "CPUWeight=");
|
||||
unit_write_settingf(u, flags, name, "%s=", name);
|
||||
else
|
||||
unit_write_settingf(u, flags, name, "CPUWeight=%" PRIu64, weight);
|
||||
unit_write_settingf(u, flags, name, "%s=%" PRIu64, name, weight);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "StartupCPUWeight")) {
|
||||
uint64_t weight;
|
||||
|
||||
r = sd_bus_message_read(message, "t", &weight);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!CGROUP_WEIGHT_IS_OK(weight))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "StartupCPUWeight= value out of range");
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
c->startup_cpu_weight = weight;
|
||||
unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
|
||||
|
||||
if (weight == CGROUP_CPU_SHARES_INVALID)
|
||||
unit_write_setting(u, flags, name, "StartupCPUWeight=");
|
||||
else
|
||||
unit_write_settingf(u, flags, name, "StartupCPUWeight=%" PRIu64, weight);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "CPUShares")) {
|
||||
} else if (STR_IN_SET(name, "CPUShares", "StartupCPUShares")) {
|
||||
uint64_t shares;
|
||||
|
||||
r = sd_bus_message_read(message, "t", &shares);
|
||||
@ -498,38 +480,20 @@ int bus_cgroup_set_property(
|
||||
return r;
|
||||
|
||||
if (!CGROUP_CPU_SHARES_IS_OK(shares))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "CPUShares= value out of range");
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= value out of range", name);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
c->cpu_shares = shares;
|
||||
if (streq(name, "CPUShares"))
|
||||
c->cpu_shares = shares;
|
||||
else /* "StartupCPUShares" */
|
||||
c->startup_cpu_shares = shares;
|
||||
|
||||
unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
|
||||
|
||||
if (shares == CGROUP_CPU_SHARES_INVALID)
|
||||
unit_write_setting(u, flags, name, "CPUShares=");
|
||||
unit_write_settingf(u, flags, name, "%s=", name);
|
||||
else
|
||||
unit_write_settingf(u, flags, name, "CPUShares=%" PRIu64, shares);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "StartupCPUShares")) {
|
||||
uint64_t shares;
|
||||
|
||||
r = sd_bus_message_read(message, "t", &shares);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!CGROUP_CPU_SHARES_IS_OK(shares))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "StartupCPUShares= value out of range");
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
c->startup_cpu_shares = shares;
|
||||
unit_invalidate_cgroup(u, CGROUP_MASK_CPU);
|
||||
|
||||
if (shares == CGROUP_CPU_SHARES_INVALID)
|
||||
unit_write_setting(u, flags, name, "StartupCPUShares=");
|
||||
else
|
||||
unit_write_settingf(u, flags, name, "StartupCPUShares=%" PRIu64, shares);
|
||||
unit_write_settingf(u, flags, name, "%s=%" PRIu64, name, shares);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -575,7 +539,7 @@ int bus_cgroup_set_property(
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "IOWeight")) {
|
||||
} else if (STR_IN_SET(name, "IOWeight", "StartupIOWeight")) {
|
||||
uint64_t weight;
|
||||
|
||||
r = sd_bus_message_read(message, "t", &weight);
|
||||
@ -583,38 +547,20 @@ int bus_cgroup_set_property(
|
||||
return r;
|
||||
|
||||
if (!CGROUP_WEIGHT_IS_OK(weight))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "IOWeight= value out of range");
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= value out of range", name);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
c->io_weight = weight;
|
||||
if (streq(name, "IOWeight"))
|
||||
c->io_weight = weight;
|
||||
else /* "StartupIOWeight" */
|
||||
c->startup_io_weight = weight;
|
||||
|
||||
unit_invalidate_cgroup(u, CGROUP_MASK_IO);
|
||||
|
||||
if (weight == CGROUP_WEIGHT_INVALID)
|
||||
unit_write_setting(u, flags, name, "IOWeight=");
|
||||
unit_write_settingf(u, flags, name, "%s=", name);
|
||||
else
|
||||
unit_write_settingf(u, flags, name, "IOWeight=%" PRIu64, weight);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "StartupIOWeight")) {
|
||||
uint64_t weight;
|
||||
|
||||
r = sd_bus_message_read(message, "t", &weight);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (CGROUP_WEIGHT_IS_OK(weight))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "StartupIOWeight= value out of range");
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
c->startup_io_weight = weight;
|
||||
unit_invalidate_cgroup(u, CGROUP_MASK_IO);
|
||||
|
||||
if (weight == CGROUP_WEIGHT_INVALID)
|
||||
unit_write_setting(u, flags, name, "StartupIOWeight=");
|
||||
else
|
||||
unit_write_settingf(u, flags, name, "StartupIOWeight=%" PRIu64, weight);
|
||||
unit_write_settingf(u, flags, name, "%s=%" PRIu64, name, weight);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -630,6 +576,10 @@ int bus_cgroup_set_property(
|
||||
|
||||
while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
|
||||
|
||||
if (!path_startswith(path, "/dev") &&
|
||||
!path_startswith(path, "/run/systemd/inaccessible/"))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s specified in %s= is not a device file in /dev", name, path);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
CGroupIODeviceLimit *a = NULL, *b;
|
||||
|
||||
@ -714,6 +664,10 @@ int bus_cgroup_set_property(
|
||||
|
||||
while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
|
||||
|
||||
if (!path_startswith(path, "/dev") &&
|
||||
!path_startswith(path, "/run/systemd/inaccessible/"))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s specified in %s= is not a device file in /dev", name, path);
|
||||
|
||||
if (!CGROUP_WEIGHT_IS_OK(weight) || weight == CGROUP_WEIGHT_INVALID)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "IODeviceWeight= value out of range");
|
||||
|
||||
@ -796,7 +750,7 @@ int bus_cgroup_set_property(
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "BlockIOWeight")) {
|
||||
} else if (STR_IN_SET(name, "BlockIOWeight", "StartupBlockIOWeight")) {
|
||||
uint64_t weight;
|
||||
|
||||
r = sd_bus_message_read(message, "t", &weight);
|
||||
@ -804,38 +758,20 @@ int bus_cgroup_set_property(
|
||||
return r;
|
||||
|
||||
if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "BlockIOWeight= value out of range");
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= value out of range", name);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
c->blockio_weight = weight;
|
||||
if (streq(name, "BlockIOWeight"))
|
||||
c->blockio_weight = weight;
|
||||
else /* "StartupBlockIOWeight" */
|
||||
c->startup_blockio_weight = weight;
|
||||
|
||||
unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
|
||||
|
||||
if (weight == CGROUP_BLKIO_WEIGHT_INVALID)
|
||||
unit_write_setting(u, flags, name, "BlockIOWeight=");
|
||||
unit_write_settingf(u, flags, name, "%s=", name);
|
||||
else
|
||||
unit_write_settingf(u, flags, name, "BlockIOWeight=%" PRIu64, weight);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "StartupBlockIOWeight")) {
|
||||
uint64_t weight;
|
||||
|
||||
r = sd_bus_message_read(message, "t", &weight);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "StartupBlockIOWeight= value out of range");
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
c->startup_blockio_weight = weight;
|
||||
unit_invalidate_cgroup(u, CGROUP_MASK_BLKIO);
|
||||
|
||||
if (weight == CGROUP_BLKIO_WEIGHT_INVALID)
|
||||
unit_write_setting(u, flags, name, "StartupBlockIOWeight=");
|
||||
else
|
||||
unit_write_settingf(u, flags, name, "StartupBlockIOWeight=%" PRIu64, weight);
|
||||
unit_write_settingf(u, flags, name, "%s=%" PRIu64, name, weight);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -855,6 +791,10 @@ int bus_cgroup_set_property(
|
||||
|
||||
while ((r = sd_bus_message_read(message, "(st)", &path, &u64)) > 0) {
|
||||
|
||||
if (!path_startswith(path, "/dev") &&
|
||||
!path_startswith(path, "/run/systemd/inaccessible/"))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s specified in %s= is not a device file in /dev", name, path);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
CGroupBlockIODeviceBandwidth *a = NULL, *b;
|
||||
|
||||
@ -951,6 +891,10 @@ int bus_cgroup_set_property(
|
||||
|
||||
while ((r = sd_bus_message_read(message, "(st)", &path, &weight)) > 0) {
|
||||
|
||||
if (!path_startswith(path, "/dev") &&
|
||||
!path_startswith(path, "/run/systemd/inaccessible/"))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s specified in %s= is not a device file in /dev", name, path);
|
||||
|
||||
if (!CGROUP_BLKIO_WEIGHT_IS_OK(weight) || weight == CGROUP_BLKIO_WEIGHT_INVALID)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "BlockIODeviceWeight= out of range");
|
||||
|
||||
@ -1034,7 +978,7 @@ int bus_cgroup_set_property(
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax")) {
|
||||
} else if (STR_IN_SET(name, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit")) {
|
||||
uint64_t v;
|
||||
|
||||
r = sd_bus_message_read(message, "t", &v);
|
||||
@ -1050,8 +994,10 @@ int bus_cgroup_set_property(
|
||||
c->memory_high = v;
|
||||
else if (streq(name, "MemorySwapMax"))
|
||||
c->memory_swap_max = v;
|
||||
else
|
||||
else if (streq(name, "MemoryMax"))
|
||||
c->memory_max = v;
|
||||
else /* "MemoryLimit" */
|
||||
c->memory_limit = v;
|
||||
|
||||
unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
|
||||
|
||||
@ -1063,7 +1009,7 @@ int bus_cgroup_set_property(
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "MemoryLowScale", "MemoryHighScale", "MemoryMaxScale", "MemorySwapMaxScale")) {
|
||||
} else if (STR_IN_SET(name, "MemoryLowScale", "MemoryHighScale", "MemoryMaxScale", "MemorySwapMaxScale", "MemoryLimitScale")) {
|
||||
uint32_t raw;
|
||||
uint64_t v;
|
||||
|
||||
@ -1086,10 +1032,12 @@ int bus_cgroup_set_property(
|
||||
c->memory_low = v;
|
||||
else if (streq(name, "MemoryHigh"))
|
||||
c->memory_high = v;
|
||||
else if (streq(name, "MemorySwapMaxScale"))
|
||||
else if (streq(name, "MemorySwapMax"))
|
||||
c->memory_swap_max = v;
|
||||
else /* MemoryMax */
|
||||
else if (streq(name, "MemoryMax"))
|
||||
c->memory_max = v;
|
||||
else /* "MemoryLimit" */
|
||||
c->memory_limit = v;
|
||||
|
||||
unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
|
||||
unit_write_settingf(u, flags, name, "%s=%" PRIu32 "%%", name,
|
||||
@ -1098,48 +1046,6 @@ int bus_cgroup_set_property(
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "MemoryLimit")) {
|
||||
uint64_t limit;
|
||||
|
||||
r = sd_bus_message_read(message, "t", &limit);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (limit <= 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= is too small", name);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
c->memory_limit = limit;
|
||||
unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
|
||||
|
||||
if (limit == CGROUP_LIMIT_MAX)
|
||||
unit_write_setting(u, flags, name, "MemoryLimit=infinity");
|
||||
else
|
||||
unit_write_settingf(u, flags, name, "MemoryLimit=%" PRIu64, limit);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "MemoryLimitScale")) {
|
||||
uint64_t limit;
|
||||
uint32_t raw;
|
||||
|
||||
r = sd_bus_message_read(message, "u", &raw);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
limit = physical_memory_scale(raw, UINT32_MAX);
|
||||
if (limit <= 0 || limit == UINT64_MAX)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s= is out of range", name);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
c->memory_limit = limit;
|
||||
unit_invalidate_cgroup(u, CGROUP_MASK_MEMORY);
|
||||
unit_write_settingf(u, flags, "MemoryLimit", "MemoryLimit=%" PRIu32 "%%",
|
||||
(uint32_t) (DIV_ROUND_UP((uint64_t) raw * 100U, (uint64_t) UINT32_MAX)));
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "DevicePolicy")) {
|
||||
const char *policy;
|
||||
CGroupDevicePolicy p;
|
||||
@ -1170,10 +1076,8 @@ int bus_cgroup_set_property(
|
||||
|
||||
while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
|
||||
|
||||
if ((!path_startswith(path, "/dev/") &&
|
||||
!path_startswith(path, "/run/systemd/inaccessible/") &&
|
||||
!startswith(path, "block-") &&
|
||||
!startswith(path, "char-")) ||
|
||||
if ((!is_deviceallow_pattern(path) &&
|
||||
!path_startswith(path, "/run/systemd/inaccessible/")) ||
|
||||
strpbrk(path, WHITESPACE))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "DeviceAllow= requires device node");
|
||||
|
||||
@ -1450,12 +1354,8 @@ int bus_cgroup_set_property(
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (u->transient && u->load_state == UNIT_STUB) {
|
||||
r = bus_cgroup_set_transient_property(u, c, name, message, flags, error);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
}
|
||||
if (u->transient && u->load_state == UNIT_STUB)
|
||||
return bus_cgroup_set_transient_property(u, c, name, message, flags, error);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1036,6 +1036,121 @@ int bus_property_get_exec_command_list(
|
||||
return sd_bus_message_close_container(reply);
|
||||
}
|
||||
|
||||
int bus_exec_command_set_transient_property(
|
||||
Unit *u,
|
||||
const char *name,
|
||||
ExecCommand **exec_command,
|
||||
sd_bus_message *message,
|
||||
UnitWriteFlags flags,
|
||||
sd_bus_error *error) {
|
||||
unsigned n = 0;
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_enter_container(message, 'a', "(sasb)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
|
||||
_cleanup_strv_free_ char **argv = NULL;
|
||||
const char *path;
|
||||
int b;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!path_is_absolute(path))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
|
||||
|
||||
r = sd_bus_message_read_strv(message, &argv);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_read(message, "b", &b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
ExecCommand *c;
|
||||
|
||||
c = new0(ExecCommand, 1);
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
c->path = strdup(path);
|
||||
if (!c->path) {
|
||||
free(c);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
c->argv = argv;
|
||||
argv = NULL;
|
||||
|
||||
c->flags = b ? EXEC_COMMAND_IGNORE_FAILURE : 0;
|
||||
|
||||
path_kill_slashes(c->path);
|
||||
exec_command_append_list(exec_command, c);
|
||||
}
|
||||
|
||||
n++;
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
ExecCommand *c;
|
||||
size_t size = 0;
|
||||
|
||||
if (n == 0)
|
||||
*exec_command = exec_command_free_list(*exec_command);
|
||||
|
||||
f = open_memstream(&buf, &size);
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
fputs("ExecStart=\n", f);
|
||||
|
||||
LIST_FOREACH(command, c, *exec_command) {
|
||||
_cleanup_free_ char *a = NULL, *t = NULL;
|
||||
const char *p;
|
||||
|
||||
p = unit_escape_setting(c->path, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS, &t);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
a = unit_concat_strv(c->argv, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS);
|
||||
if (!a)
|
||||
return -ENOMEM;
|
||||
|
||||
fprintf(f, "%s=%s@%s %s\n",
|
||||
name,
|
||||
c->flags & EXEC_COMMAND_IGNORE_FAILURE ? "-" : "",
|
||||
p,
|
||||
a);
|
||||
}
|
||||
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
unit_write_setting(u, flags, name, buf);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int bus_exec_context_set_transient_property(
|
||||
Unit *u,
|
||||
ExecContext *c,
|
||||
@ -1054,7 +1169,7 @@ int bus_exec_context_set_transient_property(
|
||||
|
||||
flags |= UNIT_PRIVATE;
|
||||
|
||||
if (streq(name, "User")) {
|
||||
if (STR_IN_SET(name, "User", "Group")) {
|
||||
const char *uu;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &uu);
|
||||
@ -1062,36 +1177,18 @@ int bus_exec_context_set_transient_property(
|
||||
return r;
|
||||
|
||||
if (!isempty(uu) && !valid_user_group_name_or_id(uu))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid user name: %s", uu);
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %s", name, uu);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
|
||||
r = free_and_strdup(&c->user, empty_to_null(uu));
|
||||
if (streq(name, "User"))
|
||||
r = free_and_strdup(&c->user, empty_to_null(uu));
|
||||
else /* "Group" */
|
||||
r = free_and_strdup(&c->group, empty_to_null(uu));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "User=%s", uu);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "Group")) {
|
||||
const char *gg;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &gg);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!isempty(gg) && !valid_user_group_name_or_id(gg))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid group name: %s", gg);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
|
||||
r = free_and_strdup(&c->group, empty_to_null(gg));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "Group=%s", gg);
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, uu);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -1139,10 +1236,9 @@ int bus_exec_context_set_transient_property(
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
|
||||
if (isempty(id))
|
||||
c->syslog_identifier = mfree(c->syslog_identifier);
|
||||
else if (free_and_strdup(&c->syslog_identifier, id) < 0)
|
||||
return -ENOMEM;
|
||||
r = free_and_strdup(&c->syslog_identifier, empty_to_null(id));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "SyslogIdentifier=%s", id);
|
||||
}
|
||||
@ -1361,59 +1457,42 @@ int bus_exec_context_set_transient_property(
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
_cleanup_free_ char *joined = NULL;
|
||||
bool invert = !whitelist;
|
||||
char **s;
|
||||
|
||||
if (strv_isempty(l)) {
|
||||
c->syscall_whitelist = false;
|
||||
c->syscall_filter = hashmap_free(c->syscall_filter);
|
||||
} else {
|
||||
char **s;
|
||||
|
||||
unit_write_settingf(u, flags, name, "SystemCallFilter=");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!c->syscall_filter) {
|
||||
c->syscall_filter = hashmap_new(NULL);
|
||||
if (!c->syscall_filter)
|
||||
return log_oom();
|
||||
|
||||
c->syscall_whitelist = whitelist;
|
||||
|
||||
r = hashmap_ensure_allocated(&c->syscall_filter, NULL);
|
||||
if (c->syscall_whitelist) {
|
||||
r = seccomp_parse_syscall_filter(invert, "@default", -1, c->syscall_filter, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
STRV_FOREACH(s, l) {
|
||||
_cleanup_free_ char *n = NULL;
|
||||
int e;
|
||||
|
||||
r = parse_syscall_and_errno(*s, &n, &e);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(s, l) {
|
||||
_cleanup_free_ char *n = NULL;
|
||||
int e;
|
||||
|
||||
r = parse_syscall_and_errno(*s, &n, &e);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (*n == '@') {
|
||||
const SyscallFilterSet *set;
|
||||
const char *i;
|
||||
|
||||
set = syscall_filter_set_find(n);
|
||||
if (!set)
|
||||
return -EINVAL;
|
||||
|
||||
NULSTR_FOREACH(i, set->value) {
|
||||
int id;
|
||||
|
||||
id = seccomp_syscall_resolve_name(i);
|
||||
if (id == __NR_SCMP_ERROR)
|
||||
return -EINVAL;
|
||||
|
||||
r = hashmap_put(c->syscall_filter, INT_TO_PTR(id + 1), INT_TO_PTR(e));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
} else {
|
||||
int id;
|
||||
|
||||
id = seccomp_syscall_resolve_name(n);
|
||||
if (id == __NR_SCMP_ERROR)
|
||||
return -EINVAL;
|
||||
|
||||
r = hashmap_put(c->syscall_filter, INT_TO_PTR(id + 1), INT_TO_PTR(e));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
r = seccomp_parse_syscall_filter(invert, n, e, c->syscall_filter, c->syscall_whitelist);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
joined = strv_join(l, " ");
|
||||
@ -1507,30 +1586,38 @@ int bus_exec_context_set_transient_property(
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
_cleanup_free_ char *joined = NULL;
|
||||
bool invert = !whitelist;
|
||||
char **s;
|
||||
|
||||
if (strv_isempty(l)) {
|
||||
c->address_families_whitelist = false;
|
||||
c->address_families = set_free(c->address_families);
|
||||
} else {
|
||||
char **s;
|
||||
|
||||
unit_write_settingf(u, flags, name, "RestrictAddressFamilies=");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!c->address_families) {
|
||||
c->address_families = set_new(NULL);
|
||||
if (!c->address_families)
|
||||
return log_oom();
|
||||
|
||||
c->address_families_whitelist = whitelist;
|
||||
}
|
||||
|
||||
r = set_ensure_allocated(&c->address_families, NULL);
|
||||
if (r < 0)
|
||||
return r;
|
||||
STRV_FOREACH(s, l) {
|
||||
int af;
|
||||
|
||||
STRV_FOREACH(s, l) {
|
||||
int af;
|
||||
|
||||
af = af_from_name(*s);
|
||||
if (af <= 0)
|
||||
return -EINVAL;
|
||||
af = af_from_name(*s);
|
||||
if (af <= 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (!invert == c->address_families_whitelist) {
|
||||
r = set_put(c->address_families, INT_TO_PTR(af));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
} else
|
||||
(void) set_remove(c->address_families, INT_TO_PTR(af));
|
||||
}
|
||||
|
||||
joined = strv_join(l, " ");
|
||||
@ -1573,7 +1660,7 @@ int bus_exec_context_set_transient_property(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!ioprio_priority_is_valid(n))
|
||||
if (!sched_priority_is_valid(n))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid CPU scheduling priority");
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
@ -1717,17 +1804,17 @@ int bus_exec_context_set_transient_property(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!path_is_absolute(s))
|
||||
if (!isempty(s) && !path_is_absolute(s))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s takes an absolute path", name);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
if (streq(name, "TTYPath"))
|
||||
r = free_and_strdup(&c->tty_path, s);
|
||||
r = free_and_strdup(&c->tty_path, empty_to_null(s));
|
||||
else if (streq(name, "RootImage"))
|
||||
r = free_and_strdup(&c->root_image, s);
|
||||
r = free_and_strdup(&c->root_image, empty_to_null(s));
|
||||
else {
|
||||
assert(streq(name, "RootDirectory"));
|
||||
r = free_and_strdup(&c->root_directory, s);
|
||||
r = free_and_strdup(&c->root_directory, empty_to_null(s));
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
@ -1751,7 +1838,7 @@ int bus_exec_context_set_transient_property(
|
||||
} else
|
||||
missing_ok = false;
|
||||
|
||||
if (!streq(s, "~") && !path_is_absolute(s))
|
||||
if (!isempty(s) && !streq(s, "~") && !path_is_absolute(s))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'");
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
@ -1759,7 +1846,7 @@ int bus_exec_context_set_transient_property(
|
||||
c->working_directory = mfree(c->working_directory);
|
||||
c->working_directory_home = true;
|
||||
} else {
|
||||
r = free_and_strdup(&c->working_directory, s);
|
||||
r = free_and_strdup(&c->working_directory, empty_to_null(s));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1840,15 +1927,13 @@ int bus_exec_context_set_transient_property(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (isempty(s))
|
||||
s = NULL;
|
||||
else if (!fdname_is_valid(s))
|
||||
if (!isempty(s) && !fdname_is_valid(s))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid file descriptor name");
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
|
||||
if (streq(name, "StandardInputFileDescriptorName")) {
|
||||
r = free_and_strdup(c->stdio_fdname + STDIN_FILENO, s);
|
||||
r = free_and_strdup(c->stdio_fdname + STDIN_FILENO, empty_to_null(s));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1856,7 +1941,7 @@ int bus_exec_context_set_transient_property(
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardInput=fd:%s", exec_context_fdname(c, STDIN_FILENO));
|
||||
|
||||
} else if (streq(name, "StandardOutputFileDescriptorName")) {
|
||||
r = free_and_strdup(c->stdio_fdname + STDOUT_FILENO, s);
|
||||
r = free_and_strdup(c->stdio_fdname + STDOUT_FILENO, empty_to_null(s));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1866,7 +1951,7 @@ int bus_exec_context_set_transient_property(
|
||||
} else {
|
||||
assert(streq(name, "StandardErrorFileDescriptorName"));
|
||||
|
||||
r = free_and_strdup(&c->stdio_fdname[STDERR_FILENO], s);
|
||||
r = free_and_strdup(&c->stdio_fdname[STDERR_FILENO], empty_to_null(s));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1884,15 +1969,17 @@ int bus_exec_context_set_transient_property(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!path_is_absolute(s))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute", s);
|
||||
if (!path_is_normalized(s))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not normalized", s);
|
||||
if (!isempty(s)) {
|
||||
if (!path_is_absolute(s))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute", s);
|
||||
if (!path_is_normalized(s))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not normalized", s);
|
||||
}
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
|
||||
if (streq(name, "StandardInputFile")) {
|
||||
r = free_and_strdup(&c->stdio_file[STDIN_FILENO], s);
|
||||
r = free_and_strdup(&c->stdio_file[STDIN_FILENO], empty_to_null(s));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1900,7 +1987,7 @@ int bus_exec_context_set_transient_property(
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "StandardInput=file:%s", s);
|
||||
|
||||
} else if (streq(name, "StandardOutputFile")) {
|
||||
r = free_and_strdup(&c->stdio_file[STDOUT_FILENO], s);
|
||||
r = free_and_strdup(&c->stdio_file[STDOUT_FILENO], empty_to_null(s));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1910,7 +1997,7 @@ int bus_exec_context_set_transient_property(
|
||||
} else {
|
||||
assert(streq(name, "StandardErrorFile"));
|
||||
|
||||
r = free_and_strdup(&c->stdio_file[STDERR_FILENO], s);
|
||||
r = free_and_strdup(&c->stdio_file[STDERR_FILENO], empty_to_null(s));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -2323,7 +2410,7 @@ int bus_exec_context_set_transient_property(
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(p, l) {
|
||||
const char *i = *p;
|
||||
char *i = *p;
|
||||
size_t offset;
|
||||
|
||||
if (!utf8_is_valid(i))
|
||||
@ -2333,6 +2420,8 @@ int bus_exec_context_set_transient_property(
|
||||
offset += i[offset] == '+';
|
||||
if (!path_is_absolute(i + offset))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
|
||||
|
||||
path_kill_slashes(i + offset);
|
||||
}
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
@ -2527,15 +2616,16 @@ int bus_exec_context_set_transient_property(
|
||||
|
||||
} else if (streq(name, "SELinuxContext")) {
|
||||
const char *s;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &s);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
if (isempty(s))
|
||||
c->selinux_context = mfree(c->selinux_context);
|
||||
else if (free_and_strdup(&c->selinux_context, s) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
r = free_and_strdup(&c->selinux_context, empty_to_null(s));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, strempty(s));
|
||||
}
|
||||
|
@ -44,3 +44,4 @@ int bus_property_get_exec_command(sd_bus *bus, const char *path, const char *int
|
||||
int bus_property_get_exec_command_list(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error);
|
||||
|
||||
int bus_exec_context_set_transient_property(Unit *u, ExecContext *c, const char *name, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
int bus_exec_command_set_transient_property(Unit *u, const char *name, ExecCommand **exec_command, sd_bus_message *message, UnitWriteFlags flags, sd_bus_error *error);
|
||||
|
@ -239,114 +239,8 @@ static int bus_service_set_transient_property(
|
||||
|
||||
return 1;
|
||||
|
||||
} else if ((ci = service_exec_command_from_string(name)) >= 0) {
|
||||
unsigned n = 0;
|
||||
|
||||
r = sd_bus_message_enter_container(message, 'a', "(sasb)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
|
||||
_cleanup_strv_free_ char **argv = NULL;
|
||||
const char *path;
|
||||
int b;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &path);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!path_is_absolute(path))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
|
||||
|
||||
r = sd_bus_message_read_strv(message, &argv);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_read(message, "b", &b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
ExecCommand *c;
|
||||
|
||||
c = new0(ExecCommand, 1);
|
||||
if (!c)
|
||||
return -ENOMEM;
|
||||
|
||||
c->path = strdup(path);
|
||||
if (!c->path) {
|
||||
free(c);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
c->argv = argv;
|
||||
argv = NULL;
|
||||
|
||||
c->flags = b ? EXEC_COMMAND_IGNORE_FAILURE : 0;
|
||||
|
||||
path_kill_slashes(c->path);
|
||||
exec_command_append_list(&s->exec_command[ci], c);
|
||||
}
|
||||
|
||||
n++;
|
||||
}
|
||||
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
_cleanup_free_ char *buf = NULL;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
ExecCommand *c;
|
||||
size_t size = 0;
|
||||
|
||||
if (n == 0)
|
||||
s->exec_command[ci] = exec_command_free_list(s->exec_command[ci]);
|
||||
|
||||
f = open_memstream(&buf, &size);
|
||||
if (!f)
|
||||
return -ENOMEM;
|
||||
|
||||
(void) __fsetlocking(f, FSETLOCKING_BYCALLER);
|
||||
|
||||
fputs("ExecStart=\n", f);
|
||||
|
||||
LIST_FOREACH(command, c, s->exec_command[ci]) {
|
||||
_cleanup_free_ char *a = NULL, *t = NULL;
|
||||
const char *p;
|
||||
|
||||
p = unit_escape_setting(c->path, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS, &t);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
a = unit_concat_strv(c->argv, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS);
|
||||
if (!a)
|
||||
return -ENOMEM;
|
||||
|
||||
fprintf(f, "%s=%s@%s %s\n",
|
||||
name,
|
||||
c->flags & EXEC_COMMAND_IGNORE_FAILURE ? "-" : "",
|
||||
p,
|
||||
a);
|
||||
}
|
||||
|
||||
r = fflush_and_check(f);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
unit_write_setting(UNIT(s), flags, name, buf);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
} else if ((ci = service_exec_command_from_string(name)) >= 0)
|
||||
return bus_exec_command_set_transient_property(UNIT(s), name, &s->exec_command[ci], message, flags, error);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -22,10 +22,18 @@
|
||||
#include "bus-util.h"
|
||||
#include "dbus-cgroup.h"
|
||||
#include "dbus-execute.h"
|
||||
#include "dbus-kill.h"
|
||||
#include "dbus-socket.h"
|
||||
#include "fd-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "socket.h"
|
||||
#include "socket-protocol-list.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
#include "unit.h"
|
||||
#include "user-util.h"
|
||||
#include "utf8.h"
|
||||
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, socket_result, SocketResult);
|
||||
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_bind_ipv6_only, socket_address_bind_ipv6_only, SocketAddressBindIPv6Only);
|
||||
@ -141,6 +149,7 @@ const sd_bus_vtable bus_socket_vtable[] = {
|
||||
SD_BUS_PROPERTY("MaxConnectionsPerSource", "u", bus_property_get_unsigned, offsetof(Socket, max_connections_per_source), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("MessageQueueMaxMessages", "x", bus_property_get_long, offsetof(Socket, mq_maxmsg), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("MessageQueueMessageSize", "x", bus_property_get_long, offsetof(Socket, mq_msgsize), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("TCPCongestion", "s", NULL, offsetof(Socket, tcp_congestion), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("ReusePort", "b", bus_property_get_bool, offsetof(Socket, reuse_port), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("SmackLabel", "s", NULL, offsetof(Socket, smack), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
SD_BUS_PROPERTY("SmackLabelIPIn", "s", NULL, offsetof(Socket, smack_ip_in), SD_BUS_VTABLE_PROPERTY_CONST),
|
||||
@ -162,6 +171,465 @@ const sd_bus_vtable bus_socket_vtable[] = {
|
||||
SD_BUS_VTABLE_END
|
||||
};
|
||||
|
||||
static int bus_socket_set_transient_property(
|
||||
Socket *s,
|
||||
const char *name,
|
||||
sd_bus_message *message,
|
||||
UnitWriteFlags flags,
|
||||
sd_bus_error *error) {
|
||||
|
||||
SocketExecCommand ci;
|
||||
Unit *u = UNIT(s);
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(name);
|
||||
assert(message);
|
||||
|
||||
flags |= UNIT_PRIVATE;
|
||||
|
||||
if (STR_IN_SET(name,
|
||||
"Accept", "Writable", "KeepAlive", "NoDelay", "FreeBind", "Transparent", "Broadcast",
|
||||
"PassCredentials", "PassSecurity", "ReusePort", "RemoveOnStop", "SELinuxContextFromNet")) {
|
||||
int b;
|
||||
|
||||
r = sd_bus_message_read(message, "b", &b);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
if (streq(name, "Accept"))
|
||||
s->accept = b;
|
||||
else if (streq(name, "Writable"))
|
||||
s->writable = b;
|
||||
else if (streq(name, "KeepAlive"))
|
||||
s->keep_alive = b;
|
||||
else if (streq(name, "NoDelay"))
|
||||
s->no_delay = b;
|
||||
else if (streq(name, "FreeBind"))
|
||||
s->free_bind = b;
|
||||
else if (streq(name, "Transparent"))
|
||||
s->transparent = b;
|
||||
else if (streq(name, "Broadcast"))
|
||||
s->broadcast = b;
|
||||
else if (streq(name, "PassCredentials"))
|
||||
s->pass_cred = b;
|
||||
else if (streq(name, "PassSecurity"))
|
||||
s->pass_sec = b;
|
||||
else if (streq(name, "ReusePort"))
|
||||
s->reuse_port = b;
|
||||
else if (streq(name, "RemoveOnStop"))
|
||||
s->remove_on_stop = b;
|
||||
else /* "SELinuxContextFromNet" */
|
||||
s->selinux_context_from_net = b;
|
||||
|
||||
unit_write_settingf(u, flags, name, "%s=%s", name, yes_no(b));
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "Priority", "IPTTL", "Mark")) {
|
||||
int32_t i;
|
||||
|
||||
r = sd_bus_message_read(message, "i", &i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
if (streq(name, "Priority"))
|
||||
s->priority = i;
|
||||
else if (streq(name, "IPTTL"))
|
||||
s->ip_ttl = i;
|
||||
else /* "Mark" */
|
||||
s->mark = i;
|
||||
|
||||
unit_write_settingf(u, flags, name, "%s=%i", name, i);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "IPTOS")) {
|
||||
_cleanup_free_ char *str = NULL;
|
||||
int32_t i;
|
||||
|
||||
r = sd_bus_message_read(message, "i", &i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ip_tos_to_string_alloc(i, &str);
|
||||
if (r < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %i", name, i);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
s->ip_tos = i;
|
||||
|
||||
unit_write_settingf(u, flags, name, "%s=%s", name, str);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "SocketProtocol")) {
|
||||
const char *p;
|
||||
int32_t i;
|
||||
|
||||
r = sd_bus_message_read(message, "i", &i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
p = socket_protocol_to_name(i);
|
||||
if (!p)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %i", name, i);
|
||||
|
||||
if (!IN_SET(i, IPPROTO_UDPLITE, IPPROTO_SCTP))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported socket protocol: %s", p);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
s->socket_protocol = i;
|
||||
unit_write_settingf(u, flags, name, "%s=%s", name, p);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "Backlog", "MaxConnections", "MaxConnectionsPerSource", "KeepAliveProbes", "TriggerLimitBurst")) {
|
||||
uint32_t n;
|
||||
|
||||
r = sd_bus_message_read(message, "u", &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
if (streq(name, "Backlog"))
|
||||
s->backlog = n;
|
||||
else if (streq(name, "MaxConnections"))
|
||||
s->max_connections = n;
|
||||
else if (streq(name, "MaxConnectionsPerSource"))
|
||||
s->max_connections_per_source = n;
|
||||
else if (streq(name, "KeepAliveProbes"))
|
||||
s->keep_alive_cnt = n;
|
||||
else /* "TriggerLimitBurst" */
|
||||
s->trigger_limit.burst = n;
|
||||
|
||||
unit_write_settingf(u, flags, name, "%s=%u", name, n);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "SocketMode", "DirectoryMode")) {
|
||||
mode_t m;
|
||||
|
||||
r = sd_bus_message_read(message, "u", &m);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
if (streq(name, "SocketMode"))
|
||||
s->socket_mode = m;
|
||||
else /* "DirectoryMode" */
|
||||
s->directory_mode = m;
|
||||
|
||||
unit_write_settingf(u, flags, name, "%s=%040o", name, m);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "MessageQueueMaxMessages", "MessageQueueMessageSize")) {
|
||||
int64_t n;
|
||||
|
||||
r = sd_bus_message_read(message, "x", &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
if (streq(name, "MessageQueueMaxMessages"))
|
||||
s->mq_maxmsg = (long) n;
|
||||
else /* "MessageQueueMessageSize" */
|
||||
s->mq_msgsize = (long) n;
|
||||
|
||||
unit_write_settingf(u, flags, name, "%s=%" PRIi64, name, n);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "TimeoutUSec", "KeepAliveTimeUSec", "KeepAliveIntervalUSec", "DeferAcceptUSec", "TriggerLimitIntervalUSec")) {
|
||||
usec_t t;
|
||||
|
||||
r = sd_bus_message_read(message, "t", &t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
if (streq(name, "TimeoutUSec"))
|
||||
s->timeout_usec = t ?: USEC_INFINITY;
|
||||
else if (streq(name, "KeepAliveTimeUSec"))
|
||||
s->keep_alive_time = t;
|
||||
else if (streq(name, "KeepAliveIntervalUSec"))
|
||||
s->keep_alive_interval = t;
|
||||
else if (streq(name, "DeferAcceptUSec"))
|
||||
s->defer_accept = t;
|
||||
else /* "TriggerLimitIntervalUSec" */
|
||||
s->trigger_limit.interval = t;
|
||||
|
||||
unit_write_settingf(u, flags, name, "%s=" USEC_FMT, name, t);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "ReceiveBuffer", "SendBuffer", "PipeSize")) {
|
||||
uint64_t t;
|
||||
|
||||
r = sd_bus_message_read(message, "t", &t);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if ((uint64_t) (size_t) t != t)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %" PRIu64, name, t);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
if (streq(name, "ReceiveBuffer"))
|
||||
s->receive_buffer = t;
|
||||
else if (streq(name, "SendBuffer"))
|
||||
s->send_buffer = t;
|
||||
else /* "PipeSize" */
|
||||
s->pipe_size = t;
|
||||
|
||||
unit_write_settingf(u, flags, name, "%s=%" PRIu64, name, t);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "SmackLabel", "SmackLabelIPIn", "SmackLabelIPOut", "TCPCongestion")) {
|
||||
const char *n;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
|
||||
if (streq(name, "SmackLabel"))
|
||||
r = free_and_strdup(&s->smack, empty_to_null(n));
|
||||
else if (streq(name, "SmackLabelIPin"))
|
||||
r = free_and_strdup(&s->smack_ip_in, empty_to_null(n));
|
||||
else if (streq(name, "SmackLabelIPOut"))
|
||||
r = free_and_strdup(&s->smack_ip_out, empty_to_null(n));
|
||||
else /* "TCPCongestion" */
|
||||
r = free_and_strdup(&s->tcp_congestion, empty_to_null(n));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, strempty(n));
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "BindToDevice")) {
|
||||
const char *n;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (n[0] && !streq(n, "*")) {
|
||||
if (!ifname_valid(n))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid interface name for %s: %s", name, n);
|
||||
} else
|
||||
n = NULL;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
|
||||
r = free_and_strdup(&s->bind_to_device, empty_to_null(n));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, strempty(n));
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "BindIPv6Only")) {
|
||||
SocketAddressBindIPv6Only b;
|
||||
const char *n;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
b = socket_address_bind_ipv6_only_from_string(n);
|
||||
if (b < 0) {
|
||||
r = parse_boolean(n);
|
||||
if (r < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %s", name, n);
|
||||
|
||||
b = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
|
||||
}
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
s->bind_ipv6_only = b;
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, n);
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "FileDescriptorName")) {
|
||||
const char *n;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!isempty(n) && !fdname_is_valid(n))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %s", name, n);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
r = free_and_strdup(&s->fdname, empty_to_null(n));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, strempty(n));
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (STR_IN_SET(name, "SocketUser", "SocketGroup")) {
|
||||
const char *n;
|
||||
|
||||
r = sd_bus_message_read(message, "s", &n);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!isempty(n) && !valid_user_group_name_or_id(n))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s: %s", name, n);
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
|
||||
if (streq(name, "SocketUser"))
|
||||
r = free_and_strdup(&s->user, empty_to_null(n));
|
||||
else /* "SocketGroup" */
|
||||
r = free_and_strdup(&s->user, empty_to_null(n));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, strempty(n));
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "Symlinks")) {
|
||||
_cleanup_strv_free_ char **l = NULL;
|
||||
char **p;
|
||||
|
||||
r = sd_bus_message_read_strv(message, &l);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
STRV_FOREACH(p, l) {
|
||||
if (!utf8_is_valid(*p))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "String is not UTF-8 clean, ignoring assignment: %s", *p);
|
||||
|
||||
if (!path_is_absolute(*p))
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Symlink path is not absolute: %s", *p);
|
||||
}
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
if (strv_isempty(l)) {
|
||||
s->symlinks = strv_free(s->symlinks);
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=", name);
|
||||
} else {
|
||||
_cleanup_free_ char *joined = NULL;
|
||||
|
||||
r = strv_extend_strv(&s->symlinks, l, true);
|
||||
if (r < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
joined = strv_join(l, " ");
|
||||
if (!joined)
|
||||
return -ENOMEM;
|
||||
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "%s=%s", name, joined);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if (streq(name, "Listen")) {
|
||||
const char *t, *a;
|
||||
bool empty = true;
|
||||
|
||||
r = sd_bus_message_enter_container(message, 'a', "(ss)");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
while ((r = sd_bus_message_read(message, "(ss)", &t, &a)) > 0) {
|
||||
_cleanup_free_ SocketPort *p = NULL;
|
||||
|
||||
p = new0(SocketPort, 1);
|
||||
if (!p)
|
||||
return log_oom();
|
||||
|
||||
p->type = socket_port_type_from_string(t);
|
||||
if (p->type < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown Socket type: %s", t);
|
||||
|
||||
if (p->type != SOCKET_SOCKET) {
|
||||
p->path = strdup(a);
|
||||
path_kill_slashes(p->path);
|
||||
|
||||
} else if (streq(t, "Netlink")) {
|
||||
r = socket_address_parse_netlink(&p->address, a);
|
||||
if (r < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid netlink address: %s", a);
|
||||
|
||||
} else {
|
||||
r = socket_address_parse(&p->address, a);
|
||||
if (r < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address: %s", a);
|
||||
|
||||
p->address.type = socket_address_type_from_string(t);
|
||||
if (p->address.type < 0)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid address type: %s", t);
|
||||
|
||||
if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET)
|
||||
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Address family not supported: %s", a);
|
||||
}
|
||||
|
||||
p->fd = -1;
|
||||
p->auxiliary_fds = NULL;
|
||||
p->n_auxiliary_fds = 0;
|
||||
p->socket = s;
|
||||
|
||||
empty = false;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
|
||||
SocketPort *tail;
|
||||
|
||||
LIST_FIND_TAIL(port, s->ports, tail);
|
||||
LIST_INSERT_AFTER(port, s->ports, tail, p);
|
||||
|
||||
p = NULL;
|
||||
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "Listen%s=%s", t, a);
|
||||
}
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_bus_message_exit_container(message);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!UNIT_WRITE_FLAGS_NOOP(flags) && empty) {
|
||||
socket_free_ports(s);
|
||||
unit_write_settingf(u, flags|UNIT_ESCAPE_SPECIFIERS, name, "ListenStream=");
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
} else if ((ci = socket_exec_command_from_string(name)) >= 0)
|
||||
return bus_exec_command_set_transient_property(UNIT(s), name, &s->exec_command[ci], message, flags, error);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bus_socket_set_property(
|
||||
Unit *u,
|
||||
const char *name,
|
||||
@ -170,12 +638,37 @@ int bus_socket_set_property(
|
||||
sd_bus_error *error) {
|
||||
|
||||
Socket *s = SOCKET(u);
|
||||
int r;
|
||||
|
||||
assert(s);
|
||||
assert(name);
|
||||
assert(message);
|
||||
|
||||
return bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error);
|
||||
assert(s);
|
||||
assert(name);
|
||||
assert(message);
|
||||
|
||||
r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
if (u->transient && u->load_state == UNIT_STUB) {
|
||||
/* This is a transient unit, let's load a little more */
|
||||
|
||||
r = bus_socket_set_transient_property(s, name, message, flags, error);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = bus_exec_context_set_transient_property(u, &s->exec_context, name, message, flags, error);
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, flags, error);
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bus_socket_commit_properties(Unit *u) {
|
||||
|
@ -4162,19 +4162,19 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
|
||||
if (c->pam_name)
|
||||
fprintf(f, "%sPAMName: %s\n", prefix, c->pam_name);
|
||||
|
||||
if (strv_length(c->read_write_paths) > 0) {
|
||||
if (!strv_isempty(c->read_write_paths)) {
|
||||
fprintf(f, "%sReadWritePaths:", prefix);
|
||||
strv_fprintf(f, c->read_write_paths);
|
||||
fputs("\n", f);
|
||||
}
|
||||
|
||||
if (strv_length(c->read_only_paths) > 0) {
|
||||
if (!strv_isempty(c->read_only_paths)) {
|
||||
fprintf(f, "%sReadOnlyPaths:", prefix);
|
||||
strv_fprintf(f, c->read_only_paths);
|
||||
fputs("\n", f);
|
||||
}
|
||||
|
||||
if (strv_length(c->inaccessible_paths) > 0) {
|
||||
if (!strv_isempty(c->inaccessible_paths)) {
|
||||
fprintf(f, "%sInaccessiblePaths:", prefix);
|
||||
strv_fprintf(f, c->inaccessible_paths);
|
||||
fputs("\n", f);
|
||||
|
@ -64,6 +64,7 @@
|
||||
#include "securebits.h"
|
||||
#include "securebits-util.h"
|
||||
#include "signal-util.h"
|
||||
#include "socket-protocol-list.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
@ -433,11 +434,9 @@ int config_parse_socket_listen(const char *unit,
|
||||
p->n_auxiliary_fds = 0;
|
||||
p->socket = s;
|
||||
|
||||
if (s->ports) {
|
||||
LIST_FIND_TAIL(port, s->ports, tail);
|
||||
LIST_INSERT_AFTER(port, s->ports, tail, p);
|
||||
} else
|
||||
LIST_PREPEND(port, s->ports, p);
|
||||
LIST_FIND_TAIL(port, s->ports, tail);
|
||||
LIST_INSERT_AFTER(port, s->ports, tail, p);
|
||||
|
||||
p = NULL;
|
||||
|
||||
return 0;
|
||||
@ -454,6 +453,7 @@ int config_parse_socket_protocol(const char *unit,
|
||||
void *data,
|
||||
void *userdata) {
|
||||
Socket *s;
|
||||
int r;
|
||||
|
||||
assert(filename);
|
||||
assert(lvalue);
|
||||
@ -462,15 +462,17 @@ int config_parse_socket_protocol(const char *unit,
|
||||
|
||||
s = SOCKET(data);
|
||||
|
||||
if (streq(rvalue, "udplite"))
|
||||
s->socket_protocol = IPPROTO_UDPLITE;
|
||||
else if (streq(rvalue, "sctp"))
|
||||
s->socket_protocol = IPPROTO_SCTP;
|
||||
else {
|
||||
r = socket_protocol_from_name(rvalue);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid socket protocol, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
} else if (!IN_SET(r, IPPROTO_UDPLITE, IPPROTO_SCTP)) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Socket protocol not supported, ignoring: %s", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->socket_protocol = r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2891,60 +2893,6 @@ int config_parse_documentation(const char *unit,
|
||||
}
|
||||
|
||||
#if HAVE_SECCOMP
|
||||
|
||||
static int syscall_filter_parse_one(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line,
|
||||
ExecContext *c,
|
||||
bool invert,
|
||||
const char *t,
|
||||
bool warn,
|
||||
int errno_num) {
|
||||
int r;
|
||||
|
||||
if (t[0] == '@') {
|
||||
const SyscallFilterSet *set;
|
||||
const char *i;
|
||||
|
||||
set = syscall_filter_set_find(t);
|
||||
if (!set) {
|
||||
if (warn)
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown system call group, ignoring: %s", t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
NULSTR_FOREACH(i, set->value) {
|
||||
r = syscall_filter_parse_one(unit, filename, line, c, invert, i, false, errno_num);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
int id;
|
||||
|
||||
id = seccomp_syscall_resolve_name(t);
|
||||
if (id == __NR_SCMP_ERROR) {
|
||||
if (warn)
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse system call, ignoring: %s", t);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If we previously wanted to forbid a syscall and now
|
||||
* we want to allow it, then remove it from the list.
|
||||
*/
|
||||
if (!invert == c->syscall_whitelist) {
|
||||
r = hashmap_put(c->syscall_filter, INT_TO_PTR(id + 1), INT_TO_PTR(errno_num));
|
||||
if (r == 0)
|
||||
return 0;
|
||||
if (r < 0)
|
||||
return log_oom();
|
||||
} else
|
||||
(void) hashmap_remove(c->syscall_filter, INT_TO_PTR(id + 1));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_parse_syscall_filter(
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
@ -2993,7 +2941,7 @@ int config_parse_syscall_filter(
|
||||
c->syscall_whitelist = true;
|
||||
|
||||
/* Accept default syscalls if we are on a whitelist */
|
||||
r = syscall_filter_parse_one(unit, filename, line, c, false, "@default", false, -1);
|
||||
r = seccomp_parse_syscall_filter(false, "@default", -1, c->syscall_filter, true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -3020,7 +2968,7 @@ int config_parse_syscall_filter(
|
||||
continue;
|
||||
}
|
||||
|
||||
r = syscall_filter_parse_one(unit, filename, line, c, invert, name, true, num);
|
||||
r = seccomp_parse_syscall_filter_and_warn(invert, name, num, c->syscall_filter, c->syscall_whitelist, unit, filename, line);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -3575,7 +3523,8 @@ int config_parse_device_allow(
|
||||
if (!path)
|
||||
return log_oom();
|
||||
|
||||
if (!is_deviceallow_pattern(path)) {
|
||||
if (!is_deviceallow_pattern(path) &&
|
||||
!path_startswith(path, "/run/systemd/inaccessible/")) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
|
||||
return 0;
|
||||
}
|
||||
@ -3675,7 +3624,8 @@ int config_parse_io_device_weight(
|
||||
if (!path)
|
||||
return log_oom();
|
||||
|
||||
if (!path_startswith(path, "/dev")) {
|
||||
if (!path_startswith(path, "/dev") &&
|
||||
!path_startswith(path, "/run/systemd/inaccessible/")) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
|
||||
return 0;
|
||||
}
|
||||
@ -3748,7 +3698,8 @@ int config_parse_io_limit(
|
||||
if (!path)
|
||||
return log_oom();
|
||||
|
||||
if (!path_startswith(path, "/dev")) {
|
||||
if (!path_startswith(path, "/dev") &&
|
||||
!path_startswith(path, "/run/systemd/inaccessible/")) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
|
||||
return 0;
|
||||
}
|
||||
@ -3862,7 +3813,8 @@ int config_parse_blockio_device_weight(
|
||||
if (!path)
|
||||
return log_oom();
|
||||
|
||||
if (!path_startswith(path, "/dev")) {
|
||||
if (!path_startswith(path, "/dev") &&
|
||||
!path_startswith(path, "/run/systemd/inaccessible/")) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
|
||||
return 0;
|
||||
}
|
||||
@ -3936,7 +3888,8 @@ int config_parse_blockio_bandwidth(
|
||||
if (!path)
|
||||
return log_oom();
|
||||
|
||||
if (!path_startswith(path, "/dev")) {
|
||||
if (!path_startswith(path, "/dev") &&
|
||||
!path_startswith(path, "/run/systemd/inaccessible/")) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid device node path '%s'. Ignoring.", path);
|
||||
return 0;
|
||||
}
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "signal-util.h"
|
||||
#include "smack-util.h"
|
||||
#include "socket.h"
|
||||
#include "socket-protocol-list.h"
|
||||
#include "special.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
@ -655,7 +656,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
SocketExecCommand c;
|
||||
Socket *s = SOCKET(u);
|
||||
SocketPort *p;
|
||||
const char *prefix2;
|
||||
const char *prefix2, *str;
|
||||
|
||||
assert(s);
|
||||
assert(f);
|
||||
@ -680,7 +681,7 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
"%sTCPCongestion: %s\n"
|
||||
"%sRemoveOnStop: %s\n"
|
||||
"%sWritable: %s\n"
|
||||
"%sFDName: %s\n"
|
||||
"%sFileDescriptorName: %s\n"
|
||||
"%sSELinuxContextFromNet: %s\n",
|
||||
prefix, socket_state_to_string(s->state),
|
||||
prefix, socket_result_to_string(s->result),
|
||||
@ -715,10 +716,12 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
fprintf(f,
|
||||
"%sAccepted: %u\n"
|
||||
"%sNConnections: %u\n"
|
||||
"%sMaxConnections: %u\n",
|
||||
"%sMaxConnections: %u\n"
|
||||
"%sMaxConnectionsPerSource: %u\n",
|
||||
prefix, s->n_accepted,
|
||||
prefix, s->n_connections,
|
||||
prefix, s->max_connections);
|
||||
prefix, s->max_connections,
|
||||
prefix, s->max_connections_per_source);
|
||||
|
||||
if (s->priority >= 0)
|
||||
fprintf(f,
|
||||
@ -843,6 +846,24 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
|
||||
prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, s->trigger_limit.interval, USEC_PER_SEC),
|
||||
prefix, s->trigger_limit.burst);
|
||||
|
||||
str = socket_protocol_to_name(s->socket_protocol);
|
||||
if (str)
|
||||
fprintf(f, "%sSocketProtocol: %s\n", prefix, str);
|
||||
|
||||
if (!strv_isempty(s->symlinks)) {
|
||||
char **q;
|
||||
|
||||
fprintf(f, "%sSymlinks:", prefix);
|
||||
STRV_FOREACH(q, s->symlinks)
|
||||
fprintf(f, " %s", *q);
|
||||
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
|
||||
fprintf(f,
|
||||
"%sTimeoutSec: %s\n",
|
||||
prefix, format_timespan(time_string, FORMAT_TIMESPAN_MAX, s->timeout_usec, USEC_PER_SEC));
|
||||
|
||||
exec_context_dump(&s->exec_context, f, prefix);
|
||||
kill_context_dump(&s->kill_context, f, prefix);
|
||||
|
||||
@ -2780,6 +2801,23 @@ const char* socket_port_type_to_string(SocketPort *p) {
|
||||
}
|
||||
}
|
||||
|
||||
SocketType socket_port_type_from_string(const char *s) {
|
||||
assert(s);
|
||||
|
||||
if (STR_IN_SET(s, "Stream", "Datagram", "SequentialPacket", "Netlink"))
|
||||
return SOCKET_SOCKET;
|
||||
else if (streq(s, "Special"))
|
||||
return SOCKET_SPECIAL;
|
||||
else if (streq(s, "MessageQueue"))
|
||||
return SOCKET_MQUEUE;
|
||||
else if (streq(s, "FIFO"))
|
||||
return SOCKET_FIFO;
|
||||
else if (streq(s, "USBFunction"))
|
||||
return SOCKET_USB_FUNCTION;
|
||||
else
|
||||
return _SOCKET_TYPE_INVALID;
|
||||
}
|
||||
|
||||
_pure_ static bool socket_check_gc(Unit *u) {
|
||||
Socket *s = SOCKET(u);
|
||||
|
||||
@ -3212,10 +3250,7 @@ char *socket_fdname(Socket *s) {
|
||||
* didn't specify anything specifically, use the socket unit's
|
||||
* name as fallback. */
|
||||
|
||||
if (s->fdname)
|
||||
return s->fdname;
|
||||
|
||||
return UNIT(s)->id;
|
||||
return s->fdname ?: UNIT(s)->id;
|
||||
}
|
||||
|
||||
static int socket_control_pid(Unit *u) {
|
||||
@ -3227,11 +3262,11 @@ static int socket_control_pid(Unit *u) {
|
||||
}
|
||||
|
||||
static const char* const socket_exec_command_table[_SOCKET_EXEC_COMMAND_MAX] = {
|
||||
[SOCKET_EXEC_START_PRE] = "StartPre",
|
||||
[SOCKET_EXEC_START_CHOWN] = "StartChown",
|
||||
[SOCKET_EXEC_START_POST] = "StartPost",
|
||||
[SOCKET_EXEC_STOP_PRE] = "StopPre",
|
||||
[SOCKET_EXEC_STOP_POST] = "StopPost"
|
||||
[SOCKET_EXEC_START_PRE] = "ExecStartPre",
|
||||
[SOCKET_EXEC_START_CHOWN] = "ExecStartChown",
|
||||
[SOCKET_EXEC_START_POST] = "ExecStartPost",
|
||||
[SOCKET_EXEC_STOP_PRE] = "ExecStopPre",
|
||||
[SOCKET_EXEC_STOP_POST] = "ExecStopPost"
|
||||
};
|
||||
|
||||
DEFINE_STRING_TABLE_LOOKUP(socket_exec_command, SocketExecCommand);
|
||||
@ -3264,6 +3299,8 @@ const UnitVTable socket_vtable = {
|
||||
"Install\0",
|
||||
.private_section = "Socket",
|
||||
|
||||
.can_transient = true,
|
||||
|
||||
.init = socket_init,
|
||||
.done = socket_done,
|
||||
.load = socket_load,
|
||||
|
@ -43,8 +43,8 @@ typedef enum SocketType {
|
||||
SOCKET_SPECIAL,
|
||||
SOCKET_MQUEUE,
|
||||
SOCKET_USB_FUNCTION,
|
||||
_SOCKET_FIFO_MAX,
|
||||
_SOCKET_FIFO_INVALID = -1
|
||||
_SOCKET_TYPE_MAX,
|
||||
_SOCKET_TYPE_INVALID = -1
|
||||
} SocketType;
|
||||
|
||||
typedef enum SocketResult {
|
||||
@ -194,3 +194,4 @@ const char* socket_result_to_string(SocketResult i) _const_;
|
||||
SocketResult socket_result_from_string(const char *s) _pure_;
|
||||
|
||||
const char* socket_port_type_to_string(SocketPort *p) _pure_;
|
||||
SocketType socket_port_type_from_string(const char *p) _pure_;
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "stat-util.h"
|
||||
#include "strv.h"
|
||||
#include "udev-util.h"
|
||||
#include "unit-def.h"
|
||||
#include "unit-name.h"
|
||||
#include "user-util.h"
|
||||
#include "terminal-util.h"
|
||||
@ -403,7 +404,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int transient_unit_set_properties(sd_bus_message *m, char **properties) {
|
||||
static int transient_unit_set_properties(sd_bus_message *m, UnitType t, char **properties) {
|
||||
int r;
|
||||
|
||||
if (!isempty(arg_description)) {
|
||||
@ -432,7 +433,7 @@ static int transient_unit_set_properties(sd_bus_message *m, char **properties) {
|
||||
return r;
|
||||
}
|
||||
|
||||
r = bus_append_unit_property_assignment_many(m, properties);
|
||||
r = bus_append_unit_property_assignment_many(m, t, properties);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -445,7 +446,7 @@ static int transient_mount_set_properties(sd_bus_message *m) {
|
||||
|
||||
assert(m);
|
||||
|
||||
r = transient_unit_set_properties(m, arg_property);
|
||||
r = transient_unit_set_properties(m, UNIT_MOUNT, arg_property);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -503,7 +504,7 @@ static int transient_automount_set_properties(sd_bus_message *m) {
|
||||
|
||||
assert(m);
|
||||
|
||||
r = transient_unit_set_properties(m, arg_automount_property);
|
||||
r = transient_unit_set_properties(m, UNIT_AUTOMOUNT, arg_automount_property);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -179,7 +179,7 @@ int main(int argc, char* argv[]) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (strv_length(final_env) <= 0) {
|
||||
if (strv_isempty(final_env)) {
|
||||
r = 0;
|
||||
goto finish;
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ int register_machine(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = bus_append_unit_property_assignment_many(m, properties);
|
||||
r = bus_append_unit_property_assignment_many(m, UNIT_SERVICE, properties);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -339,7 +339,7 @@ int allocate_scope(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = bus_append_unit_property_assignment_many(m, properties);
|
||||
r = bus_append_unit_property_assignment_many(m, UNIT_SCOPE, properties);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "spawn-polkit-agent.h"
|
||||
#include "strv.h"
|
||||
#include "terminal-util.h"
|
||||
#include "unit-def.h"
|
||||
#include "unit-name.h"
|
||||
#include "user-util.h"
|
||||
|
||||
@ -68,6 +69,8 @@ static enum {
|
||||
ARG_STDIO_DIRECT, /* Directly pass our stdin/stdout/stderr to the activated service, useful for usage in shell pipelines, requested by --pipe */
|
||||
ARG_STDIO_AUTO, /* If --pipe and --pty are used together we use --pty when invoked on a TTY, and --pipe otherwise */
|
||||
} arg_stdio = ARG_STDIO_NONE;
|
||||
static char **arg_path_property = NULL;
|
||||
static char **arg_socket_property = NULL;
|
||||
static char **arg_timer_property = NULL;
|
||||
static bool with_timer = false;
|
||||
static bool arg_quiet = false;
|
||||
@ -101,6 +104,10 @@ static void help(void) {
|
||||
" -P --pipe Pass STDIN/STDOUT/STDERR directly to service\n"
|
||||
" -q --quiet Suppress information messages during runtime\n"
|
||||
" -G --collect Unload unit after it ran, even when failed\n\n"
|
||||
"Path options:\n"
|
||||
" --path-property=NAME=VALUE Set path unit property\n\n"
|
||||
"Socket options:\n"
|
||||
" --socket-property=NAME=VALUE Set socket unit property\n\n"
|
||||
"Timer options:\n"
|
||||
" --on-active=SECONDS Run after SECONDS delay\n"
|
||||
" --on-boot=SECONDS Run SECONDS after machine was booted up\n"
|
||||
@ -152,6 +159,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_ON_UNIT_INACTIVE,
|
||||
ARG_ON_CALENDAR,
|
||||
ARG_TIMER_PROPERTY,
|
||||
ARG_PATH_PROPERTY,
|
||||
ARG_SOCKET_PROPERTY,
|
||||
ARG_NO_BLOCK,
|
||||
ARG_NO_ASK_PASSWORD,
|
||||
ARG_WAIT,
|
||||
@ -188,12 +197,15 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "on-unit-inactive", required_argument, NULL, ARG_ON_UNIT_INACTIVE },
|
||||
{ "on-calendar", required_argument, NULL, ARG_ON_CALENDAR },
|
||||
{ "timer-property", required_argument, NULL, ARG_TIMER_PROPERTY },
|
||||
{ "path-property", required_argument, NULL, ARG_PATH_PROPERTY },
|
||||
{ "socket-property", required_argument, NULL, ARG_SOCKET_PROPERTY },
|
||||
{ "no-block", no_argument, NULL, ARG_NO_BLOCK },
|
||||
{ "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
|
||||
{ "collect", no_argument, NULL, 'G' },
|
||||
{},
|
||||
};
|
||||
|
||||
bool with_trigger = false;
|
||||
int r, c;
|
||||
|
||||
assert(argc >= 0);
|
||||
@ -368,6 +380,20 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
!!startswith(optarg, "OnCalendar=");
|
||||
break;
|
||||
|
||||
case ARG_PATH_PROPERTY:
|
||||
|
||||
if (strv_extend(&arg_path_property, optarg) < 0)
|
||||
return log_oom();
|
||||
|
||||
break;
|
||||
|
||||
case ARG_SOCKET_PROPERTY:
|
||||
|
||||
if (strv_extend(&arg_socket_property, optarg) < 0)
|
||||
return log_oom();
|
||||
|
||||
break;
|
||||
|
||||
case ARG_NO_BLOCK:
|
||||
arg_no_block = true;
|
||||
break;
|
||||
@ -387,6 +413,13 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
assert_not_reached("Unhandled option");
|
||||
}
|
||||
|
||||
with_trigger = !!arg_path_property || !!arg_socket_property || with_timer;
|
||||
|
||||
/* currently, only single trigger (path, socket, timer) unit can be created simultaneously */
|
||||
if ((int) !!arg_path_property + (int) !!arg_socket_property + (int) with_timer > 1) {
|
||||
log_error("Only single trigger (path, socket, timer) unit can be created.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arg_stdio == ARG_STDIO_AUTO) {
|
||||
/* If we both --pty and --pipe are specified we'll automatically pick --pty if we are connected fully
|
||||
@ -397,7 +430,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_STDIO_DIRECT;
|
||||
}
|
||||
|
||||
if ((optind >= argc) && (!arg_unit || !with_timer)) {
|
||||
if ((optind >= argc) && (!arg_unit || !with_trigger)) {
|
||||
log_error("Command line to execute required.");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -417,7 +450,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arg_stdio != ARG_STDIO_NONE && (with_timer || arg_scope)) {
|
||||
if (arg_stdio != ARG_STDIO_NONE && (with_trigger || arg_scope)) {
|
||||
log_error("--pty/--pipe is not compatible in timer or --scope mode.");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -432,8 +465,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (arg_scope && with_timer) {
|
||||
log_error("Timer options are not supported in --scope mode.");
|
||||
if (arg_scope && with_trigger) {
|
||||
log_error("Path, socket or timer options are not supported in --scope mode.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -448,8 +481,8 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (with_timer) {
|
||||
log_error("--wait may not be combined with timer operations.");
|
||||
if (with_trigger) {
|
||||
log_error("--wait may not be combined with path, socket or timer operations.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -462,7 +495,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int transient_unit_set_properties(sd_bus_message *m, char **properties) {
|
||||
static int transient_unit_set_properties(sd_bus_message *m, UnitType t, char **properties) {
|
||||
int r;
|
||||
|
||||
r = sd_bus_message_append(m, "(sv)", "Description", "s", arg_description);
|
||||
@ -475,7 +508,7 @@ static int transient_unit_set_properties(sd_bus_message *m, char **properties) {
|
||||
return bus_log_create_error(r);
|
||||
}
|
||||
|
||||
r = bus_append_unit_property_assignment_many(m, properties);
|
||||
r = bus_append_unit_property_assignment_many(m, t, properties);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -521,7 +554,7 @@ static int transient_service_set_properties(sd_bus_message *m, char **argv, cons
|
||||
|
||||
assert(m);
|
||||
|
||||
r = transient_unit_set_properties(m, arg_property);
|
||||
r = transient_unit_set_properties(m, UNIT_SERVICE, arg_property);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -694,7 +727,7 @@ static int transient_scope_set_properties(sd_bus_message *m) {
|
||||
|
||||
assert(m);
|
||||
|
||||
r = transient_unit_set_properties(m, arg_property);
|
||||
r = transient_unit_set_properties(m, UNIT_SCOPE, arg_property);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -718,7 +751,7 @@ static int transient_timer_set_properties(sd_bus_message *m) {
|
||||
|
||||
assert(m);
|
||||
|
||||
r = transient_unit_set_properties(m, arg_timer_property);
|
||||
r = transient_unit_set_properties(m, UNIT_TIMER, arg_timer_property);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1282,14 +1315,15 @@ static int start_transient_scope(
|
||||
return log_error_errno(errno, "Failed to execute: %m");
|
||||
}
|
||||
|
||||
static int start_transient_timer(
|
||||
static int start_transient_trigger(
|
||||
sd_bus *bus,
|
||||
char **argv) {
|
||||
char **argv,
|
||||
const char *suffix) {
|
||||
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL, *reply = NULL;
|
||||
_cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *w = NULL;
|
||||
_cleanup_free_ char *timer = NULL, *service = NULL;
|
||||
_cleanup_free_ char *trigger = NULL, *service = NULL;
|
||||
const char *object = NULL;
|
||||
int r;
|
||||
|
||||
@ -1308,17 +1342,17 @@ static int start_transient_timer(
|
||||
if (!service)
|
||||
return log_oom();
|
||||
|
||||
r = unit_name_change_suffix(service, ".timer", &timer);
|
||||
r = unit_name_change_suffix(service, suffix, &trigger);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to change unit suffix: %m");
|
||||
break;
|
||||
|
||||
case UNIT_TIMER:
|
||||
timer = strdup(arg_unit);
|
||||
if (!timer)
|
||||
trigger = strdup(arg_unit);
|
||||
if (!trigger)
|
||||
return log_oom();
|
||||
|
||||
r = unit_name_change_suffix(timer, ".service", &service);
|
||||
r = unit_name_change_suffix(trigger, ".service", &service);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to change unit suffix: %m");
|
||||
break;
|
||||
@ -1328,7 +1362,7 @@ static int start_transient_timer(
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to mangle unit name: %m");
|
||||
|
||||
r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, ".timer", &timer);
|
||||
r = unit_name_mangle_with_suffix(arg_unit, UNIT_NAME_NOGLOB, suffix, &trigger);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to mangle unit name: %m");
|
||||
|
||||
@ -1339,7 +1373,7 @@ static int start_transient_timer(
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_name_change_suffix(service, ".timer", &timer);
|
||||
r = unit_name_change_suffix(service, suffix, &trigger);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to change unit suffix: %m");
|
||||
}
|
||||
@ -1359,7 +1393,7 @@ static int start_transient_timer(
|
||||
return bus_log_create_error(r);
|
||||
|
||||
/* Name and Mode */
|
||||
r = sd_bus_message_append(m, "ss", timer, "fail");
|
||||
r = sd_bus_message_append(m, "ss", trigger, "fail");
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
@ -1368,7 +1402,14 @@ static int start_transient_timer(
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = transient_timer_set_properties(m);
|
||||
if (streq(suffix, ".path"))
|
||||
r = transient_unit_set_properties(m, UNIT_PATH, arg_path_property);
|
||||
else if (streq(suffix, ".socket"))
|
||||
r = transient_unit_set_properties(m, UNIT_SOCKET, arg_socket_property);
|
||||
else if (streq(suffix, ".timer"))
|
||||
r = transient_timer_set_properties(m);
|
||||
else
|
||||
assert_not_reached("Invalid suffix");
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -1414,7 +1455,7 @@ static int start_transient_timer(
|
||||
|
||||
r = sd_bus_call(bus, m, 0, &error, &reply);
|
||||
if (r < 0) {
|
||||
log_error("Failed to start transient timer unit: %s", bus_error_message(&error, -r));
|
||||
log_error("Failed to start transient %s unit: %s", suffix + 1, bus_error_message(&error, -r));
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -1427,7 +1468,7 @@ static int start_transient_timer(
|
||||
return r;
|
||||
|
||||
if (!arg_quiet) {
|
||||
log_info("Running timer as unit: %s", timer);
|
||||
log_info("Running %s as unit: %s", suffix + 1, trigger);
|
||||
if (argv[0])
|
||||
log_info("Will run service as unit: %s", service);
|
||||
}
|
||||
@ -1488,14 +1529,20 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
if (arg_scope)
|
||||
r = start_transient_scope(bus, argv + optind);
|
||||
else if (arg_path_property)
|
||||
r = start_transient_trigger(bus, argv + optind, ".path");
|
||||
else if (arg_socket_property)
|
||||
r = start_transient_trigger(bus, argv + optind, ".socket");
|
||||
else if (with_timer)
|
||||
r = start_transient_timer(bus, argv + optind);
|
||||
r = start_transient_trigger(bus, argv + optind, ".timer");
|
||||
else
|
||||
r = start_transient_service(bus, argv + optind, &retval);
|
||||
|
||||
finish:
|
||||
strv_free(arg_environment);
|
||||
strv_free(arg_property);
|
||||
strv_free(arg_path_property);
|
||||
strv_free(arg_socket_property);
|
||||
strv_free(arg_timer_property);
|
||||
|
||||
return r < 0 ? EXIT_FAILURE : retval;
|
||||
|
@ -656,7 +656,7 @@ int ask_password_agent(
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (strv_length(l) <= 0) {
|
||||
if (strv_isempty(l)) {
|
||||
l = strv_free(l);
|
||||
log_debug("Invalid packet");
|
||||
continue;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -20,10 +20,10 @@
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include "sd-bus.h"
|
||||
|
||||
#include "output-mode.h"
|
||||
#include "install.h"
|
||||
#include "output-mode.h"
|
||||
#include "sd-bus.h"
|
||||
#include "unit-def.h"
|
||||
|
||||
typedef struct UnitInfo {
|
||||
const char *machine;
|
||||
@ -41,8 +41,8 @@ typedef struct UnitInfo {
|
||||
|
||||
int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u);
|
||||
|
||||
int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment);
|
||||
int bus_append_unit_property_assignment_many(sd_bus_message *m, char **l);
|
||||
int bus_append_unit_property_assignment(sd_bus_message *m, UnitType t, const char *assignment);
|
||||
int bus_append_unit_property_assignment_many(sd_bus_message *m, UnitType t, char **l);
|
||||
|
||||
typedef struct BusWaitForJobs BusWaitForJobs;
|
||||
|
||||
|
@ -950,6 +950,65 @@ int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, u
|
||||
return 0;
|
||||
}
|
||||
|
||||
int seccomp_parse_syscall_filter_internal(
|
||||
bool invert,
|
||||
const char *name,
|
||||
int errno_num,
|
||||
Hashmap *filter,
|
||||
bool whitelist,
|
||||
bool warn,
|
||||
const char *unit,
|
||||
const char *filename,
|
||||
unsigned line) {
|
||||
|
||||
int r;
|
||||
|
||||
assert(name);
|
||||
assert(filter);
|
||||
|
||||
if (name[0] == '@') {
|
||||
const SyscallFilterSet *set;
|
||||
const char *i;
|
||||
|
||||
set = syscall_filter_set_find(name);
|
||||
if (!set) {
|
||||
if (warn) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "Unknown system call group, ignoring: %s", name);
|
||||
return 0;
|
||||
} else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
NULSTR_FOREACH(i, set->value) {
|
||||
r = seccomp_parse_syscall_filter_internal(invert, i, errno_num, filter, whitelist, warn, unit, filename, line);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
int id;
|
||||
|
||||
id = seccomp_syscall_resolve_name(name);
|
||||
if (id == __NR_SCMP_ERROR) {
|
||||
if (warn) {
|
||||
log_syntax(unit, LOG_WARNING, filename, line, 0, "Failed to parse system call, ignoring: %s", name);
|
||||
return 0;
|
||||
} else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* If we previously wanted to forbid a syscall and now
|
||||
* we want to allow it, then remove it from the list. */
|
||||
if (!invert == whitelist) {
|
||||
r = hashmap_put(filter, INT_TO_PTR(id + 1), INT_TO_PTR(errno_num));
|
||||
if (r < 0)
|
||||
return warn ? log_oom() : -ENOMEM;
|
||||
} else
|
||||
(void) hashmap_remove(filter, INT_TO_PTR(id + 1));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int seccomp_restrict_namespaces(unsigned long retain) {
|
||||
uint32_t arch;
|
||||
int r;
|
||||
|
@ -81,6 +81,24 @@ int seccomp_add_syscall_filter_item(scmp_filter_ctx *ctx, const char *name, uint
|
||||
int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action);
|
||||
int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Hashmap* set, uint32_t action);
|
||||
|
||||
int seccomp_parse_syscall_filter_internal(
|
||||
bool invert, const char *name, int errno_num, Hashmap *filter, bool whitelist,
|
||||
bool warn, const char *unit, const char *filename, unsigned line);
|
||||
|
||||
static inline int seccomp_parse_syscall_filter_and_warn(
|
||||
bool invert, const char *name, int errno_num, Hashmap *filter, bool whitelist,
|
||||
const char *unit, const char *filename, unsigned line) {
|
||||
assert(unit);
|
||||
assert(filename);
|
||||
|
||||
return seccomp_parse_syscall_filter_internal(invert, name, errno_num, filter, whitelist, true, unit, filename, line);
|
||||
}
|
||||
|
||||
static inline int seccomp_parse_syscall_filter(
|
||||
bool invert, const char *name, int errno_num, Hashmap *filter, bool whitelist) {
|
||||
return seccomp_parse_syscall_filter_internal(invert, name, errno_num, filter, whitelist, false, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
int seccomp_restrict_archs(Set *archs);
|
||||
int seccomp_restrict_namespaces(unsigned long retain);
|
||||
int seccomp_protect_sysctl(void);
|
||||
|
@ -84,6 +84,7 @@
|
||||
#include "stat-util.h"
|
||||
#include "strv.h"
|
||||
#include "terminal-util.h"
|
||||
#include "unit-def.h"
|
||||
#include "unit-name.h"
|
||||
#include "user-util.h"
|
||||
#include "util.h"
|
||||
@ -5582,6 +5583,7 @@ static int set_property(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
|
||||
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
|
||||
_cleanup_free_ char *n = NULL;
|
||||
UnitType t;
|
||||
sd_bus *bus;
|
||||
int r;
|
||||
|
||||
@ -5605,6 +5607,12 @@ static int set_property(int argc, char *argv[], void *userdata) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to mangle unit name: %m");
|
||||
|
||||
t = unit_name_to_type(n);
|
||||
if (t < 0) {
|
||||
log_error("Invalid unit type: %s", n);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = sd_bus_message_append(m, "sb", n, arg_runtime);
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
@ -5613,7 +5621,7 @@ static int set_property(int argc, char *argv[], void *userdata) {
|
||||
if (r < 0)
|
||||
return bus_log_create_error(r);
|
||||
|
||||
r = bus_append_unit_property_assignment_many(m, strv_skip(argv, 2));
|
||||
r = bus_append_unit_property_assignment_many(m, t, strv_skip(argv, 2));
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user