From ef278157f938011ee08fb683311e5e31ffd29fdf Mon Sep 17 00:00:00 2001 From: Avinash Repaka Date: Mon, 29 Feb 2016 15:30:57 -0800 Subject: [PATCH] RDS: Make message size limit compliant with spec This patch limits RDS messages(both RDMA & non-RDMA) and RDS MR size to RDS_MAX_MSG_SIZE(1MB) irrespective of underlying transport layer. Orabug: 22661521 Signed-off-by: Santosh Shilimkar Signed-off-by: Avinash Repaka Acked-by: Ajaykumar Hotchandani --- net/rds/rdma.c | 5 +++++ net/rds/rds.h | 3 +++ net/rds/send.c | 27 ++++++++++++++++++++------- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/net/rds/rdma.c b/net/rds/rdma.c index e49d4b1cc8f4..c1de2be806f6 100644 --- a/net/rds/rdma.c +++ b/net/rds/rdma.c @@ -200,6 +200,11 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args, goto out; } + if ((nr_pages << PAGE_SHIFT) > RDS_MAX_MSG_SIZE) { + ret = -EMSGSIZE; + goto out; + } + rdsdebug("RDS: get_mr addr %llx len %llu nr_pages %u\n", args->vec.addr, args->vec.bytes, nr_pages); diff --git a/net/rds/rds.h b/net/rds/rds.h index 8810398e2472..981775b1a050 100644 --- a/net/rds/rds.h +++ b/net/rds/rds.h @@ -59,6 +59,9 @@ rdsdebug(char *fmt, ...) #define RDS_FRAG_SIZE ((unsigned int)(1 << RDS_FRAG_SHIFT)) #define RDS_MAX_FRAG_SIZE SZ_16K +/* 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_PAGE_SIZE (1UL << 12) #define RDS_CONG_MAP_LONGS (RDS_CONG_MAP_BYTES / sizeof(unsigned long)) diff --git a/net/rds/send.c b/net/rds/send.c index 5bc6400ae368..e033397cac29 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -1159,20 +1159,25 @@ static int rds_cmsg_send(struct rds_sock *rs, struct rds_message *rm, return ret; } -static inline unsigned int rds_rdma_bytes(struct msghdr *msg) +static inline int rds_rdma_bytes(struct msghdr *msg, size_t *rdma_bytes) { struct rds_rdma_args *args; struct cmsghdr *cmsg; - unsigned int rdma_bytes = 0; 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; + *rdma_bytes += args->remote_vec.bytes; } } - return rdma_bytes; + return 0; } int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len) @@ -1188,7 +1193,7 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len) int queued = 0, allocated_mr = 0; int nonblock = msg->msg_flags & MSG_DONTWAIT; long timeo = sock_sndtimeo(sk, nonblock); - size_t total_payload_len = payload_len; + 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 */ @@ -1222,6 +1227,15 @@ 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; + + 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; @@ -1252,8 +1266,7 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len) /* For RDMA operation(s), add up rmda bytes to payload to make * sure its within system QoS threshold limits. */ - if (rm->rdma.op_active) - total_payload_len += rds_rdma_bytes(msg); + total_payload_len += rdma_payload_len; if (rds_check_qos_threshold(rs->rs_tos, total_payload_len)) { ret = -EINVAL; -- 2.50.1