[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#480020: openssh-server: adjusted OOM killer is inherited by all child processes



Package: openssh-server
Version: 1:4.7p1-8
Severity: normal
Tags: patch

Hi,
there is IMO problem with adjusting OOM killer by startup script,
because it is inherited by all child processes:

zito@bobek:/tmp$ ./ps_oom_adj 
OMA   PID TTY      STAT   TIME COMMAND
...
-17 24733 ?        Ss     0:00 /usr/sbin/sshd
-17 25007 ?        Ss     0:00  \_ sshd: zito [priv]
-17 25010 ?        S      0:00      \_ sshd: zito@pts/11
-17 25012 pts/11   Ss+    0:00          \_ -bash

^^^ everything is immortal

I have prepared an attached patch, that implements adjusting directly in
sshd and the adjusting is reverted after fork() to original value.

sid:~# ./ps_oom_adj 
OMA   PID TTY      STAT   TIME COMMAND
...
-17  1494 ?        Ss     0:00 /usr/sbin/sshd
  0  1645 ?        Ss     0:00  \_ sshd: zito [priv]
  0  1649 ?        S      0:00      \_ sshd: zito@pts/0 
  0  1652 pts/0    Ss     0:00          \_ -bash
  0  1669 pts/0    S      0:00              \_ newrole -r sysadm_r


This also solves problem with enabled SE Linux - no need to change
policy for this. I hope this change will be usable, please review the
code.
Thanks
-- 
zito

-- System Information:
Debian Release: lenny/sid
  APT prefers unstable
  APT policy: (500, 'unstable')
Architecture: i386 (i686)

Kernel: Linux 2.6.24-1-686 (SMP w/2 CPU cores)
Locale: LANG=C, LC_CTYPE=cs_CZ.ISO-8859-2 (charmap=ISO-8859-2)
Shell: /bin/sh linked to /bin/bash

Versions of packages openssh-server depends on:
ii  adduser              3.107               add and remove users and groups
ii  debconf [debconf-2.0 1.5.21              Debian configuration management sy
ii  dpkg                 1.14.18             package maintenance system for Deb
ii  libc6                2.7-10              GNU C Library: Shared libraries
ii  libcomerr2           1.40.8-2            common error description library
ii  libkrb53             1.6.dfsg.3-1        MIT Kerberos runtime libraries
ii  libpam-modules       0.99.10.0-1~icz50+1 Pluggable Authentication Modules f
ii  libpam-runtime       0.99.10.0-1~icz50+1 Runtime support for the PAM librar
ii  libpam0g             0.99.10.0-1~icz50+1 Pluggable Authentication Modules l
ii  libselinux1          2.0.59-1            SELinux shared libraries
ii  libssl0.9.8          0.9.8g-8            SSL shared libraries
ii  libwrap0             7.6.q-15            Wietse Venema's TCP wrappers libra
ii  lsb-base             3.2-12              Linux Standard Base 3.2 init scrip
ii  openssh-client       1:4.7p1-8           secure shell client, an rlogin/rsh
ii  zlib1g               1:1.2.3.3.dfsg-12   compression library - runtime

Versions of packages openssh-server recommends:
ii  xauth                         1:1.0.3-1  X authentication utility

-- debconf information excluded
diff --git a/debian/changelog b/debian/changelog
index 2801ec2..293a2b3 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,12 @@
+openssh (1:4.7p1-9~icz50+1) unstable; urgency=low
+
+  * Rewritten adjusting of OOM-killer directly into sshd.c.
+     - no need to change SE Linux policy in this case
+     - adjusting is done for parent sshd process and is returned back
+       for childs
+
+ -- Vaclav Ovsik <vaclav.ovsik@i.cz>  Wed, 07 May 2008 17:15:28 +0200
+
 openssh (1:4.7p1-8) unstable; urgency=high
 
   * Fill in CVE identifier for security vulnerability fixed in 1:4.7p1-5.
diff --git a/debian/openssh-server.init b/debian/openssh-server.init
index 862d117..7d7d54b 100644
--- a/debian/openssh-server.init
+++ b/debian/openssh-server.init
@@ -20,6 +20,7 @@ SSHD_OOM_ADJUST=-17
 if test -f /etc/default/ssh; then
     . /etc/default/ssh
 fi
+export SSHD_OOM_ADJUST
 
 . /lib/lsb/init-functions
 
@@ -71,15 +72,6 @@ check_config() {
     fi
 }
 
-adjust_oom() {
-    if [ -e /var/run/sshd.pid ]; then
-	PID="$(head -n1 /var/run/sshd.pid)"
-	if [ -e "/proc/$PID/oom_adj" ]; then
-	    printf '%s' "$SSHD_OOM_ADJUST" >"/proc/$PID/oom_adj" || true
-	fi
-    fi
-}
-
 export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"
 
 case "$1" in
@@ -90,7 +82,6 @@ case "$1" in
 	log_daemon_msg "Starting OpenBSD Secure Shell server" "sshd"
 	if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd -- $SSHD_OPTS; then
 	    log_end_msg 0
-	    adjust_oom
 	else
 	    log_end_msg 1
 	fi
@@ -124,7 +115,6 @@ case "$1" in
 	check_dev_null log_end_msg
 	if start-stop-daemon --start --quiet --oknodo --pidfile /var/run/sshd.pid --exec /usr/sbin/sshd -- $SSHD_OPTS; then
 	    log_end_msg 0
-	    adjust_oom
 	else
 	    log_end_msg 1
 	fi
diff --git a/sshd.c b/sshd.c
index add61cc..75c37bd 100644
--- a/sshd.c
+++ b/sshd.c
@@ -251,6 +251,10 @@ Buffer loginmsg;
 /* Unprivileged user */
 struct passwd *privsep_pw = NULL;
 
+/* Linux OOM killer adjusting */
+static char oom_adj_save[8];
+static ssize_t oom_adj_save_n = 0;
+
 /* Prototypes for various functions defined later in this file. */
 void destroy_sensitive_data(void);
 void demote_sensitive_data(void);
@@ -259,6 +263,45 @@ static void do_ssh1_kex(void);
 static void do_ssh2_kex(void);
 
 /*
+ * Linux OOM killer adjusting
+ */
+static int oom_adj_open(void)
+{
+	int fd = open("/proc/self/oom_adj", O_RDWR);
+	if (fd < 0)
+		logit("error opening /proc/self/oom_adj: %s", strerror(errno));
+	return fd;
+}
+
+static int oom_adj_get(char *buf, size_t *len, size_t maxlen)
+{
+	ssize_t n;
+	int fd = oom_adj_open();
+	if ( fd < 0 )
+		return -1;
+	n = read(fd, buf, maxlen);
+	if ( n < 0 )
+		logit("error reading /proc/self/oom_adj: %s", strerror(errno));
+	else
+		*len = (size_t)n;
+	close(fd);
+	return n < 0 ? -1 : 0;
+}
+
+static int oom_adj_set(const char *buf, size_t len)
+{
+	ssize_t n;
+	int fd = oom_adj_open();
+	if ( fd < 0 )
+		return -1;
+	n = write(fd, buf, len);
+	if ( n < 0 )
+		logit("error writing /proc/self/oom_adj: %s", strerror(errno));
+	close(fd);
+	return n < 0 ? -1 : 0;
+}
+
+/*
  * Close all listening sockets
  */
 static void
@@ -1031,6 +1074,15 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
 	for (i = 0; i < options.max_startups; i++)
 		startup_pipes[i] = -1;
 
+	/* Linux OOM killer adjusting */
+	if (getenv("SSHD_OOM_ADJUST") != NULL)
+	{
+		const char *oom_adj = getenv("SSHD_OOM_ADJUST");
+		oom_adj_get(oom_adj_save, &oom_adj_save_n,
+			    sizeof(oom_adj_save));
+		oom_adj_set(oom_adj, strlen(oom_adj));
+	}
+
 	/*
 	 * Stay listening for connections until the system crashes or
 	 * the daemon is killed with a signal.
@@ -1166,6 +1218,8 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
 				 * We break out of the loop to handle
 				 * the connection.
 				 */
+				if ( oom_adj_save_n > 0 )
+					oom_adj_set(oom_adj_save, oom_adj_save_n);
 				platform_post_fork_child();
 				startup_pipe = startup_p[1];
 				close_startup_pipes();

Attachment: ps_oom_adj
Description: application/shellscript


Reply to: