git: 2fb778fab893 - main - MAC: improve handling of listening sockets

From: Michael Tuexen <tuexen_at_FreeBSD.org>
Date: Thu, 26 Sep 2024 06:08:44 UTC
The branch main has been updated by tuexen:

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

commit 2fb778fab893b4a8a86ecfa20acf2e23bb2cdae8
Author:     Michael Tuexen <tuexen@FreeBSD.org>
AuthorDate: 2024-09-26 06:06:24 +0000
Commit:     Michael Tuexen <tuexen@FreeBSD.org>
CommitDate: 2024-09-26 06:06:24 +0000

    MAC: improve handling of listening sockets
    
    so_peerlabel can only be used when the socket is not listening.
    
    Reviewed by:            markj
    MFC after:              1 week
    Sponsored by:           Netflix, Inc.
    Differential Revision:  https://reviews.freebsd.org/D46755
---
 sys/kern/uipc_socket.c          |  5 +++++
 sys/security/mac/mac_internal.h |  1 +
 sys/security/mac/mac_socket.c   | 19 +++++++++++++------
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index e83422e3a29f..189e8ca5b498 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -153,6 +153,7 @@
 #include <net/vnet.h>
 
 #include <security/mac/mac_framework.h>
+#include <security/mac/mac_internal.h>
 
 #include <vm/uma.h>
 
@@ -1485,6 +1486,10 @@ solisten_proto(struct socket *so, int backlog)
 	sbrcv_timeo = so->so_rcv.sb_timeo;
 	sbsnd_timeo = so->so_snd.sb_timeo;
 
+#ifdef MAC
+	mac_socketpeer_label_free(so->so_peerlabel);
+#endif
+
 	if (!(so->so_proto->pr_flags & PR_SOCKBUF)) {
 		sbdestroy(so, SO_SND);
 		sbdestroy(so, SO_RCV);
diff --git a/sys/security/mac/mac_internal.h b/sys/security/mac/mac_internal.h
index aa407598600a..89f74a65c803 100644
--- a/sys/security/mac/mac_internal.h
+++ b/sys/security/mac/mac_internal.h
@@ -242,6 +242,7 @@ struct label	*mac_pipe_label_alloc(void);
 void		 mac_pipe_label_free(struct label *label);
 struct label	*mac_socket_label_alloc(int flag);
 void		 mac_socket_label_free(struct label *label);
+void		 mac_socketpeer_label_free(struct label *label);
 struct label	*mac_vnode_label_alloc(void);
 void		 mac_vnode_label_free(struct label *label);
 
diff --git a/sys/security/mac/mac_socket.c b/sys/security/mac/mac_socket.c
index e9f94404734a..b03f98bbfdb5 100644
--- a/sys/security/mac/mac_socket.c
+++ b/sys/security/mac/mac_socket.c
@@ -170,7 +170,7 @@ mac_socket_label_free(struct label *label)
 	mac_labelzone_free(label);
 }
 
-static void
+void
 mac_socketpeer_label_free(struct label *label)
 {
 
@@ -185,8 +185,10 @@ mac_socket_destroy(struct socket *so)
 	if (so->so_label != NULL) {
 		mac_socket_label_free(so->so_label);
 		so->so_label = NULL;
-		mac_socketpeer_label_free(so->so_peerlabel);
-		so->so_peerlabel = NULL;
+		if (!SOLISTENING(so)) {
+			mac_socketpeer_label_free(so->so_peerlabel);
+			so->so_peerlabel = NULL;
+		}
 	}
 }
 
@@ -618,10 +620,15 @@ mac_getsockopt_peerlabel(struct ucred *cred, struct socket *so,
 	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
 	intlabel = mac_socket_label_alloc(M_WAITOK);
 	SOCK_LOCK(so);
-	mac_socket_copy_label(so->so_peerlabel, intlabel);
+	if (SOLISTENING(so))
+		error = EINVAL;
+	else
+		mac_socket_copy_label(so->so_peerlabel, intlabel);
 	SOCK_UNLOCK(so);
-	error = mac_socketpeer_externalize_label(intlabel, elements, buffer,
-	    mac->m_buflen);
+	if (error == 0) {
+		error = mac_socketpeer_externalize_label(intlabel, elements, buffer,
+		    mac->m_buflen);
+	}
 	mac_socket_label_free(intlabel);
 	if (error == 0)
 		error = copyout(buffer, mac->m_string, strlen(buffer)+1);