summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fixme2
-rw-r--r--load-fragment.c12
-rw-r--r--socket-util.c38
-rw-r--r--socket-util.h10
-rw-r--r--socket.c19
-rw-r--r--socket.h2
-rw-r--r--test1/syslog.socket6
7 files changed, 75 insertions, 14 deletions
diff --git a/fixme b/fixme
index 72cc9a55ca..6a771c72f6 100644
--- a/fixme
+++ b/fixme
@@ -72,3 +72,5 @@
- distccd
- teach dbus to talk to systemd when autospawning services
+
+- unix sockets chown()/chgrp()
diff --git a/load-fragment.c b/load-fragment.c
index ab7f830a5d..95e6cc3f88 100644
--- a/load-fragment.c
+++ b/load-fragment.c
@@ -285,7 +285,7 @@ static int config_parse_oom_adjust(
return 0;
}
-static int config_parse_umask(
+static int config_parse_mode(
const char *filename,
unsigned line,
const char *section,
@@ -306,12 +306,12 @@ static int config_parse_umask(
errno = 0;
l = strtol(rvalue, &x, 8);
if (!x || *x || errno) {
- log_error("[%s:%u] Failed to parse umask value: %s", filename, line, rvalue);
+ log_error("[%s:%u] Failed to parse mode value: %s", filename, line, rvalue);
return errno ? -errno : -EINVAL;
}
- if (l < 0000 || l > 0777) {
- log_error("[%s:%u] umask value out of range: %s", filename, line, rvalue);
+ if (l < 0000 || l > 07777) {
+ log_error("[%s:%u] mode value out of range: %s", filename, line, rvalue);
return -ERANGE;
}
@@ -1045,7 +1045,7 @@ static int load_from_path(Unit *u, const char *path) {
{ "CPUSchedulingPriority", config_parse_cpu_sched_prio, &(context), section }, \
{ "CPUSchedulingResetOnFork", config_parse_bool, &(context).cpu_sched_reset_on_fork, section }, \
{ "CPUAffinity", config_parse_cpu_affinity, &(context), section }, \
- { "UMask", config_parse_umask, &(context).umask, section }, \
+ { "UMask", config_parse_mode, &(context).umask, section }, \
{ "Environment", config_parse_strv, &(context).environment, section }, \
{ "Output", config_parse_output, &(context).output, section }, \
{ "Input", config_parse_input, &(context).input, section }, \
@@ -1112,6 +1112,8 @@ static int load_from_path(Unit *u, const char *path) {
{ "ExecStartPost", config_parse_exec, u->socket.exec_command+SOCKET_EXEC_START_POST, "Socket" },
{ "ExecStopPre", config_parse_exec, u->socket.exec_command+SOCKET_EXEC_STOP_PRE, "Socket" },
{ "ExecStopPost", config_parse_exec, u->socket.exec_command+SOCKET_EXEC_STOP_POST, "Socket" },
+ { "DirectoryMode", config_parse_mode, &u->socket.directory_mode, "Socket" },
+ { "SocketMode", config_parse_mode, &u->socket.socket_mode, "Socket" },
EXEC_CONTEXT_CONFIG_ITEMS(u->socket.exec_context, "Socket"),
EXEC_CONTEXT_CONFIG_ITEMS(u->automount.exec_context, "Automount"),
diff --git a/socket-util.c b/socket-util.c
index 0f5140ec5b..96567c6d81 100644
--- a/socket-util.c
+++ b/socket-util.c
@@ -27,6 +27,8 @@
#include <arpa/inet.h>
#include <stdio.h>
#include <net/if.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#include "macro.h"
#include "util.h"
@@ -298,7 +300,15 @@ int socket_address_print(const SocketAddress *a, char **p) {
}
}
-int socket_address_listen(const SocketAddress *a, int backlog, SocketAddressBindIPv6Only only, const char *bind_to_device, int *ret) {
+int socket_address_listen(
+ const SocketAddress *a,
+ int backlog,
+ SocketAddressBindIPv6Only only,
+ const char *bind_to_device,
+ mode_t directory_mode,
+ mode_t socket_mode,
+ int *ret) {
+
int r, fd, one;
assert(a);
assert(ret);
@@ -324,7 +334,31 @@ int socket_address_listen(const SocketAddress *a, int backlog, SocketAddressBind
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0)
goto fail;
- if (bind(fd, &a->sockaddr.sa, a->size) < 0)
+ if (socket_address_family(a) == AF_UNIX && a->sockaddr.un.sun_path[0] != 0) {
+ mode_t old_mask;
+
+ /* Create parents */
+ mkdir_parents(a->sockaddr.un.sun_path, directory_mode);
+
+ /* Enforce the right access mode for the socket*/
+ old_mask = umask(~ socket_mode);
+
+ /* Include the original umask in our mask */
+ umask(~socket_mode | old_mask);
+
+ r = bind(fd, &a->sockaddr.sa, a->size);
+
+ if (r < 0 && errno == EADDRINUSE) {
+ /* Unlink and try again */
+ unlink(a->sockaddr.un.sun_path);
+ r = bind(fd, &a->sockaddr.sa, a->size);
+ }
+
+ umask(old_mask);
+ } else
+ r = bind(fd, &a->sockaddr.sa, a->size);
+
+ if (r < 0)
goto fail;
if (a->type == SOCK_STREAM)
diff --git a/socket-util.h b/socket-util.h
index 0e73991ef5..62a48ac35a 100644
--- a/socket-util.h
+++ b/socket-util.h
@@ -58,6 +58,14 @@ typedef enum SocketAddressBindIPv6Only {
int socket_address_parse(SocketAddress *a, const char *s);
int socket_address_print(const SocketAddress *a, char **p);
int socket_address_verify(const SocketAddress *a);
-int socket_address_listen(const SocketAddress *a, int backlog, SocketAddressBindIPv6Only only, const char *bind_to_device, int *ret);
+
+int socket_address_listen(
+ const SocketAddress *a,
+ int backlog,
+ SocketAddressBindIPv6Only only,
+ const char *bind_to_device,
+ mode_t directory_mode,
+ mode_t socket_mode,
+ int *ret);
#endif
diff --git a/socket.c b/socket.c
index 6b1da016dd..b979e58d39 100644
--- a/socket.c
+++ b/socket.c
@@ -105,6 +105,8 @@ static int socket_init(Unit *u) {
s->bind_ipv6_only = false;
s->backlog = SOMAXCONN;
s->timeout_usec = DEFAULT_TIMEOUT_USEC;
+ s->directory_mode = 0755;
+ s->socket_mode = 0666;
exec_context_init(&s->exec_context);
if ((r = unit_load_fragment_and_dropin(u)) <= 0) {
@@ -171,10 +173,14 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
fprintf(f,
"%sSocket State: %s\n"
"%sBindIPv6Only: %s\n"
- "%sBacklog: %u\n",
+ "%sBacklog: %u\n"
+ "%sSocketMode: %04o\n"
+ "%sDirectoryMode: %04o\n",
prefix, state_string_table[s->state],
prefix, yes_no(s->bind_ipv6_only),
- prefix, s->backlog);
+ prefix, s->backlog,
+ prefix, s->socket_mode,
+ prefix, s->directory_mode);
if (s->bind_to_device)
fprintf(f,
@@ -243,7 +249,14 @@ static int socket_open_fds(Socket *s) {
if (p->type == SOCKET_SOCKET) {
- if ((r = socket_address_listen(&p->address, s->backlog, s->bind_ipv6_only, s->bind_to_device, &p->fd)) < 0)
+ if ((r = socket_address_listen(
+ &p->address,
+ s->backlog,
+ s->bind_ipv6_only,
+ s->bind_to_device,
+ s->directory_mode,
+ s->socket_mode,
+ &p->fd)) < 0)
goto rollback;
} else {
diff --git a/socket.h b/socket.h
index 557512d12b..356341f2a6 100644
--- a/socket.h
+++ b/socket.h
@@ -93,6 +93,8 @@ struct Socket {
pid_t control_pid;
char *bind_to_device;
+ mode_t directory_mode;
+ mode_t socket_mode;
bool failure;
Watch timer_watch;
diff --git a/test1/syslog.socket b/test1/syslog.socket
index 1662990da2..524da50613 100644
--- a/test1/syslog.socket
+++ b/test1/syslog.socket
@@ -2,7 +2,7 @@
Description=Syslog Socket
[Socket]
-ListenDatagram=/tmp/systemd-syslog-socket
+ListenDatagram=/tmp/foobar/waldo/systemd-syslog-socket
ListenStream=eth0:3456
-ExecStartPre=/bin/rm -f /tmp/systemd-syslog-socket
-ExecStopPost=/bin/rm -f /tmp/systemd-syslog-socket
+DirectoryMode=0700
+SocketMode=0400