aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Grover <andy.grover@oracle.com>2010-04-13 12:00:35 -0700
committerAndy Grover <andy.grover@oracle.com>2010-09-08 18:12:07 -0700
commitaa0a4ef4ac3a3c5ffa35e32520bfbc0922ef3630 (patch)
tree13b078f08c9411e3f8f7052c79add9db228a00b6
parent2c3a5f9abb1dc5efdab8ba9a568b1661c65fd1e3 (diff)
RDS: Make sure cmsgs aren't used in improper ways
It hasn't cropped up in the field, but this code ensures it is impossible to issue operations that pass an rdma cookie (DEST, MAP) in the same sendmsg call that's actually initiating rdma or atomic ops. Disallowing this perverse-but-technically-allowed usage makes silent RDMA heuristics slightly easier. Signed-off-by: Andy Grover <andy.grover@oracle.com>
-rw-r--r--net/rds/send.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/net/rds/send.c b/net/rds/send.c
index 38567f3ee7e..69ab1040d02 100644
--- a/net/rds/send.c
+++ b/net/rds/send.c
@@ -846,6 +846,7 @@ static int rds_rm_size(struct msghdr *msg, int data_len)
{
struct cmsghdr *cmsg;
int size = 0;
+ int cmsg_groups = 0;
int retval;
for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
@@ -857,19 +858,23 @@ static int rds_rm_size(struct msghdr *msg, int data_len)
switch (cmsg->cmsg_type) {
case RDS_CMSG_RDMA_ARGS:
+ cmsg_groups |= 1;
retval = rds_rdma_extra_size(CMSG_DATA(cmsg));
if (retval < 0)
return retval;
size += retval;
+
break;
case RDS_CMSG_RDMA_DEST:
case RDS_CMSG_RDMA_MAP:
+ cmsg_groups |= 2;
/* these are valid but do no add any size */
break;
case RDS_CMSG_ATOMIC_CSWP:
case RDS_CMSG_ATOMIC_FADD:
+ cmsg_groups |= 1;
size += sizeof(struct scatterlist);
break;
@@ -881,6 +886,10 @@ static int rds_rm_size(struct msghdr *msg, int data_len)
size += ceil(data_len, PAGE_SIZE) * sizeof(struct scatterlist);
+ /* Ensure (DEST, MAP) are never used with (ARGS, ATOMIC) */
+ if (cmsg_groups == 3)
+ return -EINVAL;
+
return size;
}