Skip to content

Commit 25e58c2

Browse files
SantoshShilimkarLinuxMinion
authored andcommitted
RDS: IB: enforce IP anti-spoofing based on ACLs
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: Bang Ngyen <[email protected]> Signed-off-by: Ajaykumar Hotchandani <[email protected]> Signed-off-by: Yuval Shaia <[email protected]> Signed-off-by: Santosh Shilimkar <[email protected]>
1 parent 857b901 commit 25e58c2

File tree

1 file changed

+75
-2
lines changed

1 file changed

+75
-2
lines changed

net/rds/ib_cm.c

Lines changed: 75 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include <asm-generic/sizes.h>
3737
#include <rdma/rdma_cm_ib.h>
3838
#include <rdma/ib_cache.h>
39+
#include <rdma/ib_cm.h>
3940

4041
#include "rds.h"
4142
#include "ib.h"
@@ -192,6 +193,54 @@ static inline void rds_ib_init_ic_frag(struct rds_ib_connection *ic)
192193
ic->i_frag_sz = ib_init_frag_size;
193194
}
194195

196+
/*
197+
* 0 - all good
198+
* 1 - acl is not enabled
199+
* -1 - acl match failed
200+
*/
201+
static int rds_ib_match_acl(struct rdma_cm_id *cm_id, __be32 saddr)
202+
{
203+
struct ib_cm_acl *acl = 0;
204+
struct ib_cm_acl_elem *acl_elem = 0;
205+
__be64 fguid = cm_id->route.path_rec->dgid.global.interface_id;
206+
__be64 fsubnet = cm_id->route.path_rec->dgid.global.subnet_prefix;
207+
struct ib_cm_dpp dpp;
208+
u32 addr;
209+
210+
ib_cm_dpp_init(&dpp, cm_id->device, cm_id->port_num,
211+
ntohs(cm_id->route.path_rec->pkey));
212+
acl = ib_cm_dpp_acl_lookup(&dpp);
213+
if (!acl)
214+
goto out;
215+
216+
if (!acl->enabled)
217+
return 0;
218+
219+
acl_elem = ib_cm_acl_lookup(acl, be64_to_cpu(fsubnet),
220+
be64_to_cpu(fguid));
221+
if (!acl_elem) {
222+
pr_err_ratelimited("RDS/IB: GUID ib_cm_acl_lookup() failed\n");
223+
goto out;
224+
}
225+
226+
addr = be32_to_cpu(saddr);
227+
if (!addr)
228+
goto out;
229+
230+
acl_elem = ib_cm_acl_lookup_uuid_ip(acl, acl_elem->uuid, addr);
231+
if (!acl_elem) {
232+
pr_err_ratelimited("RDS/IB: IP %pI4 ib_cm_acl_lookup_uuid_ip() failed\n",
233+
&saddr);
234+
goto out;
235+
}
236+
237+
return 1;
238+
out:
239+
pr_err_ratelimited("RDS/IB: %s failed due to ACLs. Check ACLs\n",
240+
__func__);
241+
return -1;
242+
}
243+
195244
/*
196245
* Connection established.
197246
* We get here for both outgoing and incoming connection.
@@ -231,13 +280,14 @@ void rds_ib_cm_connect_complete(struct rds_connection *conn, struct rdma_cm_even
231280
}
232281
}
233282

234-
printk(KERN_NOTICE "RDS/IB: %s conn %p i_cm_id %p, frag %dKB, connected <%pI4,%pI4,%d> version %u.%u%s\n",
283+
printk(KERN_NOTICE "RDS/IB: %s conn %p i_cm_id %p, frag %dKB, connected <%pI4,%pI4,%d> version %u.%u%s%s\n",
235284
ic->i_active_side ? "Active " : "Passive",
236285
conn, ic->i_cm_id, ic->i_frag_sz / SZ_1K,
237286
&conn->c_laddr, &conn->c_faddr, conn->c_tos,
238287
RDS_PROTOCOL_MAJOR(conn->c_version),
239288
RDS_PROTOCOL_MINOR(conn->c_version),
240-
ic->i_flowctl ? ", flow control" : "");
289+
ic->i_flowctl ? ", flow control" : "",
290+
conn->c_acl_en ? ", ACL Enabled" : "");
241291

242292
/* The connection might have been dropped under us*/
243293
if (!ic->i_cm_id) {
@@ -822,6 +872,7 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
822872
struct rdma_conn_param conn_param;
823873
u32 version;
824874
int err = 1, destroy = 1;
875+
int acl_ret = 0;
825876

826877
/* Check whether the remote protocol version matches ours. */
827878
version = rds_ib_protocol_compatible(event);
@@ -837,6 +888,13 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
837888
(unsigned long long)be64_to_cpu(fguid),
838889
dp->dp_tos);
839890

891+
acl_ret = rds_ib_match_acl(cm_id, dp->dp_saddr);
892+
if (acl_ret < 0) {
893+
rdma_reject(cm_id, &acl_ret, sizeof(int));
894+
rdsdebug("RDS: IB: rds_ib_match_acl failed\n");
895+
goto out;
896+
}
897+
840898
/* RDS/IB is not currently netns aware, thus init_net */
841899
conn = rds_conn_create(&init_net, dp->dp_daddr, dp->dp_saddr,
842900
&rds_ib_transport, dp->dp_tos, GFP_KERNEL);
@@ -850,6 +908,9 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id,
850908
rds_ib_set_protocol(conn, version);
851909
rds_ib_set_frag_size(conn, be16_to_cpu(dp->dp_frag_sz));
852910

911+
conn->c_acl_en = acl_ret;
912+
conn->c_acl_init = 1;
913+
853914
if (dp->dp_tos && !conn->c_base_conn) {
854915
conn->c_base_conn = rds_conn_create(&init_net,
855916
dp->dp_daddr, dp->dp_saddr,
@@ -1019,6 +1080,18 @@ int rds_ib_cm_initiate_connect(struct rdma_cm_id *cm_id)
10191080
struct rds_ib_connect_private dp;
10201081
int ret;
10211082

1083+
ret = rds_ib_match_acl(ic->i_cm_id, conn->c_faddr);
1084+
if (ret < 0) {
1085+
pr_err("RDS: IB: active conn=%p, <%u.%u.%u.%u,%u.%u.%u.%u,%d> destroyed due ACL violation\n",
1086+
conn, NIPQUAD(conn->c_laddr), NIPQUAD(conn->c_faddr),
1087+
conn->c_tos);
1088+
rds_ib_conn_destroy_init(conn);
1089+
return 0;
1090+
}
1091+
1092+
conn->c_acl_en = ret;
1093+
conn->c_acl_init = 1;
1094+
10221095
rds_ib_set_protocol(conn, RDS_PROTOCOL_4_1);
10231096
ic->i_flowctl = rds_ib_sysctl_flow_control; /* advertise flow control */
10241097
/* Use ic->i_flowctl as the first post credit to enable

0 commit comments

Comments
 (0)