socket: allow configuration of socket/directory mode
authorLennart Poettering <lennart@poettering.net>
Fri, 12 Feb 2010 01:02:14 +0000 (02:02 +0100)
committerLennart Poettering <lennart@poettering.net>
Fri, 12 Feb 2010 01:02:14 +0000 (02:02 +0100)
fixme
load-fragment.c
socket-util.c
socket-util.h
socket.c
socket.h
test1/syslog.socket

diff --git a/fixme b/fixme
index 72cc9a5..6a771c7 100644 (file)
--- a/fixme
+++ b/fixme
@@ -72,3 +72,5 @@
    - distccd
 
 - teach dbus to talk to systemd when autospawning services
+
+- unix sockets chown()/chgrp()
index ab7f830..95e6cc3 100644 (file)
@@ -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"),
index 0f5140e..96567c6 100644 (file)
@@ -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)
index 0e73991..62a48ac 100644 (file)
@@ -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
index 6b1da01..b979e58 100644 (file)
--- 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 {
index 557512d..356341f 100644 (file)
--- 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;
index 1662990..524da50 100644 (file)
@@ -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