[systemd-commits] 4 commits - configure.ac fixme man/systemd.socket.xml src/automount.c src/load-fragment.c src/main.c src/socket.c src/socket.h src/socket-util.c src/socket-util.h src/util.c src/util.h

Lennart Poettering lennart at kemper.freedesktop.org
Tue Aug 3 14:47:16 PDT 2010


 configure.ac           |   21 +++-
 fixme                  |    4 
 man/systemd.socket.xml |   12 ++
 src/automount.c        |    2 
 src/load-fragment.c    |    1 
 src/main.c             |    5 +
 src/socket-util.c      |   13 +-
 src/socket-util.h      |    3 
 src/socket.c           |  108 +++++----------------
 src/socket.h           |    1 
 src/util.c             |  244 ++++++++++++++++++++++++++++++++++++++++++++++++-
 src/util.h             |   10 ++
 12 files changed, 323 insertions(+), 101 deletions(-)

New commits:
commit 56cf987fe74270bde4e16c7ec9e0414a9030723b
Author: Daniel J Walsh <dwalsh at redhat.com>
Date:   Wed Jul 28 09:39:54 2010 -0400

    Systemd is causing mislabeled devices to be created and then attempting to read them.
    
    -----BEGIN PGP SIGNED MESSAGE-----
    Hash: SHA1
    
    On 07/28/2010 05:57 AM, Kay Sievers wrote:
    > On Wed, Jul 28, 2010 at 11:43, Lennart Poettering
    > <lennart at poettering.net> wrote:
    >> On Mon, 26.07.10 16:42, Daniel J Walsh (dwalsh at redhat.com) wrote:
    >>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file
    >>> type=1400 audit(1280174589.476:7): avc:  denied  { read } for  pid=1
    >>> comm="systemd" name="autofs" dev=devtmpfs ino=9482
    >>> scontext=system_u:system_r:init_t:s0
    >>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file
    >>> type=1400 audit(1280174589.476:8): avc:  denied  { read } for  pid=1
    >>> comm="systemd" name="autofs" dev=devtmpfs ino=9482
    >>> scontext=system_u:system_r:init_t:s0
    >>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file
    >>>
    >>> Lennart, we talked about this earlier.  I think this is caused by the
    >>> modprobe calls to create /dev/autofs.  Since udev is not created at the
    >>> point that init loads the kernel modules, the devices get created with
    >>> the wrong label.  Once udev starts the labels get fixed.
    >>>
    >>> I can allow init_t to read device_t chr_files.
    >>
    >> Hmm, I think a cleaner fix would be to make systemd relabel this device
    >> properly before accessing it? Given that this is only one device this
    >> should not be a problem for us to maintain, I think? How would the
    >> fixing of the label work? Would we have to spawn restorecon for this, or
    >> can we actually do this in C without too much work?
    >
    > I guess we can just do what udev is doing, and call setfilecon(), with
    > a context of an earlier matchpathcon().
    >
    > Kay
    > _______________________________________________
    > systemd-devel mailing list
    > systemd-devel at lists.freedesktop.org
    > http://lists.freedesktop.org/mailman/listinfo/systemd-devel
    
    Here is the updated patch with a fix for the labeling of /dev/autofs
    -----BEGIN PGP SIGNATURE-----
    Version: GnuPG v2.0.14 (GNU/Linux)
    Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/
    
    iEYEARECAAYFAkxQMyoACgkQrlYvE4MpobNviACfWgxsjW2xzz1qznFex8RVAQHf
    gIEAmwRmRcLvGqYtwQaZ3WKIg8wmrwNk
    =pC2e

diff --git a/configure.ac b/configure.ac
index 14622e4..65c8af0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -105,15 +105,26 @@ PKG_CHECK_MODULES(DBUS, [ dbus-1 >= 1.3.2 ])
 AC_SUBST(DBUS_CFLAGS)
 AC_SUBST(DBUS_LIBS)
 
