aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWANG Cong <xiyou.wangcong@gmail.com>2017-02-07 15:59:47 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-02-26 05:10:50 -0500
commit1409935400aa1faffd9fe1830adb8ea08ea424d2 (patch)
tree65203f23bd7df21cbe4d5df5353de482c3896b05
parentae7d43192ff29ca68706948362acbc3a6da7408f (diff)
kcm: fix 0-length case for kcm_sendmsg()
[ Upstream commit 98e3862ca2b1ae595a13805dcab4c3a6d7718f4d ] Dmitry reported a kernel warning: WARNING: CPU: 3 PID: 2936 at net/kcm/kcmsock.c:627 kcm_write_msgs+0x12e3/0x1b90 net/kcm/kcmsock.c:627 CPU: 3 PID: 2936 Comm: a.out Not tainted 4.10.0-rc6+ #209 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:15 [inline] dump_stack+0x2ee/0x3ef lib/dump_stack.c:51 panic+0x1fb/0x412 kernel/panic.c:179 __warn+0x1c4/0x1e0 kernel/panic.c:539 warn_slowpath_null+0x2c/0x40 kernel/panic.c:582 kcm_write_msgs+0x12e3/0x1b90 net/kcm/kcmsock.c:627 kcm_sendmsg+0x163a/0x2200 net/kcm/kcmsock.c:1029 sock_sendmsg_nosec net/socket.c:635 [inline] sock_sendmsg+0xca/0x110 net/socket.c:645 sock_write_iter+0x326/0x600 net/socket.c:848 new_sync_write fs/read_write.c:499 [inline] __vfs_write+0x483/0x740 fs/read_write.c:512 vfs_write+0x187/0x530 fs/read_write.c:560 SYSC_write fs/read_write.c:607 [inline] SyS_write+0xfb/0x230 fs/read_write.c:599 entry_SYSCALL_64_fastpath+0x1f/0xc2 when calling syscall(__NR_write, sock2, 0x208aaf27ul, 0x0ul) on a KCM seqpacket socket. It appears that kcm_sendmsg() does not handle len==0 case correctly, which causes an empty skb is allocated and queued. Fix this by skipping the skb allocation for len==0 case. Reported-by: Dmitry Vyukov <dvyukov@google.com> Cc: Tom Herbert <tom@herbertland.com> Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--net/kcm/kcmsock.c40
1 files changed, 22 insertions, 18 deletions
diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c
index 7e08a4d3d77d..64f0e8531af0 100644
--- a/net/kcm/kcmsock.c
+++ b/net/kcm/kcmsock.c
@@ -929,23 +929,25 @@ static int kcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
929 goto out_error; 929 goto out_error;
930 } 930 }
931 931
932 /* New message, alloc head skb */ 932 if (msg_data_left(msg)) {
933 head = alloc_skb(0, sk->sk_allocation); 933 /* New message, alloc head skb */
934 while (!head) {
935 kcm_push(kcm);
936 err = sk_stream_wait_memory(sk, &timeo);
937 if (err)
938 goto out_error;
939
940 head = alloc_skb(0, sk->sk_allocation); 934 head = alloc_skb(0, sk->sk_allocation);
941 } 935 while (!head) {
936 kcm_push(kcm);
937 err = sk_stream_wait_memory(sk, &timeo);
938 if (err)
939 goto out_error;
942 940
943 skb = head; 941 head = alloc_skb(0, sk->sk_allocation);
942 }
944 943
945 /* Set ip_summed to CHECKSUM_UNNECESSARY to avoid calling 944 skb = head;
946 * csum_and_copy_from_iter from skb_do_copy_data_nocache. 945
947 */ 946 /* Set ip_summed to CHECKSUM_UNNECESSARY to avoid calling
948 skb->ip_summed = CHECKSUM_UNNECESSARY; 947 * csum_and_copy_from_iter from skb_do_copy_data_nocache.
948 */
949 skb->ip_summed = CHECKSUM_UNNECESSARY;
950 }
949 951
950start: 952start:
951 while (msg_data_left(msg)) { 953 while (msg_data_left(msg)) {
@@ -1018,10 +1020,12 @@ wait_for_memory:
1018 if (eor) { 1020 if (eor) {
1019 bool not_busy = skb_queue_empty(&sk->sk_write_queue); 1021 bool not_busy = skb_queue_empty(&sk->sk_write_queue);
1020 1022
1021 /* Message complete, queue it on send buffer */ 1023 if (head) {
1022 __skb_queue_tail(&sk->sk_write_queue, head); 1024 /* Message complete, queue it on send buffer */
1023 kcm->seq_skb = NULL; 1025 __skb_queue_tail(&sk->sk_write_queue, head);
1024 KCM_STATS_INCR(kcm->stats.tx_msgs); 1026 kcm->seq_skb = NULL;
1027 KCM_STATS_INCR(kcm->stats.tx_msgs);
1028 }
1025 1029
1026 if (msg->msg_flags & MSG_BATCH) { 1030 if (msg->msg_flags & MSG_BATCH) {
1027 kcm->tx_wait_more = true; 1031 kcm->tx_wait_more = true;