Compare commits

...

8 Commits

Author SHA1 Message Date
Zbigniew Jędrzejewski-Szmek a149d4a95e
Merge pull request #17455 from poettering/packet-auxdata
add Timestamping= to socket units and some other .socket unit tweaks
2020-10-27 20:20:57 +01:00
Lennart Poettering 02229dff2b units: turn on timestamping for journald sockets
To make things simple and robust when debugging journald, we'll leave
the SO_TIMESTAMP invocations in the C code in place, even if they are
now typically redundant, given that the sockets are already passed into
the process with SO_TIMESTAMP turned on now.
2020-10-27 14:13:03 +01:00
Lennart Poettering 95923d7e13 man: document the new Timestamping= option 2020-10-27 14:12:45 +01:00
Lennart Poettering 9b1915256c core: add Timestamping= option for socket units
This adds a way to control SO_TIMESTAMP/SO_TIMESTAMPNS socket options
for sockets PID 1 binds to.

This is useful in journald so that we get proper timestamps even for
ingress log messages that are submitted before journald is running.

We recently turned on packet info metadata from PID 1 for these sockets,
but the timestamping info was still missing. Let's correct that.
2020-10-27 14:12:39 +01:00
Lennart Poettering a2b06dbe15 conf-parser: add a flavour of DEFINE_CONFIG_PARSE_ENUM() that allows specifiying the precie from_string() function to call 2020-10-27 14:12:31 +01:00
Lennart Poettering 3b719003c3 journald: remove pointless conditionalization
Let's not have #ifdeffery both in the consumers and the providers of the
selinux glue code. Unless the code is particularly complex, let's do the
ifdeffery only in the provider of the selinux glue code, and let's keep
the consumers simple and just invoke it.
2020-10-27 14:12:26 +01:00
Lennart Poettering 2d6d4136cd socket-util: make socket_set_recvpktinfo control PACKET_AUXDATA sockopt on AF_PACKET
Just for the sake of completness.
2020-10-27 14:12:10 +01:00
Lennart Poettering c758bea722 man: add references to fifo(7) and mq_overview(7) man pages 2020-10-27 14:11:48 +01:00
15 changed files with 117 additions and 30 deletions

View File

@ -3968,6 +3968,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PassPacketInfo = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Timestamping = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RemoveOnStop = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) Listen = [...];
@ -4523,6 +4525,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<!--property PassPacketInfo is not documented!-->
<!--property Timestamping is not documented!-->
<!--property RemoveOnStop is not documented!-->
<!--property Listen is not documented!-->
@ -5065,6 +5069,8 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<variablelist class="dbus-property" generated="True" extra-ref="PassPacketInfo"/>
<variablelist class="dbus-property" generated="True" extra-ref="Timestamping"/>
<variablelist class="dbus-property" generated="True" extra-ref="RemoveOnStop"/>
<variablelist class="dbus-property" generated="True" extra-ref="Listen"/>

View File

@ -253,11 +253,10 @@
<varlistentry>
<term><varname>ListenFIFO=</varname></term>
<listitem><para>Specifies a file system FIFO to listen on.
This expects an absolute file system path as argument.
Behavior otherwise is very similar to the
<varname>ListenDatagram=</varname> directive
above.</para></listitem>
<listitem><para>Specifies a file system FIFO (see <citerefentry
project='man-pages'><refentrytitle>fifo</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
details) to listen on. This expects an absolute file system path as argument. Behavior otherwise is
very similar to the <varname>ListenDatagram=</varname> directive above.</para></listitem>
</varlistentry>
<varlistentry>
@ -285,12 +284,12 @@
<varlistentry>
<term><varname>ListenMessageQueue=</varname></term>
<listitem><para>Specifies a POSIX message queue name to listen
on. This expects a valid message queue name (i.e. beginning
with /). Behavior otherwise is very similar to the
<varname>ListenFIFO=</varname> directive above. On Linux
message queue descriptors are actually file descriptors and
can be inherited between processes.</para></listitem>
<listitem><para>Specifies a POSIX message queue name to listen on (see <citerefentry
project='man-pages'><refentrytitle>mq_overview</refentrytitle><manvolnum>7</manvolnum></citerefentry>
for details). This expects a valid message queue name (i.e. beginning with
<literal>/</literal>). Behavior otherwise is very similar to the <varname>ListenFIFO=</varname>
directive above. On Linux message queue descriptors are actually file descriptors and can be
inherited between processes.</para></listitem>
</varlistentry>
<varlistentry>
@ -698,10 +697,20 @@
<varlistentry>
<term><varname>PassPacketInfo=</varname></term>
<listitem><para>Takes a boolean value. This controls the <constant>IP_PKTINFO</constant>,
<constant>IPV6_RECVPKTINFO</constant> and <constant>NETLINK_PKTINFO</constant> socket options, which
enable reception of additional per-packet metadata as ancillary message, on
<constant>AF_INET</constant>, <constant>AF_INET6</constant> and <constant>AF_UNIX</constant> sockets.
Defaults to <option>false</option>.</para></listitem>
<constant>IPV6_RECVPKTINFO</constant>, <constant>NETLINK_PKTINFO</constant> or
<constant>PACKET_AUXDATA</constant> socket options, which enable reception of additional per-packet
metadata as ancillary message, on <constant>AF_INET</constant>, <constant>AF_INET6</constant>,
<constant>AF_UNIX</constant> and <constant>AF_PACKET</constant> sockets. Defaults to
<option>false</option>.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>Timestamping=</varname></term>
<listitem><para>Takes one of <literal>off</literal>, <literal>us</literal> (alias:
<literal>usec</literal>, <literal>µs</literal>) or <literal>ns</literal> (alias:
<literal>nsec</literal>). This controls the <constant>SO_TIMESTAMP</constant> or
<constant>SO_TIMESTAMPNS</constant> socket options, and enables whether ingress network traffic shall
carry timestamping metadata. Defaults to <option>off</option>.</para></listitem>
</varlistentry>
<varlistentry>

