]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
RDS: IB: enforce IP anti-spoofing for UUID context
authorSantosh Shilimkar <santosh.shilimkar@oracle.com>
Tue, 15 Mar 2016 12:32:09 +0000 (05:32 -0700)
committerSantosh Shilimkar <santosh.shilimkar@oracle.com>
Tue, 31 May 2016 16:03:34 +0000 (09:03 -0700)
Connection is established only after the IP requesting the connection
is legitimate and part of the ACL group. Invalid connection request(s)
are rejected and destroyed.

Ajay moved destroy connection when ACL check fails while initiating
connection to avoid unnecessary packet transfer on wire.

Orabug: 23222944

Signed-off-by: Yuval Shaia <yuval.shaia@oracle.com>
Signed-off-by: Bang Ngyen <bang.nguyen@oracle.com>
Signed-off-by: Ajaykumar Hotchandani <ajaykumar.hotchandani@oracle.com>
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
net/rds/ib_cm.c

index 21edd76e4dc7fc87b7ccac69ee4e6ce0ed59877d..870ec8dcaee6bb93c6e9c88625bdb17e65af1802 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm-generic/sizes.h>
 #include <rdma/rdma_cm_ib.h>
 #include <rdma/ib_cache.h>
+#include <rdma/ib_cm.h>
 
 #include "rds.h"
 #include "ib.h"
@@ -192,6 +193,48 @@ static inline void rds_ib_init_ic_frag(struct rds_ib_connection *ic)
                ic->i_frag_sz = ib_init_frag_size;
 }
 
+/*
+*  0 - all good copy uuid to the connection context
+*  1 - acl is not enabled, ignore uuid
+* -1 - acl match failed
+*/
+static int rds_ib_match_acl(struct rdma_cm_id *cm_id, u32 saddr, char* uuid)
+{
+       struct ib_cm_acl *acl = 0;
+       struct ib_cm_acl_elem *acl_elem = 0;
+       __be64 fguid = cm_id->route.path_rec->dgid.global.interface_id;
+       __be64 fsubnet = cm_id->route.path_rec->dgid.global.subnet_prefix;
+       struct ib_cm_dpp dpp;
+
+       ib_cm_dpp_init(&dpp, cm_id->device, cm_id->port_num,
+                      ntohs(cm_id->route.path_rec->pkey));
+       acl = ib_cm_dpp_acl_lookup(&dpp);
+       if (!acl)
+               goto out;
+
+       if (!acl->enabled)
+               return 0;
+
+       acl_elem = ib_cm_acl_lookup(acl, be64_to_cpu(fsubnet),
+                                   be64_to_cpu(fguid));
+       if (!acl_elem)
+               goto out;
+
+       saddr = be32_to_cpu(saddr);
+       if (!saddr)
+               goto out;
+
+       acl_elem = ib_cm_acl_lookup_uuid_ip(acl, acl_elem->uuid, saddr);
+       if (!acl_elem)
+               goto out;
+
+       memcpy(uuid, acl_elem->uuid, UUID_SZ);
+       return 1;
+out:
+       pr_err("RDS/IB: %s failed due to ACL mismatch. Check ACLs\n", __func__);
+       return -1;
+}
+
 /*
  * Connection established.
  * We get here for both outgoing and incoming connection.
@@ -231,13 +274,14 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even
                }
        }
 
-       printk(KERN_NOTICE "RDS/IB: %s conn %p i_cm_id %p, frag %dKB, connected <%pI4,%pI4,%d> version %u.%u%s\n",
+       printk(KERN_NOTICE "RDS/IB: %s conn %p i_cm_id %p, frag %dKB, connected <%pI4,%pI4,%d> version %u.%u%s%s\n",
               ic->i_active_side ? "Active " : "Passive",
               conn, ic->i_cm_id, ic->i_frag_sz / SZ_1K,
               &conn->c_laddr, &conn->c_faddr, conn->c_tos,
               RDS_PROTOCOL_MAJOR(conn->c_version),
               RDS_PROTOCOL_MINOR(conn->c_version),
-              ic->i_flowctl ? ", flow control" : "");
+              ic->i_flowctl ? ", flow control" : "",
+              conn->c_acl_en ? ", ACL Enabled" : "");
 
        /* The connection might have been dropped under us*/
        if (!ic->i_cm_id) {
@@ -793,6 +837,8 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
        struct rdma_conn_param conn_param;
        u32 version;
        int err = 1, destroy = 1;
+       char uuid[UUID_SZ];
+       int acl_ret = 0;
 
        /* Check whether the remote protocol version matches ours. */
        version = rds_ib_protocol_compatible(event);
@@ -808,6 +854,13 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
                (unsigned long long)be64_to_cpu(fguid),
                dp->dp_tos);
 
+       acl_ret = rds_ib_match_acl(cm_id, dp->dp_saddr, uuid);
+       if (acl_ret < 0) {
+               rdma_reject(cm_id, &acl_ret, sizeof(int));
+               rdsdebug("RDS: IB: rds_ib_match_acl failed\n");
+               goto out;
+       }
+
        /* RDS/IB is not currently netns aware, thus init_net */
        conn = rds_conn_create(&init_net, dp->dp_daddr, dp->dp_saddr,
                               &rds_ib_transport, dp->dp_tos, GFP_KERNEL);
@@ -821,6 +874,10 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
        rds_ib_set_protocol(conn, version);
        rds_ib_set_frag_size(conn, be16_to_cpu(dp->dp_frag_sz));
 
+       memcpy(conn->c_uuid, uuid, RDS_UUID_MAXLEN);
+       conn->c_acl_en = acl_ret;
+       conn->c_acl_init = 1;
+
        if (dp->dp_tos && !conn->c_base_conn) {
                conn->c_base_conn = rds_conn_create(&init_net,
                                        dp->dp_daddr, dp->dp_saddr,
@@ -989,6 +1046,20 @@ int rds_ib_cm_initiate_connect(struct rdma_cm_id *cm_id)
        struct rdma_conn_param conn_param;
        struct rds_ib_connect_private dp;
        int ret;
+       char uuid[UUID_SZ];
+
+       ret = rds_ib_match_acl(ic->i_cm_id, conn->c_faddr, uuid);
+       if (ret < 0) {
+               pr_err("RDS: IB: active conn=%p, <%u.%u.%u.%u,%u.%u.%u.%u,%d> destroyed due ACL violation\n",
+                       conn, NIPQUAD(conn->c_laddr), NIPQUAD(conn->c_faddr),
+                       conn->c_tos);
+               rds_ib_conn_destroy_init(conn);
+               return 0;
+       }
+
+       memcpy(conn->c_uuid, uuid, RDS_UUID_MAXLEN);
+       conn->c_acl_en = ret;
+       conn->c_acl_init = 1;
 
        rds_ib_set_protocol(conn, RDS_PROTOCOL_4_1);
        ic->i_flowctl = rds_ib_sysctl_flow_control;     /* advertise flow control */