mirror of
https://github.com/torvalds/linux.git
synced 2024-12-31 23:31:29 +00:00
RDS: make message size limit compliant with spec
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 <avinash.repaka@oracle.com> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
This commit is contained in:
parent
192a798f52
commit
f9fb69adb6
@ -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?
|
||||
*/
|
||||
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
@ -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 */
|
||||
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user