diff options
author | WANG Cong <xiyou.wangcong@gmail.com> | 2017-02-07 15:59:47 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-02-26 05:10:50 -0500 |
commit | 1409935400aa1faffd9fe1830adb8ea08ea424d2 (patch) | |
tree | 65203f23bd7df21cbe4d5df5353de482c3896b05 | |
parent | ae7d43192ff29ca68706948362acbc3a6da7408f (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.c | 40 |
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 | ||
950 | start: | 952 | start: |
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; |