Skip to content

Commit d139ff0

Browse files
Andy Groverdavem330
Andy Grover
authored andcommitted
RDS: Let rds_message_alloc_sgs() return NULL
Even with the previous fix, we still are reading the iovecs once to determine SGs needed, and then again later on. Preallocating space for sg lists as part of rds_message seemed like a good idea but it might be better to not do this. While working to redo that code, this patch attempts to protect against userspace rewriting the rds_iovec array between the first and second accesses. The consequences of this would be either a too-small or too-large sg list array. Too large is not an issue. This patch changes all callers of message_alloc_sgs to handle running out of preallocated sgs, and fail gracefully. Signed-off-by: Andy Grover <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent fc8162e commit d139ff0

File tree

3 files changed

+17
-0
lines changed

3 files changed

+17
-0
lines changed

net/rds/message.c

+5
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,9 @@ struct scatterlist *rds_message_alloc_sgs(struct rds_message *rm, int nents)
224224
WARN_ON(rm->m_used_sgs + nents > rm->m_total_sgs);
225225
WARN_ON(!nents);
226226

227+
if (rm->m_used_sgs + nents > rm->m_total_sgs)
228+
return NULL;
229+
227230
sg_ret = &sg_first[rm->m_used_sgs];
228231
sg_init_table(sg_ret, nents);
229232
rm->m_used_sgs += nents;
@@ -246,6 +249,8 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in
246249
rm->m_inc.i_hdr.h_len = cpu_to_be32(total_len);
247250
rm->data.op_nents = ceil(total_len, PAGE_SIZE);
248251
rm->data.op_sg = rds_message_alloc_sgs(rm, num_sgs);
252+
if (!rm->data.op_sg)
253+
return ERR_PTR(-ENOMEM);
249254

250255
for (i = 0; i < rm->data.op_nents; ++i) {
251256
sg_set_page(&rm->data.op_sg[i],

net/rds/rdma.c

+8
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,10 @@ int rds_cmsg_rdma_args(struct rds_sock *rs, struct rds_message *rm,
607607
op->op_recverr = rs->rs_recverr;
608608
WARN_ON(!nr_pages);
609609
op->op_sg = rds_message_alloc_sgs(rm, nr_pages);
610+
if (!op->op_sg) {
611+
ret = -ENOMEM;
612+
goto out;
613+
}
610614

611615
if (op->op_notify || op->op_recverr) {
612616
/* We allocate an uninitialized notifier here, because
@@ -807,6 +811,10 @@ int rds_cmsg_atomic(struct rds_sock *rs, struct rds_message *rm,
807811
rm->atomic.op_active = 1;
808812
rm->atomic.op_recverr = rs->rs_recverr;
809813
rm->atomic.op_sg = rds_message_alloc_sgs(rm, 1);
814+
if (!rm->atomic.op_sg) {
815+
ret = -ENOMEM;
816+
goto err;
817+
}
810818

811819
/* verify 8 byte-aligned */
812820
if (args->local_addr & 0x7) {

net/rds/send.c

+4
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,10 @@ int rds_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
973973
/* Attach data to the rm */
974974
if (payload_len) {
975975
rm->data.op_sg = rds_message_alloc_sgs(rm, ceil(payload_len, PAGE_SIZE));
976+
if (!rm->data.op_sg) {
977+
ret = -ENOMEM;
978+
goto out;
979+
}
976980
ret = rds_message_copy_from_user(rm, msg->msg_iov, payload_len);
977981
if (ret)
978982
goto out;

0 commit comments

Comments
 (0)