From b5a0699f0bb8b1d1ae55bb0d86f51dfe2783821b Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 12 Feb 2010 02:02:14 +0100 Subject: [PATCH] socket: allow configuration of socket/directory mode --- fixme | 2 ++ load-fragment.c | 12 +++++++----- socket-util.c | 38 ++++++++++++++++++++++++++++++++++++-- socket-util.h | 10 +++++++++- socket.c | 19 ++++++++++++++++--- socket.h | 2 ++ test1/syslog.socket | 6 +++--- 7 files changed, 75 insertions(+), 14 deletions(-) diff --git a/fixme b/fixme index 72cc9a55ca5..6a771c72f69 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 ab7f830a5df..95e6cc3f88a 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 0f5140ec5b9..96567c6d81e 100644 --- a/socket-util.c +++ b/socket-util.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #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 0e73991ef54..62a48ac35ac 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 6b1da016dd4..b979e58d390 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 557512d12b4..356341f2a6f 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 1662990da29..524da506137 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