summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am5
-rw-r--r--configure.ac9
-rw-r--r--src/basic/alloc-util.h22
-rw-r--r--src/basic/socket-util.c34
-rw-r--r--src/basic/socket-util.h2
-rw-r--r--src/core/load-fragment.c11
-rw-r--r--src/core/main.c1
-rw-r--r--src/libsystemd-network/sd-dhcp-client.c23
-rw-r--r--src/libsystemd-network/sd-dhcp-server.c9
-rw-r--r--src/libsystemd-network/sd-dhcp6-client.c13
-rw-r--r--src/libsystemd-network/sd-ndisc.c13
-rw-r--r--src/resolve/resolved-manager.c10
-rw-r--r--src/shared/bus-util.c31
-rw-r--r--src/shared/bus-util.h2
-rw-r--r--src/systemctl/systemctl.c5
-rw-r--r--src/test/test-execute.c5
-rw-r--r--test/test-execute/exec-spec-interpolation.service6
-rw-r--r--tmpfiles.d/systemd.conf.m419
18 files changed, 133 insertions, 87 deletions
diff --git a/Makefile.am b/Makefile.am
index 16a7a80e52..03341fcd28 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1476,8 +1476,6 @@ tests += \
test-af-list \
test-arphrd-list \
test-dns-domain \
- test-dns-packet \
- test-resolve-tables \
test-install-root \
test-rlimit-util \
test-signal-util
@@ -5214,7 +5212,8 @@ dist_zshcompletion_data += \
shell-completion/zsh/_systemd-resolve
tests += \
- test-dns-domain \
+ test-dns-packet \
+ test-resolve-tables \
test-dnssec
manual_tests += \
diff --git a/configure.ac b/configure.ac
index 614f0553b8..f51533c2b3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -495,6 +495,14 @@ if test "x$enable_apparmor" != "xno"; then
fi
AM_CONDITIONAL(HAVE_APPARMOR, [test "$have_apparmor" = "yes"])
+have_wheel_group=no
+AC_ARG_ENABLE(wheel-group, AS_HELP_STRING([--disable-wheel-group], [disable wheel group]))
+AS_IF([test "x$enable_wheel_group" != "xno"], [
+ AC_DEFINE(ENABLE_WHEEL_GROUP, 1, [Define if the ACL for wheel group should be enabled])
+ have_wheel_group=yes
+ M4_DEFINES="$M4_DEFINES -DENABLE_WHEEL_GROUP"
+])
+
AC_ARG_WITH(debug-shell,
AS_HELP_STRING([--with-debug-shell=PATH],
@@ -1631,6 +1639,7 @@ AC_MSG_RESULT([
Zsh completions dir: ${with_zshcompletiondir}
Extra start script: ${RC_LOCAL_SCRIPT_PATH_START}
Extra stop script: ${RC_LOCAL_SCRIPT_PATH_STOP}
+ Wheel group: ${have_wheel_group}
Debug shell: ${SUSHELL} @ ${DEBUGTTY}
TTY GID: ${TTY_GID}
Maximum System UID: ${SYSTEM_UID_MAX}
diff --git a/src/basic/alloc-util.h b/src/basic/alloc-util.h
index 679ba7f398..ceeee519b7 100644
--- a/src/basic/alloc-util.h
+++ b/src/basic/alloc-util.h
@@ -51,25 +51,29 @@ static inline void freep(void *p) {
#define _cleanup_free_ _cleanup_(freep)
-_malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t a, size_t b) {
- if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
+static inline bool size_multiply_overflow(size_t size, size_t need) {
+ return _unlikely_(need != 0 && size > (SIZE_MAX / need));
+}
+
+_malloc_ _alloc_(1, 2) static inline void *malloc_multiply(size_t size, size_t need) {
+ if (size_multiply_overflow(size, need))
return NULL;
- return malloc(a * b);
+ return malloc(size * need);
}
-_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t a, size_t b) {
- if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
+_alloc_(2, 3) static inline void *realloc_multiply(void *p, size_t size, size_t need) {
+ if (size_multiply_overflow(size, need))
return NULL;
- return realloc(p, a * b);
+ return realloc(p, size * need);
}
-_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t a, size_t b) {
- if (_unlikely_(b != 0 && a > ((size_t) -1) / b))
+_alloc_(2, 3) static inline void *memdup_multiply(const void *p, size_t size, size_t need) {
+ if (size_multiply_overflow(size, need))
return NULL;
- return memdup(p, a * b);
+ return memdup(p, size * need);
}
void* greedy_realloc(void **p, size_t *allocated, size_t need, size_t size);
diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c
index 49e5f5b125..58512686e3 100644
--- a/src/basic/socket-util.c
+++ b/src/basic/socket-util.c
@@ -936,3 +936,37 @@ int receive_one_fd(int transport_fd, int flags) {
return *(int*) CMSG_DATA(found);
}
+
+ssize_t next_datagram_size_fd(int fd) {
+ ssize_t l;
+ int k;
+
+ /* This is a bit like FIONREAD/SIOCINQ, however a bit more powerful. The difference being: recv(MSG_PEEK) will
+ * actually cause the next datagram in the queue to be validated regarding checksums, which FIONREAD dosn't
+ * do. This difference is actually of major importance as we need to be sure that the size returned here
+ * actually matches what we will read with recvmsg() next, as otherwise we might end up allocating a buffer of
+ * the wrong size. */
+
+ l = recv(fd, NULL, 0, MSG_PEEK|MSG_TRUNC);
+ if (l < 0) {
+ if (errno == EOPNOTSUPP)
+ goto fallback;
+
+ return -errno;
+ }
+ if (l == 0)
+ goto fallback;
+
+ return l;
+
+fallback:
+ k = 0;
+
+ /* Some sockets (AF_PACKET) do not support null-sized recv() with MSG_TRUNC set, let's fall back to FIONREAD
+ * for them. Checksums don't matter for raw sockets anyway, hence this should be fine. */
+
+ if (ioctl(fd, FIONREAD, &k) < 0)
+ return -errno;
+
+ return (ssize_t) k;
+}
diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h
index 92edc1dc22..d17a2f35f8 100644
--- a/src/basic/socket-util.h
+++ b/src/basic/socket-util.h
@@ -133,5 +133,7 @@ int send_one_fd_sa(int transport_fd,
#define send_one_fd(transport_fd, fd, flags) send_one_fd_sa(transport_fd, fd, NULL, 0, flags)
int receive_one_fd(int transport_fd, int flags);
+ssize_t next_datagram_size_fd(int fd);
+
#define CMSG_FOREACH(cmsg, mh) \
for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg)))
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index b31bf83f47..4a65d174b8 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -574,9 +574,7 @@ int config_parse_exec(
void *data,
void *userdata) {
- _cleanup_free_ char *cmd = NULL;
ExecCommand **e = data;
- Unit *u = userdata;
const char *p;
bool semicolon;
int r;
@@ -585,7 +583,6 @@ int config_parse_exec(
assert(lvalue);
assert(rvalue);
assert(e);
- assert(u);
e += ltype;
rvalue += strspn(rvalue, WHITESPACE);
@@ -596,13 +593,7 @@ int config_parse_exec(
return 0;
}
- r = unit_full_printf(u, rvalue, &cmd);
- if (r < 0) {
- log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue);
- return 0;
- }
-
- p = cmd;
+ p = rvalue;
do {
_cleanup_free_ char *path = NULL, *firstword = NULL;
bool separate_argv0 = false, ignore = false;
diff --git a/src/core/main.c b/src/core/main.c
index e2088574c0..c725a686f1 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -1313,7 +1313,6 @@ int main(int argc, char *argv[]) {
/* This is compatibility support for SysV, where
* calling init as a user is identical to telinit. */
- errno = -ENOENT;
execv(SYSTEMCTL_BINARY_PATH, argv);
log_error_errno(errno, "Failed to exec " SYSTEMCTL_BINARY_PATH ": %m");
return 1;
diff --git a/src/libsystemd-network/sd-dhcp-client.c b/src/libsystemd-network/sd-dhcp-client.c
index 5fd59f7dd3..62099dd3f4 100644
--- a/src/libsystemd-network/sd-dhcp-client.c
+++ b/src/libsystemd-network/sd-dhcp-client.c
@@ -1525,20 +1525,17 @@ static int client_receive_message_udp(sd_event_source *s, int fd,
uint32_t revents, void *userdata) {
sd_dhcp_client *client = userdata;
_cleanup_free_ DHCPMessage *message = NULL;
- int buflen = 0, len, r;
const struct ether_addr zero_mac = { { 0, 0, 0, 0, 0, 0 } };
const struct ether_addr *expected_chaddr = NULL;
uint8_t expected_hlen = 0;
+ ssize_t len, buflen;
assert(s);
assert(client);
- r = ioctl(fd, FIONREAD, &buflen);
- if (r < 0)
- return -errno;
- else if (buflen < 0)
- /* this can't be right */
- return -EIO;
+ buflen = next_datagram_size_fd(fd);
+ if (buflen < 0)
+ return buflen;
message = malloc0(buflen);
if (!message)
@@ -1616,17 +1613,15 @@ static int client_receive_message_raw(sd_event_source *s, int fd,
};
struct cmsghdr *cmsg;
bool checksum = true;
- int buflen = 0, len, r;
+ ssize_t buflen, len;
+ int r;
assert(s);
assert(client);
- r = ioctl(fd, FIONREAD, &buflen);
- if (r < 0)
- return -errno;
- else if (buflen < 0)
- /* this can't be right */
- return -EIO;
+ buflen = next_datagram_size_fd(fd);
+ if (buflen < 0)
+ return buflen;
packet = malloc0(buflen);
if (!packet)
diff --git a/src/libsystemd-network/sd-dhcp-server.c b/src/libsystemd-network/sd-dhcp-server.c
index ad3a37b722..54ff1a3f28 100644
--- a/src/libsystemd-network/sd-dhcp-server.c
+++ b/src/libsystemd-network/sd-dhcp-server.c
@@ -955,14 +955,13 @@ static int server_receive_message(sd_event_source *s, int fd,
.msg_controllen = sizeof(cmsgbuf),
};
struct cmsghdr *cmsg;
- int buflen = 0, len;
+ ssize_t buflen, len;
assert(server);
- if (ioctl(fd, FIONREAD, &buflen) < 0)
- return -errno;
- else if (buflen < 0)
- return -EIO;
+ buflen = next_datagram_size_fd(fd);
+ if (buflen < 0)
+ return buflen;
message = malloc(buflen);
if (!message)
diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c
index 5b6b9cbcac..7d56d4cc60 100644
--- a/src/libsystemd-network/sd-dhcp6-client.c
+++ b/src/libsystemd-network/sd-dhcp6-client.c
@@ -33,6 +33,7 @@
#include "in-addr-util.h"
#include "network-internal.h"
#include "random-util.h"
+#include "socket-util.h"
#include "string-table.h"
#include "util.h"
@@ -891,18 +892,16 @@ static int client_receive_message(sd_event_source *s, int fd, uint32_t revents,
sd_dhcp6_client *client = userdata;
DHCP6_CLIENT_DONT_DESTROY(client);
_cleanup_free_ DHCP6Message *message = NULL;
- int r, buflen, len;
+ ssize_t buflen, len;
+ int r = 0;
assert(s);
assert(client);
assert(client->event);
- r = ioctl(fd, FIONREAD, &buflen);
- if (r < 0)
- return -errno;
- else if (buflen < 0)
- /* This really should not happen */
- return -EIO;
+ buflen = next_datagram_size_fd(fd);
+ if (buflen < 0)
+ return buflen;
message = malloc(buflen);
if (!message)
diff --git a/src/libsystemd-network/sd-ndisc.c b/src/libsystemd-network/sd-ndisc.c
index 519d2aa36b..bae6a49fe6 100644
--- a/src/libsystemd-network/sd-ndisc.c
+++ b/src/libsystemd-network/sd-ndisc.c
@@ -491,19 +491,16 @@ static int ndisc_router_advertisment_recv(sd_event_source *s, int fd, uint32_t r
struct cmsghdr *cmsg;
struct in6_addr *gw;
unsigned lifetime;
- ssize_t len;
- int r, pref, stateful, buflen = 0;
+ ssize_t len, buflen;
+ int r, pref, stateful;
assert(s);
assert(nd);
assert(nd->event);
- r = ioctl(fd, FIONREAD, &buflen);
- if (r < 0)
- return -errno;
- else if (buflen < 0)
- /* This really should not happen */
- return -EIO;
+ buflen = next_datagram_size_fd(fd);
+ if (buflen < 0)
+ return buflen;
iov.iov_len = buflen;
diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c
index 44aafd0515..b3ff46b5da 100644
--- a/src/resolve/resolved-manager.c
+++ b/src/resolve/resolved-manager.c
@@ -617,18 +617,16 @@ int manager_recv(Manager *m, int fd, DnsProtocol protocol, DnsPacket **ret) {
struct msghdr mh = {};
struct cmsghdr *cmsg;
struct iovec iov;
- int ms = 0, r;
- ssize_t l;
+ ssize_t ms, l;
+ int r;
assert(m);
assert(fd >= 0);
assert(ret);
- r = ioctl(fd, FIONREAD, &ms);
- if (r < 0)
- return -errno;
+ ms = next_datagram_size_fd(fd);
if (ms < 0)
- return -EIO;
+ return ms;
r = dns_packet_new(&p, protocol, ms);
if (r < 0)
diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c
index 1fcf3f6a7f..c87eaf63d8 100644
--- a/src/shared/bus-util.c
+++ b/src/shared/bus-util.c
@@ -2028,8 +2028,8 @@ static const struct {
{ "start-limit", "start of the service was attempted too often" }
};
-static void log_job_error_with_service_result(const char* service, const char *result, const char** extra_args) {
- _cleanup_free_ char *service_shell_quoted = NULL, *_systemctl, *_journalctl;
+static void log_job_error_with_service_result(const char* service, const char *result, const char* const* extra_args) {
+ _cleanup_free_ char *service_shell_quoted = NULL;
const char *systemctl = "systemctl", *journalctl = "journalct";
assert(service);
@@ -2037,13 +2037,11 @@ static void log_job_error_with_service_result(const char* service, const char *r
service_shell_quoted = shell_maybe_quote(service);
if (extra_args && extra_args[1]) {
- assert(extra_args[0] == NULL);
+ _cleanup_free_ char *t;
- extra_args[0] = "systemctl";
- systemctl = _systemctl = strv_join((char**) extra_args, " ");
-
- extra_args[0] = "journalctl";
- journalctl = _journalctl = strv_join((char**) extra_args, " ");
+ t = strv_join((char**) extra_args, " ");
+ systemctl = strjoina("systemctl ", t ?: "<args>", NULL);
+ journalctl = strjoina("journalctl ", t ?: "<args>", NULL);
}
if (!isempty(result)) {
@@ -2058,29 +2056,30 @@ static void log_job_error_with_service_result(const char* service, const char *r
"See \"%s status %s\" and \"%s -xe\" for details.\n",
service,
explanations[i].explanation,
- systemctl ?: "systemctl <args>",
+ systemctl,
service_shell_quoted ?: "<service>",
- journalctl ?: "journalctl <args>");
+ journalctl);
goto finish;
}
}
- log_error("Job for %s failed. See \"%s status %s\" and \"%s -xe\" for details.\n",
+ log_error("Job for %s failed.\n"
+ "See \"%s status %s\" and \"%s -xe\" for details.\n",
service,
- systemctl ?: "systemctl <args>",
+ systemctl,
service_shell_quoted ?: "<service>",
- journalctl ?: "journalctl <args>");
+ journalctl);
finish:
/* For some results maybe additional explanation is required */
if (streq_ptr(result, "start-limit"))
log_info("To force a start use \"%1$s reset-failed %2$s\"\n"
"followed by \"%1$s start %2$s\" again.",
- systemctl ?: "systemctl <args>",
+ systemctl,
service_shell_quoted ?: "<service>");
}
-static int check_wait_response(BusWaitForJobs *d, bool quiet, const char** extra_args) {
+static int check_wait_response(BusWaitForJobs *d, bool quiet, const char* const* extra_args) {
int r = 0;
assert(d->result);
@@ -2131,7 +2130,7 @@ static int check_wait_response(BusWaitForJobs *d, bool quiet, const char** extra
return r;
}
-int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char** extra_args) {
+int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char* const* extra_args) {
int r = 0;
assert(d);
diff --git a/src/shared/bus-util.h b/src/shared/bus-util.h
index 26d338beec..fcda1b2c6c 100644
--- a/src/shared/bus-util.h
+++ b/src/shared/bus-util.h
@@ -180,7 +180,7 @@ typedef struct BusWaitForJobs BusWaitForJobs;
int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret);
void bus_wait_for_jobs_free(BusWaitForJobs *d);
int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path);
-int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char** extra_args);
+int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char* const* extra_args);
int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet);
DEFINE_TRIVIAL_CLEANUP_FUNC(BusWaitForJobs*, bus_wait_for_jobs_free);
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 44c13cf4d7..c75d12c136 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -2778,10 +2778,9 @@ static int start_unit(int argc, char *argv[], void *userdata) {
}
if (!arg_no_block) {
- int q, arg_count = 1;
- const char* extra_args[5] = {NULL};
+ int q, arg_count = 0;
+ const char* extra_args[4] = {};
- /* leave first empty for the actual command name*/
if (arg_scope != UNIT_FILE_SYSTEM)
extra_args[arg_count++] = "--user";
diff --git a/src/test/test-execute.c b/src/test/test-execute.c
index 92857cb5e2..d021be4671 100644
--- a/src/test/test-execute.c
+++ b/src/test/test-execute.c
@@ -263,6 +263,10 @@ static void test_exec_ioschedulingclass(Manager *m) {
test(m, "exec-ioschedulingclass-best-effort.service", 0, CLD_EXITED);
}
+static void test_exec_spec_interpolation(Manager *m) {
+ test(m, "exec-spec-interpolation.service", 0, CLD_EXITED);
+}
+
int main(int argc, char *argv[]) {
test_function_t tests[] = {
test_exec_workingdirectory,
@@ -284,6 +288,7 @@ int main(int argc, char *argv[]) {
test_exec_capabilityambientset,
test_exec_oomscoreadjust,
test_exec_ioschedulingclass,
+ test_exec_spec_interpolation,
NULL,
};
test_function_t *test = NULL;
diff --git a/test/test-execute/exec-spec-interpolation.service b/test/test-execute/exec-spec-interpolation.service
new file mode 100644
index 0000000000..3e62662aa9
--- /dev/null
+++ b/test/test-execute/exec-spec-interpolation.service
@@ -0,0 +1,6 @@
+[Unit]
+Description=https://github.com/systemd/systemd/issues/2637
+
+[Service]
+Type=oneshot
+ExecStart=/bin/sh -x -c "perl -e 'exit(!(qq{%%U} eq qq{\\x25U}))'"
diff --git a/tmpfiles.d/systemd.conf.m4 b/tmpfiles.d/systemd.conf.m4
index 0575408dbe..276bc6b1ba 100644
--- a/tmpfiles.d/systemd.conf.m4
+++ b/tmpfiles.d/systemd.conf.m4
@@ -26,21 +26,32 @@ d /run/log 0755 root root -
z /run/log/journal 2755 root systemd-journal - -
Z /run/log/journal/%m ~2750 root systemd-journal - -
-m4_ifdef(`HAVE_ACL',``
+m4_ifdef(`HAVE_ACL',
+m4_ifdef(`ENABLE_WHEEL_GROUP',``
a+ /run/log/journal/%m - - - - d:group:adm:r-x,d:group:wheel:r-x
A+ /run/log/journal/%m - - - - group:adm:r-x,group:wheel:r-x
-'')m4_dnl
+'',``
+a+ /run/log/journal/%m - - - - d:group:adm:r-x
+A+ /run/log/journal/%m - - - - group:adm:r-x
+''))m4_dnl
z /var/log/journal 2755 root systemd-journal - -
z /var/log/journal/%m 2755 root systemd-journal - -
z /var/log/journal/%m/system.journal 0640 root systemd-journal - -
-m4_ifdef(`HAVE_ACL',``
+m4_ifdef(`HAVE_ACL',
+m4_ifdef(`ENABLE_WHEEL_GROUP',``
a+ /var/log/journal - - - - d:group:adm:r-x,d:group:wheel:r-x
a+ /var/log/journal - - - - group:adm:r-x,group:wheel:r-x
a+ /var/log/journal/%m - - - - d:group:adm:r-x,d:group:wheel:r-x
a+ /var/log/journal/%m - - - - group:adm:r-x,group:wheel:r-x
a+ /var/log/journal/%m/system.journal - - - - group:adm:r--,group:wheel:r--
-'')m4_dnl
+'',``
+a+ /var/log/journal - - - - d:group:adm:r-x
+a+ /var/log/journal - - - - group:adm:r-x
+a+ /var/log/journal/%m - - - - d:group:adm:r-x
+a+ /var/log/journal/%m - - - - group:adm:r-x
+a+ /var/log/journal/%m/system.journal - - - - group:adm:r--
+''))m4_dnl
d /var/lib/systemd 0755 root root -
d /var/lib/systemd/coredump 0755 root root 3d