selinux: Implement mptcp_add_subflow hook
authorPaolo Abeni <pabeni@redhat.com>
Thu, 20 Apr 2023 17:17:14 +0000 (19:17 +0200)
committerPaul Moore <paul@paul-moore.com>
Thu, 18 May 2023 17:11:10 +0000 (13:11 -0400)
Newly added subflows should inherit the LSM label from the associated
MPTCP socket regardless of the current context.

This patch implements the above copying sid and class from the MPTCP
socket context, deleting the existing subflow label, if any, and then
re-creating the correct one.

The new helper reuses the selinux_netlbl_sk_security_free() function,
and the latter can end-up being called multiple times with the same
argument; we additionally need to make it idempotent.

Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Acked-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Paul Moore <paul@paul-moore.com>
security/selinux/hooks.c
security/selinux/netlabel.c

index 99ded60..03660e5 100644 (file)
@@ -5379,6 +5379,21 @@ static void selinux_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk
        selinux_netlbl_sctp_sk_clone(sk, newsk);
 }
 
+static int selinux_mptcp_add_subflow(struct sock *sk, struct sock *ssk)
+{
+       struct sk_security_struct *ssksec = ssk->sk_security;
+       struct sk_security_struct *sksec = sk->sk_security;
+
+       ssksec->sclass = sksec->sclass;
+       ssksec->sid = sksec->sid;
+
+       /* replace the existing subflow label deleting the existing one
+        * and re-recreating a new label using the updated context
+        */
+       selinux_netlbl_sk_security_free(ssksec);
+       return selinux_netlbl_socket_post_create(ssk, ssk->sk_family);
+}
+
 static int selinux_inet_conn_request(const struct sock *sk, struct sk_buff *skb,
                                     struct request_sock *req)
 {
@@ -7074,6 +7089,7 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = {
        LSM_HOOK_INIT(sctp_sk_clone, selinux_sctp_sk_clone),
        LSM_HOOK_INIT(sctp_bind_connect, selinux_sctp_bind_connect),
        LSM_HOOK_INIT(sctp_assoc_established, selinux_sctp_assoc_established),
+       LSM_HOOK_INIT(mptcp_add_subflow, selinux_mptcp_add_subflow),
        LSM_HOOK_INIT(inet_conn_request, selinux_inet_conn_request),
        LSM_HOOK_INIT(inet_csk_clone, selinux_inet_csk_clone),
        LSM_HOOK_INIT(inet_conn_established, selinux_inet_conn_established),
index 767c670..528f518 100644 (file)
@@ -154,8 +154,12 @@ void selinux_netlbl_err(struct sk_buff *skb, u16 family, int error, int gateway)
  */
 void selinux_netlbl_sk_security_free(struct sk_security_struct *sksec)
 {
-       if (sksec->nlbl_secattr != NULL)
-               netlbl_secattr_free(sksec->nlbl_secattr);
+       if (!sksec->nlbl_secattr)
+               return;
+
+       netlbl_secattr_free(sksec->nlbl_secattr);
+       sksec->nlbl_secattr = NULL;
+       sksec->nlbl_state = NLBL_UNSET;
 }
 
 /**