aboutsummaryrefslogtreecommitdiffstats
path: root/net/rds/send.c
diff options
context:
space:
mode:
authorAndy Grover <andy.grover@oracle.com>2010-04-13 15:00:35 -0400
committerAndy Grover <andy.grover@oracle.com>2010-09-08 21:12:07 -0400
commitaa0a4ef4ac3a3c5ffa35e32520bfbc0922ef3630 (patch)
tree13b078f08c9411e3f8f7052c79add9db228a00b6 /net/rds/send.c
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>
Diffstat (limited to 'net/rds/send.c')
-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 38567f3ee7e8..69ab1040d02d 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)
846{ 846{
847 struct cmsghdr *cmsg; 847 struct cmsghdr *cmsg;
848 int size = 0; 848 int size = 0;
849 int cmsg_groups = 0;
849 int retval; 850 int retval;
850 851
851 for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { 852 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)
857 858
858 switch (cmsg->cmsg_type) { 859 switch (cmsg->cmsg_type) {
859 case RDS_CMSG_RDMA_ARGS: 860 case RDS_CMSG_RDMA_ARGS:
861 cmsg_groups |= 1;
860 retval = rds_rdma_extra_size(CMSG_DATA(cmsg)); 862 retval = rds_rdma_extra_size(CMSG_DATA(cmsg));
861 if (retval < 0) 863 if (retval < 0)
862 return retval; 864 return retval;
863 size += retval; 865 size += retval;
866
864 break; 867 break;
865 868
866 case RDS_CMSG_RDMA_DEST: 869 case RDS_CMSG_RDMA_DEST:
867 case RDS_CMSG_RDMA_MAP: 870 case RDS_CMSG_RDMA_MAP:
871 cmsg_groups |= 2;
868 /* these are valid but do no add any size */ 872 /* these are valid but do no add any size */
869 break; 873 break;
870 874
871 case RDS_CMSG_ATOMIC_CSWP: 875 case RDS_CMSG_ATOMIC_CSWP:
872 case RDS_CMSG_ATOMIC_FADD: 876 case RDS_CMSG_ATOMIC_FADD:
877 cmsg_groups |= 1;
873 size += sizeof(struct scatterlist); 878 size += sizeof(struct scatterlist);
874 break; 879 break;
875 880
@@ -881,6 +886,10 @@ static int rds_rm_size(struct msghdr *msg, int data_len)
881 886
882 size += ceil(data_len, PAGE_SIZE) * sizeof(struct scatterlist); 887 size += ceil(data_len, PAGE_SIZE) * sizeof(struct scatterlist);
883 888
889 /* Ensure (DEST, MAP) are never used with (ARGS, ATOMIC) */
890 if (cmsg_groups == 3)
891 return -EINVAL;
892
884 return size; 893 return size;
885} 894}
886 895