From: John L. Hammond Date: Fri, 2 Oct 2020 18:55:01 +0000 (-0500) Subject: LU-14006 o2ib: raise bind cap before resolving address X-Git-Tag: 2.13.57~147 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=1e4bd16acfa26a06486ebd3426547502eedefa45 LU-14006 o2ib: raise bind cap before resolving address 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 Change-Id: I0552fdd64648ccb8c74667bd93852697f99f0c33 Reviewed-on: https://review.whamcloud.com/40127 Tested-by: jenkins Reviewed-by: Amir Shehata Tested-by: Amir Shehata Tested-by: Maloo Reviewed-by: Andreas Dilger --- diff --git a/lnet/klnds/o2iblnd/o2iblnd_cb.c b/lnet/klnds/o2iblnd/o2iblnd_cb.c index f3c1a4e..18ebbce 100644 --- a/lnet/klnds/o2iblnd/o2iblnd_cb.c +++ b/lnet/klnds/o2iblnd/o2iblnd_cb.c @@ -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) {