View File

@ -1240,6 +1240,9 @@ int socket_set_recvpktinfo(int fd, int af, bool b) {
case AF_NETLINK:
return setsockopt_int(fd, SOL_NETLINK, NETLINK_PKTINFO, b);
case AF_PACKET:
return setsockopt_int(fd, SOL_PACKET, PACKET_AUXDATA, b);
default:
return -EAFNOSUPPORT;
}

View File

@ -20,6 +20,7 @@
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);
static BUS_DEFINE_PROPERTY_GET(property_get_fdname, "s", Socket, socket_fdname);
static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_timestamping, socket_timestamping, SocketTimestamping);
static int property_get_listen(
sd_bus *bus,
@ -106,6 +107,7 @@ const sd_bus_vtable bus_socket_vtable[] = {
SD_BUS_PROPERTY("PassCredentials", "b", bus_property_get_bool, offsetof(Socket, pass_cred), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("PassSecurity", "b", bus_property_get_bool, offsetof(Socket, pass_sec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("PassPacketInfo", "b", bus_property_get_bool, offsetof(Socket, pass_pktinfo), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Timestamping", "s", property_get_timestamping, offsetof(Socket, timestamping), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RemoveOnStop", "b", bus_property_get_bool, offsetof(Socket, remove_on_stop), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Listen", "a(ss)", property_get_listen, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("Symlinks", "as", NULL, offsetof(Socket, symlinks), SD_BUS_VTABLE_PROPERTY_CONST),
@ -159,6 +161,7 @@ static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(fdname, fdname_is_valid);
static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(ifname, ifname_valid);
static BUS_DEFINE_SET_TRANSIENT_TO_STRING_ALLOC(ip_tos, "i", int32_t, int, "%" PRIi32, ip_tos_to_string_alloc);
static BUS_DEFINE_SET_TRANSIENT_TO_STRING(socket_protocol, "i", int32_t, int, "%" PRIi32, socket_protocol_to_string);
static BUS_DEFINE_SET_TRANSIENT_PARSE(socket_timestamping, SocketTimestamping, socket_timestamping_from_string_harder);
static int bus_socket_set_transient_property(
Socket *s,
@ -210,6 +213,9 @@ static int bus_socket_set_transient_property(
if (streq(name, "PassPacketInfo"))
return bus_set_transient_bool(u, name, &s->pass_pktinfo, message, flags, error);
if (streq(name, "Timestamping"))
return bus_set_transient_socket_timestamping(u, name, &s->timestamping, message, flags, error);
if (streq(name, "ReusePort"))
return bus_set_transient_bool(u, name, &s->reuse_port, message, flags, error);

View File

@ -419,6 +419,7 @@ Socket.Broadcast, config_parse_bool,
Socket.PassCredentials, config_parse_bool, 0, offsetof(Socket, pass_cred)
Socket.PassSecurity, config_parse_bool, 0, offsetof(Socket, pass_sec)
Socket.PassPacketInfo, config_parse_bool, 0, offsetof(Socket, pass_pktinfo)
Socket.Timestamping, config_parse_socket_timestamping, 0, offsetof(Socket, timestamping)
Socket.TCPCongestion, config_parse_string, 0, offsetof(Socket, tcp_congestion)
Socket.ReusePort, config_parse_bool, 0, offsetof(Socket, reuse_port)
Socket.MessageQueueMaxMessages, config_parse_long, 0, offsetof(Socket, mq_maxmsg)

View File

@ -140,6 +140,7 @@ DEFINE_CONFIG_PARSE_PTR(config_parse_cpu_shares, cg_cpu_shares_parse, uint64_t,
DEFINE_CONFIG_PARSE_PTR(config_parse_exec_mount_flags, mount_propagation_flags_from_string, unsigned long, "Failed to parse mount flag");
DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(config_parse_numa_policy, mpol, int, -1, "Invalid NUMA policy type");
DEFINE_CONFIG_PARSE_ENUM(config_parse_status_unit_format, status_unit_format, StatusUnitFormat, "Failed to parse status unit format");
DEFINE_CONFIG_PARSE_ENUM_FULL(config_parse_socket_timestamping, socket_timestamping_from_string_harder, SocketTimestamping, "Failed to parse timestamping precision");
int config_parse_unit_deps(
const char *unit,

View File

@ -136,6 +136,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_crash_chvt);
CONFIG_PARSER_PROTOTYPE(config_parse_timeout_abort);
CONFIG_PARSER_PROTOTYPE(config_parse_swap_priority);
CONFIG_PARSER_PROTOTYPE(config_parse_mount_images);
CONFIG_PARSER_PROTOTYPE(config_parse_socket_timestamping);
/* gperf prototypes */
const struct ConfigPerfItem* load_fragment_gperf_lookup(const char *key, GPERF_LEN_TYPE length);

View File

@ -629,6 +629,11 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
prefix, socket_fdname(s),
prefix, yes_no(s->selinux_context_from_net));
if (s->timestamping != SOCKET_TIMESTAMPING_OFF)
fprintf(f,
"%sTimestamping: %s\n",
prefix, socket_timestamping_to_string(s->timestamping));
if (s->control_pid > 0)
fprintf(f,
"%sControl PID: "PID_FMT"\n",
@ -1051,6 +1056,14 @@ static void socket_apply_socket_options(Socket *s, SocketPort *p, int fd) {
log_unit_warning_errno(UNIT(s), r, "Failed to enable packet info socket option: %m");
}
if (s->timestamping != SOCKET_TIMESTAMPING_OFF) {
r = setsockopt_int(fd, SOL_SOCKET,
s->timestamping == SOCKET_TIMESTAMPING_NS ? SO_TIMESTAMPNS : SO_TIMESTAMP,
true);
if (r < 0)
log_unit_warning_errno(UNIT(s), r, "Failed to enable timestamping socket option, ignoring: %m");
}
if (s->priority >= 0) {
r = setsockopt_int(fd, SOL_SOCKET, SO_PRIORITY, s->priority);
if (r < 0)
@ -3409,6 +3422,39 @@ static const char* const socket_result_table[_SOCKET_RESULT_MAX] = {
DEFINE_STRING_TABLE_LOOKUP(socket_result, SocketResult);
static const char* const socket_timestamping_table[_SOCKET_TIMESTAMPING_MAX] = {
[SOCKET_TIMESTAMPING_OFF] = "off",
[SOCKET_TIMESTAMPING_US] = "us",
[SOCKET_TIMESTAMPING_NS] = "ns",
};
DEFINE_STRING_TABLE_LOOKUP(socket_timestamping, SocketTimestamping);
SocketTimestamping socket_timestamping_from_string_harder(const char *p) {
SocketTimestamping t;
int r;
if (!p)
return _SOCKET_TIMESTAMPING_INVALID;
t = socket_timestamping_from_string(p);
if (t >= 0)
return t;
/* Let's alternatively support the various other aliases parse_time() accepts for ns and µs here,
* too. */
if (streq(p, "nsec"))
return SOCKET_TIMESTAMPING_NS;
if (STR_IN_SET(p, "usec", "µs"))
return SOCKET_TIMESTAMPING_US;
r = parse_boolean(p);
if (r < 0)
return _SOCKET_TIMESTAMPING_INVALID;
return r ? SOCKET_TIMESTAMPING_NS : SOCKET_TIMESTAMPING_OFF; /* If boolean yes, default to ns accuracy */
}
const UnitVTable socket_vtable = {
.object_size = sizeof(Socket),
.exec_context_offset = offsetof(Socket, exec_context),

View File

@ -58,6 +58,14 @@ typedef struct SocketPort {
LIST_FIELDS(struct SocketPort, port);
} SocketPort;
typedef enum SocketTimestamping {
SOCKET_TIMESTAMPING_OFF,
SOCKET_TIMESTAMPING_US, /* SO_TIMESTAMP */
SOCKET_TIMESTAMPING_NS, /* SO_TIMESTAMPNS */
_SOCKET_TIMESTAMPING_MAX,
_SOCKET_TIMESTAMPING_INVALID = -1,
} SocketTimestamping;
struct Socket {
Unit meta;
@ -123,6 +131,7 @@ struct Socket {
bool pass_cred;
bool pass_sec;
bool pass_pktinfo;
SocketTimestamping timestamping;
/* Only for INET6 sockets: issue IPV6_V6ONLY sockopt */
SocketAddressBindIPv6Only bind_ipv6_only;
@ -182,4 +191,8 @@ 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_;
const char* socket_timestamping_to_string(SocketTimestamping p) _const_;
SocketTimestamping socket_timestamping_from_string(const char *p) _pure_;
SocketTimestamping socket_timestamping_from_string_harder(const char *p) _pure_;
DEFINE_CAST(SOCKET, Socket);

View File

@ -483,13 +483,11 @@ int server_open_native_socket(Server *s, const char *native_socket) {
if (r < 0)
return log_error_errno(r, "SO_PASSCRED failed: %m");
#if HAVE_SELINUX
if (mac_selinux_use()) {
r = setsockopt_int(s->native_fd, SOL_SOCKET, SO_PASSSEC, true);
if (r < 0)
log_warning_errno(r, "SO_PASSSEC failed: %m");
}
#endif
r = setsockopt_int(s->native_fd, SOL_SOCKET, SO_TIMESTAMP, true);
if (r < 0)

View File

@ -70,9 +70,8 @@ static void forward_syslog_iovec(
msghdr.msg_controllen = cmsg->cmsg_len;
}
/* Forward the syslog message we received via /dev/log to
* /run/systemd/syslog. Unfortunately we currently can't set
* the SO_TIMESTAMP auxiliary data, and hence we don't. */
/* Forward the syslog message we received via /dev/log to /run/systemd/syslog. Unfortunately we
* currently can't set the SO_TIMESTAMP auxiliary data, and hence we don't. */
if (sendmsg(s->syslog_fd, &msghdr, MSG_NOSIGNAL) >= 0)
return;
@ -484,13 +483,11 @@ int server_open_syslog_socket(Server *s, const char *syslog_socket) {
if (r < 0)
return log_error_errno(r, "SO_PASSCRED failed: %m");
#if HAVE_SELINUX
if (mac_selinux_use()) {
r = setsockopt_int(s->syslog_fd, SOL_SOCKET, SO_PASSSEC, true);
if (r < 0)
log_warning_errno(r, "SO_PASSSEC failed: %m");
}
#endif
r = setsockopt_int(s->syslog_fd, SOL_SOCKET, SO_TIMESTAMP, true);
if (r < 0)

View File

@ -2037,7 +2037,8 @@ static int bus_append_socket_property(sd_bus_message *m, const char *field, cons
"BindIPv6Only",
"FileDescriptorName",
"SocketUser",
"SocketGroup"))
"SocketGroup",
"Timestamping"))
return bus_append_string(m, field, eq);
if (streq(field, "Symlinks"))

View File

@ -193,7 +193,7 @@ typedef enum Disabled {
return 0; \
}
#define DEFINE_CONFIG_PARSE_ENUM(function, name, type, msg) \
#define DEFINE_CONFIG_PARSE_ENUM_FULL(function, from_string, type, msg) \
CONFIG_PARSER_PROTOTYPE(function) { \
type *i = data, x; \
\
@ -202,7 +202,7 @@ typedef enum Disabled {
assert(rvalue); \
assert(data); \
\
x = name##_from_string(rvalue); \
x = from_string(rvalue); \
if (x < 0) { \
log_syntax(unit, LOG_WARNING, filename, line, 0, \
msg ", ignoring: %s", rvalue); \
@ -213,6 +213,9 @@ typedef enum Disabled {
return 0; \
}
#define DEFINE_CONFIG_PARSE_ENUM(function, name, type, msg) \
DEFINE_CONFIG_PARSE_ENUM_FULL(function, name##_from_string, type, msg)
#define DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(function, name, type, default_value, msg) \
CONFIG_PARSER_PROTOTYPE(function) { \
type *i = data, x; \

View File

@ -19,12 +19,13 @@ Before=sockets.target
IgnoreOnIsolate=yes
[Socket]
Service=systemd-journald.service
ListenDatagram=/run/systemd/journal/dev-log
Symlinks=/dev/log
SocketMode=0666
PassCredentials=yes
PassSecurity=yes
Service=systemd-journald.service
SocketMode=0666
Symlinks=/dev/log
Timestamping=us
# Increase both the send and receive buffer, so that things don't
# block early. Note that journald internally uses the this socket both

View File

@ -19,10 +19,11 @@ Before=sockets.target
IgnoreOnIsolate=yes
[Socket]
ListenStream=/run/systemd/journal/stdout
ListenDatagram=/run/systemd/journal/socket
SocketMode=0666
ListenStream=/run/systemd/journal/stdout
PassCredentials=yes
PassSecurity=yes
ReceiveBuffer=8M
Service=systemd-journald.service
SocketMode=0666
Timestamping=us