git: a376108029a2 - stable/13 - jail: Fix information leak.

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Mon, 12 Feb 2024 16:27:36 UTC
The branch stable/13 has been updated by markj:

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

commit a376108029a20f4ce51476d98f2483a7008ce7b5
Author:     Pawel Jakub Dawidek <pjd@FreeBSD.org>
AuthorDate: 2024-01-17 17:43:55 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2024-02-12 16:26:02 +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)
---
 sys/kern/tty.c | 25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index d7f9a914166a..be4cc2593fd1 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -1308,9 +1308,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 +1325,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);
 }