Module Name:    src
Committed By:   ad
Date:           Mon Jan  6 11:18:51 UTC 2020

Modified Files:
        src/sys/kern: tty.c

Log Message:
ttygetinfo(): avoid crash with zombies. From skrll@, tweaked by me.


To generate a diff of this commit:
cvs rdiff -u -r1.283 -r1.284 src/sys/kern/tty.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/kern/tty.c
diff -u src/sys/kern/tty.c:1.283 src/sys/kern/tty.c:1.284
--- src/sys/kern/tty.c:1.283	Thu Jan  2 16:52:55 2020
+++ src/sys/kern/tty.c	Mon Jan  6 11:18:51 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: tty.c,v 1.283 2020/01/02 16:52:55 skrll Exp $	*/
+/*	$NetBSD: tty.c,v 1.284 2020/01/06 11:18:51 ad Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -63,7 +63,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tty.c,v 1.283 2020/01/02 16:52:55 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tty.c,v 1.284 2020/01/06 11:18:51 ad Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_compat_netbsd.h"
@@ -2533,11 +2533,13 @@ ttygetinfo(struct tty *tp, int fromsig, 
 	const char	*msg;
 	char		lmsg[100];
 	long		rss;
+	bool		again = false;
 
 	KASSERT(mutex_owned(proc_lock));
 
 	*buf = '\0';
 
+ retry:
 	if (tp->t_session == NULL)
 		msg = "not a controlling terminal\n";
 	else if (tp->t_pgrp == NULL)
@@ -2568,11 +2570,26 @@ ttygetinfo(struct tty *tp, int fromsig, 
 			if (p->p_lock != oldpick->p_lock)
 				mutex_exit(oldpick->p_lock);
 		}
-		if (fromsig &&
-		    (SIGACTION_PS(pick->p_sigacts, SIGINFO).sa_flags &
-		    SA_NOKERNINFO))
-			return;
-		msg = NULL;
+
+		if (pick != NULL) {
+			mutex_enter(pick->p_lock);
+			if (P_ZOMBIE(pick)) {
+				mutex_exit(pick->p_lock);
+				pick = NULL;
+				if (!again) {
+					again = true;
+					goto retry;
+				}
+				msg = "found only zombie processes\n";
+			}
+			if (fromsig &&
+			    (SIGACTION_PS(pick->p_sigacts, SIGINFO).sa_flags &
+			    SA_NOKERNINFO)) {
+				mutex_exit(pick->p_lock);
+				return;
+			}
+			msg = NULL;
+		}
 	}
 
 	/* Print load average. */
@@ -2589,7 +2606,7 @@ ttygetinfo(struct tty *tp, int fromsig, 
 	    pick->p_pid);
 	strlcat(buf, lmsg, bufsz);
 
-	mutex_enter(pick->p_lock);
+	KASSERT(mutex_owned(pick->p_lock));
 	LIST_FOREACH(l, &pick->p_lwps, l_sibling) {
 		const char *lp;
 		lwp_lock(l);
@@ -2679,11 +2696,8 @@ proc_compare_wrapper(struct proc *p1, st
 	KASSERT(mutex_owned(p1->p_lock));
 	KASSERT(mutex_owned(p2->p_lock));
 
-	if ((l1 = LIST_FIRST(&p1->p_lwps)) == NULL)
-		return 1;
-
-	if ((l2 = LIST_FIRST(&p2->p_lwps)) == NULL)
-		return 0;
+	l1 = LIST_FIRST(&p1->p_lwps);
+	l2 = LIST_FIRST(&p2->p_lwps);
 
 	return proc_compare(p1, l1, p2, l2);
 }

Reply via email to