diff --git a/meta-networking/recipes-connectivity/inetutils/inetutils-1.9.2/telnetd-Fix-deadlock-on-cleanup.patch b/meta-networking/recipes-connectivity/inetutils/inetutils-1.9.2/telnetd-Fix-deadlock-on-cleanup.patch new file mode 100644 index 00000000000..3ec76131969 --- /dev/null +++ b/meta-networking/recipes-connectivity/inetutils/inetutils-1.9.2/telnetd-Fix-deadlock-on-cleanup.patch @@ -0,0 +1,108 @@ +telnetd: Fix deadlock on cleanup + +the patch comes from: +https://bugs.launchpad.net/ubuntu/+source/netkit-telnet/+bug/507455 +https://launchpadlibrarian.net/37882973/0001-telnetd-Fix-deadlock-on-cleanup.patch + +The cleanup function in telnetd is called both directly and on SIGCHLD +signals. This, unfortunately, triggered a deadlock in eglibc 2.9 while +running on a 2.6.31.11 kernel. + +What we were seeing is hangs like these: + + (gdb) bt + #0 0xb7702424 in __kernel_vsyscall () + #1 0xb7658e61 in __lll_lock_wait_private () from ./lib/libc.so.6 + #2 0xb767e7b5 in _L_lock_15 () from ./lib/libc.so.6 + #3 0xb767e6e0 in utmpname () from ./lib/libc.so.6 + #4 0xb76bcde7 in logout () from ./lib/libutil.so.1 + #5 0x0804c827 in cleanup () + #6 + #7 0xb7702424 in __kernel_vsyscall () + #8 0xb7641003 in __fcntl_nocancel () from ./lib/libc.so.6 + #9 0xb767e0c3 in getutline_r_file () from ./lib/libc.so.6 + #10 0xb767d675 in getutline_r () from ./lib/libc.so.6 + #11 0xb76bce42 in logout () from ./lib/libutil.so.1 + #12 0x0804c827 in cleanup () + #13 0x0804a0b5 in telnet () + #14 0x0804a9c3 in main () + +and what has happened here is that the user closes the telnet session +via the escape character. This causes telnetd to call cleanup in frame +the SIGCHLD signal is delivered while telnetd is executing cleanup. + +Telnetd then calls the signal handler for SIGCHLD, which is cleanup(). +Ouch. The actual deadlock is in libc. getutline_r in frame #10 gets the +__libc_utmp_lock lock, and utmpname above does the same thing in frame + +The fix registers the SIGCHLD handler as cleanup_sighandler, and makes +cleanup disable the SIGCHLD signal before calling cleanup_sighandler. + +Signed-off-by: Simon Kagstrom +Signed-off-by: Li Wang +--- + telnetd/pty.c | 17 ++++++++++++++++- + telnetd/telnetd.c | 2 +- + telnetd/telnetd.h | 1 + + 3 files changed, 18 insertions(+), 2 deletions(-) + +diff --git a/telnetd/pty.c b/telnetd/pty.c +index 21b0b69..22a17c5 100644 +--- a/telnetd/pty.c ++++ b/telnetd/pty.c +@@ -145,7 +145,7 @@ start_login (char *host, int autologin, char *name) + * reported exit code. + */ + void +-cleanup (int sig) ++cleanup_sighandler (int sig) + { + int status = EXIT_FAILURE; + char *p; +@@ -168,3 +168,18 @@ cleanup (int sig) + shutdown (net, 2); + exit (status); + } ++ ++void cleanup(int sig) { ++ sigset_t mask, oldmask; ++ ++ /* Set up the mask of signals to temporarily block. */ ++ sigemptyset (&mask); ++ sigaddset (&mask, SIGCHLD); ++ ++ /* Block SIGCHLD while running cleanup */ ++ sigprocmask (SIG_BLOCK, &mask, &oldmask); ++ ++ cleanup_sighandler(sig); ++ /* Technically not needed since cleanup_sighandler exits */ ++ sigprocmask (SIG_UNBLOCK, &mask, NULL); ++} +diff --git a/telnetd/telnetd.c b/telnetd/telnetd.c +index cf7ce0f..4fe95b5 100644 +--- a/telnetd/telnetd.c ++++ b/telnetd/telnetd.c +@@ -527,7 +527,7 @@ telnetd_setup (int fd) + signal (SIGTTOU, SIG_IGN); + #endif + +- signal (SIGCHLD, cleanup); ++ signal (SIGCHLD, cleanup_sighandler); + } + + int +diff --git a/telnetd/telnetd.h b/telnetd/telnetd.h +index ce90fbc..8bac120 100644 +--- a/telnetd/telnetd.h ++++ b/telnetd/telnetd.h +@@ -326,6 +326,7 @@ extern void add_slc (char func, char flag, cc_t val); + extern void check_slc (void); + extern void change_slc (char func, char flag, cc_t val); + ++extern void cleanup_sighandler (int); + extern void cleanup (int); + extern void clientstat (int, int, int); + extern void copy_termbuf (); +-- +1.7.9.5 + diff --git a/meta-networking/recipes-connectivity/inetutils/inetutils_1.9.2.bb b/meta-networking/recipes-connectivity/inetutils/inetutils_1.9.2.bb index dd69da4f088..620927209ec 100644 --- a/meta-networking/recipes-connectivity/inetutils/inetutils_1.9.2.bb +++ b/meta-networking/recipes-connectivity/inetutils/inetutils_1.9.2.bb @@ -18,6 +18,7 @@ SRC_URI = "${GNU_MIRROR}/inetutils/inetutils-${PV}.tar.gz \ file://telnet.xinetd.inetutils \ file://tftpd.xinetd.inetutils \ file://inetutils-1.9-PATH_PROCNET_DEV.patch \ + file://telnetd-Fix-deadlock-on-cleanup.patch \ " SRC_URI[md5sum] = "aa1a9a132259db83e66c1f3265065ba2"