Skip to content

Commit

Permalink
RDS: make message size limit compliant with spec
Browse files Browse the repository at this point in the history
RDS support max message size as 1M but the code doesn't check this
in all cases. Patch fixes it for RDMA & non-RDMA and RDS MR size
and its enforced irrespective of underlying transport.

Signed-off-by: Avinash Repaka <[email protected]>
Signed-off-by: Santosh Shilimkar <[email protected]>
  • Loading branch information
Avinash Repaka authored and SantoshShilimkar committed Jan 2, 2017
1 parent 192a798 commit f9fb69a
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 1 deletion.
9 changes: 8 additions & 1 deletion net/rds/rdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@
/*
* XXX
* - build with sparse
* - should we limit the size of a mr region? let transport return failure?
* - should we detect duplicate keys on a socket? hmm.
* - an rdma is an mlock, apply rlimit?
*/
Expand Down Expand Up @@ -200,6 +199,14 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
goto out;
}

/* Restrict the size of mr irrespective of underlying transport
* To account for unaligned mr regions, subtract one from nr_pages
*/
if ((nr_pages - 1) > (RDS_MAX_MSG_SIZE >> PAGE_SHIFT)) {
ret = -EMSGSIZE;
goto out;
}

rdsdebug("RDS: get_mr addr %llx len %llu nr_pages %u\n",
args->vec.addr, args->vec.bytes, nr_pages);

Expand Down
3 changes: 3 additions & 0 deletions net/rds/rds.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ void rdsdebug(char *fmt, ...)
#define RDS_FRAG_SHIFT 12
#define RDS_FRAG_SIZE ((unsigned int)(1 << RDS_FRAG_SHIFT))

/* Used to limit both RDMA and non-RDMA RDS message to 1MB */
#define RDS_MAX_MSG_SIZE ((unsigned int)(1 << 20))

#define RDS_CONG_MAP_BYTES (65536 / 8)
#define RDS_CONG_MAP_PAGES (PAGE_ALIGN(RDS_CONG_MAP_BYTES) / PAGE_SIZE)
#define RDS_CONG_MAP_PAGE_BITS (PAGE_SIZE * 8)
Expand Down
31 changes: 31 additions & 0 deletions net/rds/send.c
Original file line number Diff line number Diff line change
Expand Up @@ -994,6 +994,26 @@ static int rds_send_mprds_hash(struct rds_sock *rs, struct rds_connection *conn)
return hash;
}

static int rds_rdma_bytes(struct msghdr *msg, size_t *rdma_bytes)
{
struct rds_rdma_args *args;
struct cmsghdr *cmsg;

for_each_cmsghdr(cmsg, msg) {
if (!CMSG_OK(msg, cmsg))
return -EINVAL;

if (cmsg->cmsg_level != SOL_RDS)
continue;

if (cmsg->cmsg_type == RDS_CMSG_RDMA_ARGS) {
args = CMSG_DATA(cmsg);
*rdma_bytes += args->remote_vec.bytes;
}
}
return 0;
}

int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
{
struct sock *sk = sock->sk;
Expand All @@ -1008,6 +1028,7 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
int nonblock = msg->msg_flags & MSG_DONTWAIT;
long timeo = sock_sndtimeo(sk, nonblock);
struct rds_conn_path *cpath;
size_t total_payload_len = payload_len, rdma_payload_len = 0;

/* Mirror Linux UDP mirror of BSD error message compatibility */
/* XXX: Perhaps MSG_MORE someday */
Expand Down Expand Up @@ -1040,6 +1061,16 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
}
release_sock(sk);

ret = rds_rdma_bytes(msg, &rdma_payload_len);
if (ret)
goto out;

total_payload_len += rdma_payload_len;
if (max_t(size_t, payload_len, rdma_payload_len) > RDS_MAX_MSG_SIZE) {
ret = -EMSGSIZE;
goto out;
}

if (payload_len > rds_sk_sndbuf(rs)) {
ret = -EMSGSIZE;
goto out;
Expand Down

0 comments on commit f9fb69a

Please sign in to comment.