-PKG_CHECK_MODULES(SELINUX, [ libselinux ])
-AC_SUBST(SELINUX_CFLAGS)
-AC_SUBST(SELINUX_LIBS)
-AC_SEARCH_LIBS([is_selinux_enabled], [selinux], [], [AC_MSG_ERROR([*** libselinux library not found])])
-
 PKG_CHECK_MODULES(DBUSGLIB, [ dbus-glib-1 ])
 AC_SUBST(DBUSGLIB_CFLAGS)
 AC_SUBST(DBUSGLIB_LIBS)
 
+have_selinux=no
+AC_ARG_ENABLE(selinux, AS_HELP_STRING([--disable-selinux], [Disable optional SELINUX support]))
+if test "x$enable_selinux" != "xno"; then
+	# not using PKG_CHECK_MODULES as for some reason libselinux didn't
+	# install any pkg-config modules here
+	AC_SEARCH_LIBS([getcon], [selinux],
+                [AC_DEFINE(HAVE_SELINUX, 1, [Define if SELINUX is available]) have_selinux=yes],
+		have_selinux=no)
+        AC_SUBST(SELINUX_CFLAGS)
+        AC_SUBST(SELINUX_LIBS)
+        if test "x$have_selinux" = xno -a "x$enable_selinux" = xyes; then
+                AC_MSG_ERROR([*** selinux support requested but libraries not found])
+        fi
+fi
+AM_CONDITIONAL(HAVE_SELINUX, [test "$have_selinux" = "yes"])
+
 AC_ARG_ENABLE([tcpwrap],
         AS_HELP_STRING([--disable-tcpwrap],[Disable optional TCP wrappers support]),
                 [case "${enableval}" in
diff --git a/src/automount.c b/src/automount.c
index 213b178..3a69cf9 100644
--- a/src/automount.c
+++ b/src/automount.c
@@ -304,6 +304,8 @@ static int open_dev_autofs(Manager *m) {
         if (m->dev_autofs_fd >= 0)
                 return m->dev_autofs_fd;
 
+	label_fix("/dev/autofs");
+
         if ((m->dev_autofs_fd = open("/dev/autofs", O_CLOEXEC|O_RDONLY)) < 0) {
                 log_error("Failed to open /dev/autofs: %s", strerror(errno));
                 return -errno;
diff --git a/src/main.c b/src/main.c
index e67d222..36dea9b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -836,6 +836,9 @@ int main(int argc, char *argv[]) {
                 return 1;
         }
 
+        if (label_init() < 0)
+                goto finish;
+
         log_show_color(isatty(STDERR_FILENO) > 0);
         log_show_location(false);
         log_set_max_level(LOG_INFO);
@@ -1113,5 +1116,7 @@ finish:
         if (getpid() == 1)
                 freeze();
 
+        label_finish();
+
         return retval;
 }
diff --git a/src/socket-util.c b/src/socket-util.c
index 3a00fcf..2af8563 100644
--- a/src/socket-util.c
+++ b/src/socket-util.c
@@ -29,7 +29,6 @@
 #include <net/if.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <selinux/selinux.h>
 
 #include "macro.h"
 #include "util.h"
@@ -306,7 +305,7 @@ int socket_address_listen(
                 bool free_bind,
                 mode_t directory_mode,
                 mode_t socket_mode,
-                security_context_t scon,
+                const char *label,
                 int *ret) {
 
         int r, fd, one;
@@ -316,16 +315,14 @@ int socket_address_listen(
         if ((r = socket_address_verify(a)) < 0)
                 return r;
 
-        if (setsockcreatecon(scon) < 0) {
-                log_error("Failed to set SELinux context (%s) on socket: %m", scon);
-                if (security_getenforce() == 1)
-                        return -errno;
-        }
+        r = label_socket_set(label);
+        if (r < 0)
+                return r;
 
         fd = socket(socket_address_family(a), a->type | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
         r = fd < 0 ? -errno : 0;
 
-        setsockcreatecon(NULL);
+        label_socket_clear();
 
         if (r < 0)
                 return r;
diff --git a/src/socket-util.h b/src/socket-util.h
index 841570f..86c9e47 100644
--- a/src/socket-util.h
+++ b/src/socket-util.h
@@ -26,7 +26,6 @@
 #include <netinet/in.h>
 #include <sys/un.h>
 #include <net/if.h>
-#include <selinux/selinux.h>
 
 #include "macro.h"
 #include "util.h"
@@ -72,7 +71,7 @@ int socket_address_listen(
                 bool free_bind,
                 mode_t directory_mode,
                 mode_t socket_mode,
-                security_context_t scon,
+                const char *label,
                 int *ret);
 
 bool socket_address_is(const SocketAddress *a, const char *s, int type);
diff --git a/src/socket.c b/src/socket.c
index 2da3215..2a5270f 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -27,7 +27,6 @@
 #include <sys/epoll.h>
 #include <signal.h>
 #include <arpa/inet.h>
-#include <selinux/selinux.h>
 
 #include "unit.h"
 #include "socket.h"
@@ -653,89 +652,25 @@ static void socket_apply_fifo_options(Socket *s, int fd) {
                         log_warning("F_SETPIPE_SZ: %m");
 }
 
-static int selinux_getconfromexe(
-                const char *exe,
-                security_context_t *newcon) {
-
-        security_context_t mycon = NULL, fcon = NULL;
-        security_class_t sclass;
-        int r = 0;
-
-        r = getcon(&mycon);
-        if (r < 0)
-                goto fail;
-
-        r = getfilecon(exe, &fcon);
-        if (r < 0)
-                goto fail;
-
-        sclass = string_to_security_class("process");
-        r = security_compute_create(mycon, fcon, sclass, newcon);
-
-fail:
-        if (r < 0)
-                r = -errno;
-
-        freecon(mycon);
-        freecon(fcon);
-        return r;
-}
-
-static int selinux_getfileconfrompath(
-                const security_context_t scon,
-                const char *path,
-                const char *class,
-                security_context_t *fcon) {
-
-        security_context_t dir_con = NULL;
-        security_class_t sclass;
-        int r = 0;
-
-        r = getfilecon(path, &dir_con);
-        if (r >= 0) {
-                r = -1;
-                if ((sclass = string_to_security_class(class)) != 0)
-                        r = security_compute_create(scon, dir_con, sclass, fcon);
-        }
-        if (r < 0)
-                r = -errno;
-
-        freecon(dir_con);
-        return r;
-}
 
 static int fifo_address_create(
                 const char *path,
                 mode_t directory_mode,
                 mode_t socket_mode,
-                security_context_t scon,
+                const char *label,
                 int *_fd) {
 
         int fd = -1, r = 0;
         struct stat st;
         mode_t old_mask;
-        security_context_t filecon = NULL;
 
         assert(path);
         assert(_fd);
 
         mkdir_parents(path, directory_mode);
 
-        if (scon) {
-                if (scon && ((r = selinux_getfileconfrompath(scon, path, "fifo_file", &filecon)) == 0)) {
-                        r = setfscreatecon(filecon);
-
-                        if (r < 0) {
-                                log_error("Failed to set SELinux file context (%s) on %s: %m", scon, path);
-                                r = -errno;
-                        }
-
-                        freecon(filecon);
-                }
-
-                if (r < 0  && security_getenforce() == 1)
-                        goto fail;
-        }
+        if ((r = label_fifofile_set(label, path)) < 0)
+                goto fail;
 
         /* Enforce the right access mode for the fifo */
         old_mask = umask(~ socket_mode);
@@ -756,7 +691,7 @@ static int fifo_address_create(
                 goto fail;
         }
 
-        setfscreatecon(NULL);
+        label_file_clear();
 
         if (fstat(fd, &st) < 0) {
                 r = -errno;
@@ -776,7 +711,8 @@ static int fifo_address_create(
         return 0;
 
 fail:
-        setfscreatecon(NULL);
+        label_file_clear();
+
         if (fd >= 0)
                 close_nointr_nofail(fd);
 
@@ -786,20 +722,16 @@ fail:
 static int socket_open_fds(Socket *s) {
         SocketPort *p;
         int r;
-        security_context_t scon = NULL;
+        char *label = NULL;
 
         assert(s);
 
         if ((r = socket_instantiate_service(s)) < 0)
                 return r;
 
-        if (selinux_getconfromexe(s->service->exec_command[SERVICE_EXEC_START]->path, &scon) < 0) {
-                log_error("Failed to get SELinux exec context for %s \n", s->service->exec_command[SERVICE_EXEC_START]->path);
-                if (security_getenforce() == 1)
-                        return -errno;
-        }
+        if ((r = label_get_socket_label_from_exe(s->service->exec_command[SERVICE_EXEC_START]->path, &label)) < 0)
+                return r;
 
-        log_debug("SELinux Socket context for %s set to %s\n", s->service->exec_command[SERVICE_EXEC_START]->path, scon);
         LIST_FOREACH(port, p, s->ports) {
 
                 if (p->fd >= 0)
@@ -815,7 +747,7 @@ static int socket_open_fds(Socket *s) {
                                              s->free_bind,
                                              s->directory_mode,
                                              s->socket_mode,
-                                             scon,
+                                             label,
                                              &p->fd)) < 0)
                                 goto rollback;
 
@@ -827,7 +759,7 @@ static int socket_open_fds(Socket *s) {
                                              p->path,
                                              s->directory_mode,
                                              s->socket_mode,
-                                             scon,
+                                             label,
                                              &p->fd)) < 0)
                                 goto rollback;
 
@@ -837,12 +769,12 @@ static int socket_open_fds(Socket *s) {
                         assert_not_reached("Unknown port type");
         }
 
-        freecon(scon);
+        label_free(label);
         return 0;
 
 rollback:
         socket_close_fds(s);
-        freecon(scon);
+        label_free(label);
         return r;
 }
 
diff --git a/src/util.c b/src/util.c
index da8a6c3..2279efa 100644
--- a/src/util.c
+++ b/src/util.c
@@ -56,6 +56,244 @@
 #include "log.h"
 #include "strv.h"
 
+#if HAVE_SELINUX
+#include <selinux/selinux.h>
+#include <selinux/label.h>
+
+static struct selabel_handle *label_hnd = NULL;
+
+static inline int use_selinux(void) {
+        static int use_selinux_ind = -1;
+
+        if (use_selinux_ind == -1)
+                use_selinux_ind = (is_selinux_enabled() == 1);
+
+        return use_selinux_ind;
+}
+
+static int label_get_file_label_from_path(
+                const char *label,
+                const char *path,
+                const char *class,
+                security_context_t *fcon) {
+
+        security_context_t dir_con = NULL;
+        security_class_t sclass;
+        int r = 0;
+
+        r = getfilecon(path, &dir_con);
+        if (r >= 0) {
+                r = -1;
+                if ((sclass = string_to_security_class(class)) != 0)
+                        r = security_compute_create((security_context_t) label, dir_con, sclass, fcon);
+        }
+        if (r < 0)
+                r = -errno;
+
+        freecon(dir_con);
+        return r;
+}
+
+#endif
+
+int label_init(void) {
+        int r = 0;
+
+#if HAVE_SELINUX
+        if (use_selinux()) {
+                label_hnd = selabel_open(SELABEL_CTX_FILE, NULL, 0);
+                if (!label_hnd) {
+                        log_full(security_getenforce() == 1 ? LOG_ERR : LOG_DEBUG, "Failed to initialize SELinux context: %m");
+                        r = (security_getenforce() == 1) ? -errno : 0;
+                }
+        }
+#endif
+
+        return r;
+}
+
+int label_fix(const char *path) {
+        int r = 0;
+#if HAVE_SELINUX
+        struct stat st;
+        security_context_t fcon;
+        if (use_selinux()) {
+                r = lstat(path, &st);
+
+                if (r == 0) {
+                        r = selabel_lookup_raw(label_hnd, &fcon, path, st.st_mode);
+
+                        if (r == 0) {
+                                r = setfilecon(path, fcon);
+                                freecon(fcon);
+                        }
+                }
+                if (r < 0) {
+                        log_error("Unable to fix label of %s: %m", path);
+                        r = (security_getenforce() == 1) ? -errno : 0;
+                }
+        }
+#endif
+        return r;
+}
+
+void label_finish(void) {
+
+#if HAVE_SELINUX
+        if (use_selinux())
+                selabel_close(label_hnd);
+#endif
+
+}
+
+int label_get_socket_label_from_exe(
+        const char *exe,
+        char **label) {
+        int r = 0;
+
+#if HAVE_SELINUX
+        security_context_t mycon = NULL, fcon = NULL;
+        security_class_t sclass;
+
+        r = getcon(&mycon);
+        if (r < 0)
+                goto fail;
+
+        r = getfilecon(exe, &fcon);
+        if (r < 0)
+                goto fail;
+
+        sclass = string_to_security_class("process");
+        r = security_compute_create(mycon, fcon, sclass, (security_context_t *) label);
+        if (r == 0)
+                log_debug("SELinux Socket context for %s will be set to %s", exe, *label);
+
+fail:
+        if (r< 0 && security_getenforce() == 1)
+                r = -errno;
+
+        freecon(mycon);
+        freecon(fcon);
+#endif
+
+        return r;
+}
+
+int label_fifofile_set(const char *label, const char *path) {
+        int r = 0;
+
+#if HAVE_SELINUX
+        security_context_t filecon = NULL;
+        if (use_selinux() && label) {
+                if (((r = label_get_file_label_from_path(label, path, "fifo_file", &filecon)) == 0)) {
+                        if ((r = setfscreatecon(filecon)) < 0) {
+                                log_error("Failed to set SELinux file context (%s) on %s: %m", label, path);
+                                r = -errno;
+                        }
+
+                        freecon(filecon);
+                }
+
+                if (r < 0  && security_getenforce() == 0)
+                        r = 0;
+        }
+#endif
+
+        return r;
+}
+
+int label_socket_set(const char *label) {
+
+#if HAVE_SELINUX
+        if (use_selinux() && setsockcreatecon((security_context_t) label) < 0) {
+                log_error("Failed to set SELinux context (%s) on socket: %m", label);
+                if (security_getenforce() == 1)
+                        return -errno;
+        }
+#endif
+
+        return 0;
+}
+
+void label_file_clear(void) {
+
+#if HAVE_SELINUX
+        if (use_selinux())
+                setfscreatecon(NULL);
+#endif
+
+        return;
+}
+
+void label_free(const char *label) {
+
+#if HAVE_SELINUX
+        if (use_selinux())
+                freecon((security_context_t) label);
+#endif
+
+        return;
+}
+
+void label_socket_clear(void) {
+
+#if HAVE_SELINUX
+        if (use_selinux())
+                setsockcreatecon(NULL);
+#endif
+
+        return;
+}
+
+static int label_mkdir(
+        const char *path,
+        mode_t mode) {
+
+#if HAVE_SELINUX
+        int r;
+        security_context_t fcon = NULL;
+
+        if (use_selinux()) {
+                if (path[0] == '/') {
+                        r = selabel_lookup_raw(label_hnd, &fcon, path, mode);
+                }
+                else {
+                        char *cwd = NULL;
+                        char *newpath = NULL;
+                        cwd = getcwd(NULL,0);
+                        if ((! cwd) || (asprintf(&newpath, "%s/%s",cwd,path) < 0)) {
+                                free(cwd);
+                                return -errno;
+                        }
+                        r = selabel_lookup_raw(label_hnd, &fcon, newpath, mode);
+                        free(cwd);
+                        free(newpath);
+                }
+
+                if (r == 0)
+                        r = setfscreatecon(fcon);
+
+                if ((r < 0) && (errno != ENOENT)) {
+                        log_error("Failed to set security context %s for %s", fcon, path);
+
+                        if (security_getenforce() == 1)
+                                goto finish;
+                }
+        }
+        r = mkdir(path, mode);
+
+finish:
+        if (use_selinux()) {
+                setfscreatecon(NULL);
+                freecon(fcon);
+        }
+
+        return r;
+#else
+        return mkdir(path, mode);
+#endif
+}
+
 bool streq_ptr(const char *a, const char *b) {
 
         /* Like streq(), but tries to make sense of NULL pointers */
@@ -969,7 +1207,7 @@ char *file_in_same_dir(const char *path, const char *filename) {
 int safe_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid) {
         struct stat st;
 
-        if (mkdir(path, mode) >= 0)
+        if (label_mkdir(path, mode) >= 0)
                 if (chmod_and_chown(path, mode, uid, gid) < 0)
                         return -errno;
 
@@ -1012,7 +1250,7 @@ int mkdir_parents(const char *path, mode_t mode) {
                 if (!(t = strndup(path, e - path)))
                         return -ENOMEM;
 
-                r = mkdir(t, mode);
+                r = label_mkdir(t, mode);
                 free(t);
 
                 if (r < 0 && errno != EEXIST)
@@ -1028,7 +1266,7 @@ int mkdir_p(const char *path, mode_t mode) {
         if ((r = mkdir_parents(path, mode)) < 0)
                 return r;
 
-        if (mkdir(path, mode) < 0 && errno != EEXIST)
+        if (label_mkdir(path, mode) < 0 && errno != EEXIST)
                 return -errno;
 
         return 0;
diff --git a/src/util.h b/src/util.h
index 782adb8..b097dc9 100644
--- a/src/util.h
+++ b/src/util.h
@@ -360,4 +360,14 @@ int ip_tos_from_string(const char *s);
 const char *signal_to_string(int i);
 int signal_from_string(const char *s);
 
+int label_init(void);
+int label_fix(const char *path);
+void label_finish(void);
+int label_socket_set(const char *label);
+void label_socket_clear(void);
+int label_fifofile_set(const char *label, const char *path);
+void label_file_clear(void);
+void label_free(const char *label);
+int label_get_socket_label_from_exe(const char *exe, char **label);
+
 #endif
commit 8b33e5ca72def2b79ffcd9b7e96f8f40f6bd4a20
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Aug 3 23:29:18 2010 +0200

    update fixme

diff --git a/fixme b/fixme
index 9ed80a9..861c22b 100644
--- a/fixme
+++ b/fixme
@@ -61,6 +61,10 @@
 
 * if a service fails too often, make the service enter maintainence mode, and the socket, too.
 
+* systemctl reboot von getty tty1 hämgt
+
+* keine meldung by wants vs. conflicts
+
 External:
 
 * default.target must be %ghosted...
@@ -74,10 +78,6 @@ External:
 
 * patch /etc/init.d/functions with:
 
-* systemctl reboot von getty tty1 hämgt
-
-* keine meldung by wants vs. conflicts
-
   if [ $PPID -ne 1 && mountpoint /cgroup/systemd ] ; then echo "You suck!" ; fi
 
 https://bugzilla.redhat.com/show_bug.cgi?id=614245 -- plymouth
commit cebf8b209237db381a504c50eeba76c4c28fb677
Author: Tomasz Torcz <tomek at pipebreaker.pl>
Date:   Tue Aug 3 13:33:40 2010 +0200

    socket: Allow selection of TCP Congestion Avoidance algorithm to socket
    
    Hi,
    
    attached path extends socket configurables with another
    knob - TCP Congestion Avoidance selection. Linux implements
    handful of those, useful in various situations. For example,
    TCP Low Priority may be used by FTP service to gracefully
    yield bandwidth for more important TCP/IP streams.
    
    Until recently TCP_CONGESTION was Linux-specific, recently
    FreeBSD 8 and OpenSolaris gained compatible support.

diff --git a/man/systemd.socket.xml b/man/systemd.socket.xml
index 20dc00e..a7b8228 100644
--- a/man/systemd.socket.xml
+++ b/man/systemd.socket.xml
@@ -438,6 +438,18 @@
                         </varlistentry>
 
                         <varlistentry>
+                                <term><varname>TCPCongestion=</varname></term>
+                                <listitem><para>Takes a string
+                                value. Controls the TCP congestion
+                                algorithm used by this socket. Should
+                                be one of "westwood", "veno", "cubic",
+                                "lp" or any other available algorithm
+                                supported by the IP stack. This
+                                setting applies only to stream
+                                sockets.</para></listitem>
+                        </varlistentry>
+
+                        <varlistentry>
                                 <term><varname>ExecStartPre=</varname></term>
                                 <term><varname>ExecStartPost=</varname></term>
                                 <listitem><para>Takes one or more
diff --git a/src/load-fragment.c b/src/load-fragment.c
index 98f16f9..f2f2d72 100644
--- a/src/load-fragment.c
+++ b/src/load-fragment.c
@@ -1616,6 +1616,7 @@ static int load_from_path(Unit *u, const char *path) {
                 { "Mark",                   config_parse_int,             &u->socket.mark,                                 "Socket"  },
                 { "PipeSize",               config_parse_size,            &u->socket.pipe_size,                            "Socket"  },
                 { "FreeBind",               config_parse_bool,            &u->socket.free_bind,                            "Socket"  },
+                { "TCPCongestion",          config_parse_string,          &u->socket.tcp_congestion,                       "Socket"  },
                 EXEC_CONTEXT_CONFIG_ITEMS(u->socket.exec_context, "Socket"),
 
                 { "What",                   config_parse_string,          &u->mount.parameters_fragment.what,              "Mount"   },
diff --git a/src/socket.c b/src/socket.c
index 82a9348..2da3215 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -31,6 +31,7 @@
 
 #include "unit.h"
 #include "socket.h"
+#include "netinet/tcp.h"
 #include "log.h"
 #include "load-dropin.h"
 #include "load-fragment.h"
@@ -116,6 +117,9 @@ static void socket_done(Unit *u) {
 
         s->service = NULL;
 
+        free(s->tcp_congestion);
+        s->tcp_congestion = NULL;
+
         free(s->bind_to_device);
         s->bind_to_device = NULL;
 
@@ -371,14 +375,16 @@ static void socket_dump(Unit *u, FILE *f, const char *prefix) {
                 "%sSocketMode: %04o\n"
                 "%sDirectoryMode: %04o\n"
                 "%sKeepAlive: %s\n"
-                "%sFreeBind: %s\n",
+                "%sFreeBind: %s\n"
+                "%sTCPCongestion: %s\n",
                 prefix, socket_state_to_string(s->state),
                 prefix, socket_address_bind_ipv6_only_to_string(s->bind_ipv6_only),
                 prefix, s->backlog,
                 prefix, s->socket_mode,
                 prefix, s->directory_mode,
                 prefix, yes_no(s->keep_alive),
-                prefix, yes_no(s->free_bind));
+                prefix, yes_no(s->free_bind),
+                prefix, s->tcp_congestion);
 
         if (s->control_pid > 0)
                 fprintf(f,
@@ -632,6 +638,10 @@ static void socket_apply_socket_options(Socket *s, int fd) {
                 if (r < 0 && x < 0)
                         log_warning("IP_TTL/IPV6_UNICAST_HOPS failed: %m");
         }
+
+        if (s->tcp_congestion)
+                if (setsockopt(fd, SOL_TCP, TCP_CONGESTION, s->tcp_congestion, strlen(s->tcp_congestion)+1) < 0)
+                        log_warning("TCP_CONGESTION failed: %m");
 }
 
 static void socket_apply_fifo_options(Socket *s, int fd) {
diff --git a/src/socket.h b/src/socket.h
index 88ebf26..230dd20 100644
--- a/src/socket.h
+++ b/src/socket.h
@@ -114,6 +114,7 @@ struct Socket {
         int mark;
         bool free_bind;
         char *bind_to_device;
+        char *tcp_congestion;
 
         /* Only for INET6 sockets: issue IPV6_V6ONLY sockopt */
         SocketAddressBindIPv6Only bind_ipv6_only;
commit 07424048b52f8b22b472bf0370a185c1eb443417
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Aug 3 16:42:41 2010 +0200

    update fixme

diff --git a/fixme b/fixme
index 9f5d354..9ed80a9 100644
--- a/fixme
+++ b/fixme
@@ -74,6 +74,10 @@ External:
 
 * patch /etc/init.d/functions with:
 
+* systemctl reboot von getty tty1 hämgt
+
+* keine meldung by wants vs. conflicts
+
   if [ $PPID -ne 1 && mountpoint /cgroup/systemd ] ; then echo "You suck!" ; fi
 
 https://bugzilla.redhat.com/show_bug.cgi?id=614245 -- plymouth


More information about the systemd-commits mailing list