Whamcloud - gitweb
LU-14006 o2ib: raise bind cap before resolving address 27/40127/2
authorJohn L. Hammond <jhammond@whamcloud.com>
Fri, 2 Oct 2020 18:55:01 +0000 (13:55 -0500)
committerOleg Drokin <green@whamcloud.com>
Mon, 12 Oct 2020 05:48:30 +0000 (05:48 +0000)
In kiblnd_resolve_addr(), ensure that the current task has
CAP_NET_BIND_SERVICE before calling rdma_resolve_addr() with a
protected source port.

Signed-off-by: John L. Hammond <jhammond@whamcloud.com>
Change-Id: I0552fdd64648ccb8c74667bd93852697f99f0c33
Reviewed-on: https://review.whamcloud.com/40127
Tested-by: jenkins <devops@whamcloud.com>
Reviewed-by: Amir Shehata <ashehata@whamcloud.com>
Tested-by: Amir Shehata <ashehata@whamcloud.com>
Tested-by: Maloo <maloo@whamcloud.com>
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
lnet/klnds/o2iblnd/o2iblnd_cb.c

index f3c1a4e..18ebbce 100644 (file)
@@ -1293,14 +1293,17 @@ kiblnd_queue_tx(struct kib_tx *tx, struct kib_conn *conn)
        spin_unlock(&conn->ibc_lock);
 }
 
-static int kiblnd_resolve_addr(struct rdma_cm_id *cmid,
-                               struct sockaddr_in *srcaddr,
-                               struct sockaddr_in *dstaddr,
-                               int timeout_ms)
+static int
+kiblnd_resolve_addr_cap(struct rdma_cm_id *cmid,
+                       struct sockaddr_in *srcaddr,
+                       struct sockaddr_in *dstaddr,
+                       int timeout_ms)
 {
         unsigned short port;
         int rc;
 
+       LASSERT(capable(CAP_NET_BIND_SERVICE));
+
         /* allow the port to be reused */
         rc = rdma_set_reuseaddr(cmid, 1);
         if (rc != 0) {
@@ -1330,6 +1333,33 @@ static int kiblnd_resolve_addr(struct rdma_cm_id *cmid,
         return rc;
 }
 
+static int
+kiblnd_resolve_addr(struct rdma_cm_id *cmid,
+                   struct sockaddr_in *srcaddr,
+                   struct sockaddr_in *dstaddr,
+                   int timeout_ms)
+{
+       const struct cred *old_creds = NULL;
+       struct cred *new_creds;
+       int rc;
+
+       if (!capable(CAP_NET_BIND_SERVICE)) {
+               new_creds = prepare_creds();
+               if (!new_creds)
+                       return -ENOMEM;
+
+               cap_raise(new_creds->cap_effective, CAP_NET_BIND_SERVICE);
+               old_creds = override_creds(new_creds);
+       }
+
+       rc = kiblnd_resolve_addr_cap(cmid, srcaddr, dstaddr, timeout_ms);
+
+       if (old_creds)
+               revert_creds(old_creds);
+
+       return rc;
+}
+
 static void
 kiblnd_connect_peer(struct kib_peer_ni *peer_ni)
 {