Signed-off-by: Dan Smith <danms@xxxxxxxxxx> --- net/unix/checkpoint.c | 54 ++++++++++++++++++++++++++---------------------- 1 files changed, 29 insertions(+), 25 deletions(-) diff --git a/net/unix/checkpoint.c b/net/unix/checkpoint.c index 749673d..c6a1b27 100644 --- a/net/unix/checkpoint.c +++ b/net/unix/checkpoint.c @@ -201,7 +201,6 @@ static int sock_read_buffer_sendmsg(struct ckpt_ctx *ctx, uint8_t peer_shutdown = 0; void *buf = NULL; int sndbuf; - int len; int ret = 0; memset(&msg, 0, sizeof(msg)); @@ -210,14 +209,30 @@ static int sock_read_buffer_sendmsg(struct ckpt_ctx *ctx, if (IS_ERR(h)) return PTR_ERR(h); - len = _ckpt_read_obj_type(ctx, NULL, 0, CKPT_HDR_BUFFER); - if (len < 0) { - ret = len; + if (h->lin_len > SKB_MAX_ALLOC) { + ckpt_debug("socket buffer too big (%u > %lu)\n", + h->lin_len, SKB_MAX_ALLOC); + ret = -EINVAL; + goto out; + } else if (h->nr_frags != 0) { + ckpt_debug("unix socket claims to have fragments\n"); + ret = -EINVAL; goto out; - } else if (len > SKB_MAX_ALLOC) { - ckpt_debug("Socket buffer too big (%i > %lu)", - len, SKB_MAX_ALLOC); - ret = -ENOSPC; + } + + buf = kmalloc(h->lin_len, GFP_KERNEL); + if (!buf) { + ret = -ENOMEM; + goto out; + } + + kvec.iov_len = h->lin_len; + kvec.iov_base = buf; + ret = _ckpt_read_obj_type(ctx, kvec.iov_base, + h->lin_len, CKPT_HDR_BUFFER); + ckpt_debug("read unix socket buffer %u: %i\n", h->lin_len, ret); + if (ret < h->lin_len) { + ret = -EINVAL; goto out; } @@ -246,18 +261,6 @@ static int sock_read_buffer_sendmsg(struct ckpt_ctx *ctx, } } - kvec.iov_len = len; - buf = kmalloc(len, GFP_KERNEL); - kvec.iov_base = buf; - if (!buf) { - ret = -ENOMEM; - goto out; - } - - ret = ckpt_kread(ctx, kvec.iov_base, len); - if (ret < 0) - goto out; - msg.msg_name = addr; msg.msg_namelen = addrlen; @@ -273,15 +276,16 @@ static int sock_read_buffer_sendmsg(struct ckpt_ctx *ctx, /* Make sure there's room in the send buffer */ sndbuf = sk->sk_sndbuf; - if (((sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc)) < len) && + if (((sk->sk_sndbuf - atomic_read(&sk->sk_wmem_alloc)) < h->lin_len) && capable(CAP_NET_ADMIN)) - sk->sk_sndbuf += len; + sk->sk_sndbuf += h->lin_len; else sk->sk_sndbuf = sysctl_wmem_max; - ret = kernel_sendmsg(sk->sk_socket, &msg, &kvec, 1, len); - ckpt_debug("kernel_sendmsg(%i,%i): %i\n", h->sk_objref, len, ret); - if ((ret > 0) && (ret != len)) + ret = kernel_sendmsg(sk->sk_socket, &msg, &kvec, 1, h->lin_len); + ckpt_debug("kernel_sendmsg(%i,%u): %i\n", + h->sk_objref, h->lin_len, ret); + if ((ret > 0) && (ret != h->lin_len)) ret = -ENOMEM; sk->sk_sndbuf = sndbuf; -- 1.6.2.5 _______________________________________________ Containers mailing list Containers@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linux-foundation.org/mailman/listinfo/containers