git: 784695750ef3 - releng/13.3 - jail: Fix information leak.

From: Ed Maste <emaste_at_FreeBSD.org>
Date: Thu, 29 Feb 2024 13:17:45 UTC
The branch releng/13.3 has been updated by emaste:

URL: https://cgit.FreeBSD.org/src/commit/?id=784695750ef3f73dec38150617684b9f757c787d

commit 784695750ef3f73dec38150617684b9f757c787d
Author:     Pawel Jakub Dawidek <pjd@FreeBSD.org>
AuthorDate: 2024-01-17 17:43:55 +0000
Commit:     Ed Maste <emaste@FreeBSD.org>
CommitDate: 2024-02-29 13:16:30 +0000

    jail: Fix information leak.
    
    There is a lack of proper visibility checking in kern.ttys sysctl handler
    which leads to information leak about processes outside the current jail.
    
    This can be demonstrated with pstat -t: when called from within a jail,
    it will output all terminal devices including process groups and
    session leader process IDs:
    
            jail# pstat -t | grep pts/ | head
                  LINE   INQ  CAN  LIN  LOW  OUTQ  USE  LOW   COL  SESS  PGID STATE
                 pts/2  1920    0    0  192  1984    0  199     0  4132 27245 Oi
                 pts/3  1920    0    0  192  1984    0  199    16 24890 33627 Oi
                 pts/5     0    0    0    0     0    0    0    25 17758     0 G
                pts/16     0    0    0    0     0    0    0     0 52495     0 G
                pts/15     0    0    0    0     0    0    0    25 53446     0 G
                pts/17     0    0    0    0     0    0    0  6702 33230     0 G
                pts/19     0    0    0    0     0    0    0    14  1116     0 G
                 pts/0     0    0    0    0     0    0    0     0  2241     0 G
                pts/23     0    0    0    0     0    0    0    20 15639     0 G
                 pts/6     0    0    0    0     0    0    0     0 44062 93792 G
            jail# pstat -t | grep pts/ | wc -l
                  85
    
    Devfs does the filtering correctly and we get only one entry:
    
            jail# ls /dev/pts/
            2
    
    Approved by:    mzaborski, secteam
    MFC after:      1 week
    Sponsored by:   Fudo Security
    
    (cherry picked from commit f1d0a0cbecf2c688061f35adea85bfb29c9ec893)
    (cherry picked from commit a376108029a20f4ce51476d98f2483a7008ce7b5)
    (cherry picked from commit 41ac0b4ce00bae061164384f23356a4df6e0e695)
    (cherry picked from commit 9bff7ec98354a76c171905ce9530f85685725ee7)
    
    Approved by:    re (cperciva)
---
 sys/kern/tty.c | 26 ++++++++++++++++++++++----
 1 file changed, 22 insertions(+), 4 deletions(-)

diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index d7f9a914166a..508c0f14b861 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -44,6 +44,7 @@
 #ifdef COMPAT_43TTY
 #include <sys/ioctl_compat.h>
 #endif /* COMPAT_43TTY */
+#include <sys/jail.h>
 #include <sys/kernel.h>
 #include <sys/limits.h>
 #include <sys/malloc.h>
@@ -1308,9 +1309,11 @@ static int
 sysctl_kern_ttys(SYSCTL_HANDLER_ARGS)
 {
 	unsigned long lsize;
+	struct thread *td = curthread;
 	struct xtty *xtlist, *xt;
 	struct tty *tp;
-	int error;
+	struct proc *p;
+	int cansee, error;
 
 	sx_slock(&tty_list_sx);
 	lsize = tty_list_count * sizeof(struct xtty);
@@ -1323,13 +1326,28 @@ sysctl_kern_ttys(SYSCTL_HANDLER_ARGS)
 
 	TAILQ_FOREACH(tp, &tty_list, t_list) {
 		tty_lock(tp);
-		tty_to_xtty(tp, xt);
+		if (tp->t_session != NULL) {
+			p = tp->t_session->s_leader;
+			PROC_LOCK(p);
+			cansee = (p_cansee(td, p) == 0);
+			PROC_UNLOCK(p);
+		} else {
+			cansee = !jailed(td->td_ucred);
+		}
+		if (cansee) {
+			tty_to_xtty(tp, xt);
+			xt++;
+		}
 		tty_unlock(tp);
-		xt++;
 	}
 	sx_sunlock(&tty_list_sx);
 
-	error = SYSCTL_OUT(req, xtlist, lsize);
+	lsize = (xt - xtlist) * sizeof(struct xtty);
+	if (lsize > 0) {
+		error = SYSCTL_OUT(req, xtlist, lsize);
+	} else {
+		error = 0;
+	}
 	free(xtlist, M_TTY);
 	return (error);
 }