)]}'
{
  "commit": "5924f17a8a30c2ae18d034a86ee7581b34accef6",
  "tree": "1585360d36e33afab81a9cbf3edd732046a9263a",
  "parents": [
    "5925a0555bdaf0b396a84318cbc21ba085f6c0d3"
  ],
  "author": {
    "name": "Christoph Paasch",
    "email": "christoph.paasch@uclouvain.be",
    "time": "Sat Jun 28 18:26:37 2014 +0200"
  },
  "committer": {
    "name": "David S. Miller",
    "email": "davem@davemloft.net",
    "time": "Wed Jul 02 18:21:03 2014 -0700"
  },
  "message": "tcp: Fix divide by zero when pushing during tcp-repair\n\nWhen in repair-mode and TCP_RECV_QUEUE is set, we end up calling\ntcp_push with mss_now being 0. If data is in the send-queue and\ntcp_set_skb_tso_segs gets called, we crash because it will divide by\nmss_now:\n\n[  347.151939] divide error: 0000 [#1] SMP\n[  347.152907] Modules linked in:\n[  347.152907] CPU: 1 PID: 1123 Comm: packetdrill Not tainted 3.16.0-rc2 #4\n[  347.152907] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2007\n[  347.152907] task: f5b88540 ti: f3c82000 task.ti: f3c82000\n[  347.152907] EIP: 0060:[\u003cc1601359\u003e] EFLAGS: 00210246 CPU: 1\n[  347.152907] EIP is at tcp_set_skb_tso_segs+0x49/0xa0\n[  347.152907] EAX: 00000b67 EBX: f5acd080 ECX: 00000000 EDX: 00000000\n[  347.152907] ESI: f5a28f40 EDI: f3c88f00 EBP: f3c83d10 ESP: f3c83d00\n[  347.152907]  DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068\n[  347.152907] CR0: 80050033 CR2: 083158b0 CR3: 35146000 CR4: 000006b0\n[  347.152907] Stack:\n[  347.152907]  c167f9d9 f5acd080 000005b4 00000002 f3c83d20 c16013e6 f3c88f00 f5acd080\n[  347.152907]  f3c83da0 c1603b5a f3c83d38 c10a0188 00000000 00000000 f3c83d84 c10acc85\n[  347.152907]  c1ad5ec0 00000000 00000000 c1ad679c 010003e0 00000000 00000000 f3c88fc8\n[  347.152907] Call Trace:\n[  347.152907]  [\u003cc167f9d9\u003e] ? apic_timer_interrupt+0x2d/0x34\n[  347.152907]  [\u003cc16013e6\u003e] tcp_init_tso_segs+0x36/0x50\n[  347.152907]  [\u003cc1603b5a\u003e] tcp_write_xmit+0x7a/0xbf0\n[  347.152907]  [\u003cc10a0188\u003e] ? up+0x28/0x40\n[  347.152907]  [\u003cc10acc85\u003e] ? console_unlock+0x295/0x480\n[  347.152907]  [\u003cc10ad24f\u003e] ? vprintk_emit+0x1ef/0x4b0\n[  347.152907]  [\u003cc1605716\u003e] __tcp_push_pending_frames+0x36/0xd0\n[  347.152907]  [\u003cc15f4860\u003e] tcp_push+0xf0/0x120\n[  347.152907]  [\u003cc15f7641\u003e] tcp_sendmsg+0xf1/0xbf0\n[  347.152907]  [\u003cc116d920\u003e] ? kmem_cache_free+0xf0/0x120\n[  347.152907]  [\u003cc106a682\u003e] ? __sigqueue_free+0x32/0x40\n[  347.152907]  [\u003cc106a682\u003e] ? __sigqueue_free+0x32/0x40\n[  347.152907]  [\u003cc114f0f0\u003e] ? do_wp_page+0x3e0/0x850\n[  347.152907]  [\u003cc161c36a\u003e] inet_sendmsg+0x4a/0xb0\n[  347.152907]  [\u003cc1150269\u003e] ? handle_mm_fault+0x709/0xfb0\n[  347.152907]  [\u003cc15a006b\u003e] sock_aio_write+0xbb/0xd0\n[  347.152907]  [\u003cc1180b79\u003e] do_sync_write+0x69/0xa0\n[  347.152907]  [\u003cc1181023\u003e] vfs_write+0x123/0x160\n[  347.152907]  [\u003cc1181d55\u003e] SyS_write+0x55/0xb0\n[  347.152907]  [\u003cc167f0d8\u003e] sysenter_do_call+0x12/0x28\n\nThis can easily be reproduced with the following packetdrill-script (the\n\"magic\" with netem, sk_pacing and limit_output_bytes is done to prevent\nthe kernel from pushing all segments, because hitting the limit without\ndoing this is not so easy with packetdrill):\n\n0   socket(..., SOCK_STREAM, IPPROTO_TCP) \u003d 3\n+0  setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) \u003d 0\n\n+0  bind(3, ..., ...) \u003d 0\n+0  listen(3, 1) \u003d 0\n\n+0  \u003c S 0:0(0) win 32792 \u003cmss 1460\u003e\n+0  \u003e S. 0:0(0) ack 1 \u003cmss 1460\u003e\n+0.1  \u003c . 1:1(0) ack 1 win 65000\n\n+0  accept(3, ..., ...) \u003d 4\n\n// This forces that not all segments of the snd-queue will be pushed\n+0 `tc qdisc add dev tun0 root netem delay 10ms`\n+0 `sysctl -w net.ipv4.tcp_limit_output_bytes\u003d2`\n+0 setsockopt(4, SOL_SOCKET, 47, [2], 4) \u003d 0\n\n+0 write(4,...,10000) \u003d 10000\n+0 write(4,...,10000) \u003d 10000\n\n// Set tcp-repair stuff, particularly TCP_RECV_QUEUE\n+0 setsockopt(4, SOL_TCP, 19, [1], 4) \u003d 0\n+0 setsockopt(4, SOL_TCP, 20, [1], 4) \u003d 0\n\n// This now will make the write push the remaining segments\n+0 setsockopt(4, SOL_SOCKET, 47, [20000], 4) \u003d 0\n+0 `sysctl -w net.ipv4.tcp_limit_output_bytes\u003d130000`\n\n// Now we will crash\n+0 write(4,...,1000) \u003d 1000\n\nThis happens since ec3423257508 (tcp: fix retransmission in repair\nmode). Prior to that, the call to tcp_push was prevented by a check for\ntp-\u003erepair.\n\nThe patch fixes it, by adding the new goto-label out_nopush. When exiting\ntcp_sendmsg and a push is not required, which is the case for tp-\u003erepair,\nwe go to this label.\n\nWhen repairing and calling send() with TCP_RECV_QUEUE, the data is\nactually put in the receive-queue. So, no push is required because no\ndata has been added to the send-queue.\n\nCc: Andrew Vagin \u003cavagin@openvz.org\u003e\nCc: Pavel Emelyanov \u003cxemul@parallels.com\u003e\nFixes: ec3423257508 (tcp: fix retransmission in repair mode)\nSigned-off-by: Christoph Paasch \u003cchristoph.paasch@uclouvain.be\u003e\nAcked-by: Andrew Vagin \u003cavagin@openvz.org\u003e\nAcked-by: Pavel Emelyanov \u003cxemul@parallels.com\u003e\nSigned-off-by: David S. Miller \u003cdavem@davemloft.net\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "eb1dde37e678f6bb1570bfb452c019b88eb1a76c",
      "old_mode": 33188,
      "old_path": "net/ipv4/tcp.c",
      "new_id": "9d2118e5fbc79359e205c41b4802402d79b580f6",
      "new_mode": 33188,
      "new_path": "net/ipv4/tcp.c"
    }
  ]
}
