<feed xmlns='http://www.w3.org/2005/Atom'>
<title>kernel/linux.git/drivers/net/slip, branch v4.19.112</title>
<subtitle>Linux kernel stable tree (mirror)</subtitle>
<id>https://git.radix-linux.su/kernel/linux.git/atom?h=v4.19.112</id>
<link rel='self' href='https://git.radix-linux.su/kernel/linux.git/atom?h=v4.19.112'/>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/'/>
<updated>2020-03-20T10:55:54+00:00</updated>
<entry>
<title>slip: not call free_netdev before rtnl_unlock in slip_open</title>
<updated>2020-03-20T10:55:54+00:00</updated>
<author>
<name>yangerkun</name>
<email>yangerkun@huawei.com</email>
</author>
<published>2020-02-26T03:54:35+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=851346e59122de504f185d83cd9315a4170f1fc5'/>
<id>urn:sha1:851346e59122de504f185d83cd9315a4170f1fc5</id>
<content type='text'>
[ Upstream commit f596c87005f7b1baeb7d62d9a9e25d68c3dfae10 ]

As the description before netdev_run_todo, we cannot call free_netdev
before rtnl_unlock, fix it by reorder the code.

Signed-off-by: yangerkun &lt;yangerkun@huawei.com&gt;
Reviewed-by: Oliver Hartkopp &lt;socketcan@hartkopp.net&gt;
Signed-off-by: David S. Miller &lt;davem@davemloft.net&gt;
Signed-off-by: Sasha Levin &lt;sashal@kernel.org&gt;
</content>
</entry>
<entry>
<title>slip: make slhc_compress() more robust against malicious packets</title>
<updated>2020-03-18T06:14:18+00:00</updated>
<author>
<name>Eric Dumazet</name>
<email>edumazet@google.com</email>
</author>
<published>2020-03-04T23:51:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=6a62f2dd47a7ec7ea4f638fa8c0acea086c2d3de'/>
<id>urn:sha1:6a62f2dd47a7ec7ea4f638fa8c0acea086c2d3de</id>
<content type='text'>
[ Upstream commit 110a40dfb708fe940a3f3704d470e431c368d256 ]

Before accessing various fields in IPV4 network header
and TCP header, make sure the packet :

- Has IP version 4 (ip-&gt;version == 4)
- Has not a silly network length (ip-&gt;ihl &gt;= 5)
- Is big enough to hold network and transport headers
- Has not a silly TCP header size (th-&gt;doff &gt;= sizeof(struct tcphdr) / 4)

syzbot reported :

BUG: KMSAN: uninit-value in slhc_compress+0x5b9/0x2e60 drivers/net/slip/slhc.c:270
CPU: 0 PID: 11728 Comm: syz-executor231 Not tainted 5.6.0-rc2-syzkaller #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Call Trace:
 __dump_stack lib/dump_stack.c:77 [inline]
 dump_stack+0x1c9/0x220 lib/dump_stack.c:118
 kmsan_report+0xf7/0x1e0 mm/kmsan/kmsan_report.c:118
 __msan_warning+0x58/0xa0 mm/kmsan/kmsan_instr.c:215
 slhc_compress+0x5b9/0x2e60 drivers/net/slip/slhc.c:270
 ppp_send_frame drivers/net/ppp/ppp_generic.c:1637 [inline]
 __ppp_xmit_process+0x1902/0x2970 drivers/net/ppp/ppp_generic.c:1495
 ppp_xmit_process+0x147/0x2f0 drivers/net/ppp/ppp_generic.c:1516
 ppp_write+0x6bb/0x790 drivers/net/ppp/ppp_generic.c:512
 do_loop_readv_writev fs/read_write.c:717 [inline]
 do_iter_write+0x812/0xdc0 fs/read_write.c:1000
 compat_writev+0x2df/0x5a0 fs/read_write.c:1351
 do_compat_pwritev64 fs/read_write.c:1400 [inline]
 __do_compat_sys_pwritev fs/read_write.c:1420 [inline]
 __se_compat_sys_pwritev fs/read_write.c:1414 [inline]
 __ia32_compat_sys_pwritev+0x349/0x3f0 fs/read_write.c:1414
 do_syscall_32_irqs_on arch/x86/entry/common.c:339 [inline]
 do_fast_syscall_32+0x3c7/0x6e0 arch/x86/entry/common.c:410
 entry_SYSENTER_compat+0x68/0x77 arch/x86/entry/entry_64_compat.S:139
RIP: 0023:0xf7f7cd99
Code: 90 e8 0b 00 00 00 f3 90 0f ae e8 eb f9 8d 74 26 00 89 3c 24 c3 90 90 90 90 90 90 90 90 90 90 90 90 51 52 55 89 e5 0f 34 cd 80 &lt;5d&gt; 5a 59 c3 90 90 90 90 eb 0d 90 90 90 90 90 90 90 90 90 90 90 90
RSP: 002b:00000000ffdb84ac EFLAGS: 00000217 ORIG_RAX: 000000000000014e
RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00000000200001c0
RDX: 0000000000000001 RSI: 0000000000000000 RDI: 0000000000000003
RBP: 0000000040047459 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000

Uninit was created at:
 kmsan_save_stack_with_flags mm/kmsan/kmsan.c:144 [inline]
 kmsan_internal_poison_shadow+0x66/0xd0 mm/kmsan/kmsan.c:127
 kmsan_slab_alloc+0x8a/0xe0 mm/kmsan/kmsan_hooks.c:82
 slab_alloc_node mm/slub.c:2793 [inline]
 __kmalloc_node_track_caller+0xb40/0x1200 mm/slub.c:4401
 __kmalloc_reserve net/core/skbuff.c:142 [inline]
 __alloc_skb+0x2fd/0xac0 net/core/skbuff.c:210
 alloc_skb include/linux/skbuff.h:1051 [inline]
 ppp_write+0x115/0x790 drivers/net/ppp/ppp_generic.c:500
 do_loop_readv_writev fs/read_write.c:717 [inline]
 do_iter_write+0x812/0xdc0 fs/read_write.c:1000
 compat_writev+0x2df/0x5a0 fs/read_write.c:1351
 do_compat_pwritev64 fs/read_write.c:1400 [inline]
 __do_compat_sys_pwritev fs/read_write.c:1420 [inline]
 __se_compat_sys_pwritev fs/read_write.c:1414 [inline]
 __ia32_compat_sys_pwritev+0x349/0x3f0 fs/read_write.c:1414
 do_syscall_32_irqs_on arch/x86/entry/common.c:339 [inline]
 do_fast_syscall_32+0x3c7/0x6e0 arch/x86/entry/common.c:410
 entry_SYSENTER_compat+0x68/0x77 arch/x86/entry/entry_64_compat.S:139

Fixes: b5451d783ade ("slip: Move the SLIP drivers")
Signed-off-by: Eric Dumazet &lt;edumazet@google.com&gt;
Reported-by: syzbot &lt;syzkaller@googlegroups.com&gt;
Signed-off-by: David S. Miller &lt;davem@davemloft.net&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
</entry>
<entry>
<title>can, slip: Protect tty-&gt;disc_data in write_wakeup and close with RCU</title>
<updated>2020-01-29T15:43:14+00:00</updated>
<author>
<name>Richard Palethorpe</name>
<email>rpalethorpe@suse.com</email>
</author>
<published>2020-01-21T13:42:58+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=bd1448458c6a67782d4e82c181b5540b5727546b'/>
<id>urn:sha1:bd1448458c6a67782d4e82c181b5540b5727546b</id>
<content type='text'>
[ Upstream commit 0ace17d56824165c7f4c68785d6b58971db954dd ]

write_wakeup can happen in parallel with close/hangup where tty-&gt;disc_data
is set to NULL and the netdevice is freed thus also freeing
disc_data. write_wakeup accesses disc_data so we must prevent close from
freeing the netdev while write_wakeup has a non-NULL view of
tty-&gt;disc_data.

We also need to make sure that accesses to disc_data are atomic. Which can
all be done with RCU.

This problem was found by Syzkaller on SLCAN, but the same issue is
reproducible with the SLIP line discipline using an LTP test based on the
Syzkaller reproducer.

A fix which didn't use RCU was posted by Hillf Danton.

Fixes: 661f7fda21b1 ("slip: Fix deadlock in write_wakeup")
Fixes: a8e83b17536a ("slcan: Port write_wakeup deadlock fix from slip")
Reported-by: syzbot+017e491ae13c0068598a@syzkaller.appspotmail.com
Signed-off-by: Richard Palethorpe &lt;rpalethorpe@suse.com&gt;
Cc: Wolfgang Grandegger &lt;wg@grandegger.com&gt;
Cc: Marc Kleine-Budde &lt;mkl@pengutronix.de&gt;
Cc: "David S. Miller" &lt;davem@davemloft.net&gt;
Cc: Tyler Hall &lt;tylerwhall@gmail.com&gt;
Cc: linux-can@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: syzkaller@googlegroups.com
Signed-off-by: David S. Miller &lt;davem@davemloft.net&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
</entry>
<entry>
<title>slip: Fix use-after-free Read in slip_open</title>
<updated>2019-12-05T08:21:30+00:00</updated>
<author>
<name>Jouni Hogander</name>
<email>jouni.hogander@unikie.com</email>
</author>
<published>2019-11-25T12:23:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=0c6e6ceae72c9bdb8834352190c6cafcd0b3c21d'/>
<id>urn:sha1:0c6e6ceae72c9bdb8834352190c6cafcd0b3c21d</id>
<content type='text'>
[ Upstream commit e58c1912418980f57ba2060017583067f5f71e52 ]

Slip_open doesn't clean-up device which registration failed from the
slip_devs device list. On next open after failure this list is iterated
and freed device is accessed. Fix this by calling sl_free_netdev in error
path.

Here is the trace from the Syzbot:

__dump_stack lib/dump_stack.c:77 [inline]
dump_stack+0x197/0x210 lib/dump_stack.c:118
print_address_description.constprop.0.cold+0xd4/0x30b mm/kasan/report.c:374
__kasan_report.cold+0x1b/0x41 mm/kasan/report.c:506
kasan_report+0x12/0x20 mm/kasan/common.c:634
__asan_report_load8_noabort+0x14/0x20 mm/kasan/generic_report.c:132
sl_sync drivers/net/slip/slip.c:725 [inline]
slip_open+0xecd/0x11b7 drivers/net/slip/slip.c:801
tty_ldisc_open.isra.0+0xa3/0x110 drivers/tty/tty_ldisc.c:469
tty_set_ldisc+0x30e/0x6b0 drivers/tty/tty_ldisc.c:596
tiocsetd drivers/tty/tty_io.c:2334 [inline]
tty_ioctl+0xe8d/0x14f0 drivers/tty/tty_io.c:2594
vfs_ioctl fs/ioctl.c:46 [inline]
file_ioctl fs/ioctl.c:509 [inline]
do_vfs_ioctl+0xdb6/0x13e0 fs/ioctl.c:696
ksys_ioctl+0xab/0xd0 fs/ioctl.c:713
__do_sys_ioctl fs/ioctl.c:720 [inline]
__se_sys_ioctl fs/ioctl.c:718 [inline]
__x64_sys_ioctl+0x73/0xb0 fs/ioctl.c:718
do_syscall_64+0xfa/0x760 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe

Fixes: 3b5a39979daf ("slip: Fix memory leak in slip_open error path")
Reported-by: syzbot+4d5170758f3762109542@syzkaller.appspotmail.com
Cc: David Miller &lt;davem@davemloft.net&gt;
Cc: Oliver Hartkopp &lt;socketcan@hartkopp.net&gt;
Cc: Lukas Bulwahn &lt;lukas.bulwahn@gmail.com&gt;
Signed-off-by: Jouni Hogander &lt;jouni.hogander@unikie.com&gt;
Signed-off-by: David S. Miller &lt;davem@davemloft.net&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
</entry>
<entry>
<title>slip: Fix memory leak in slip_open error path</title>
<updated>2019-11-20T17:45:12+00:00</updated>
<author>
<name>Jouni Hogander</name>
<email>jouni.hogander@unikie.com</email>
</author>
<published>2019-11-13T11:45:02+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=edc471038b4846b119d0b025f0336bf4b3e1ce23'/>
<id>urn:sha1:edc471038b4846b119d0b025f0336bf4b3e1ce23</id>
<content type='text'>
[ Upstream commit 3b5a39979dafea9d0cd69c7ae06088f7a84cdafa ]

Driver/net/can/slcan.c is derived from slip.c. Memory leak was detected
by Syzkaller in slcan. Same issue exists in slip.c and this patch is
addressing the leak in slip.c.

Here is the slcan memory leak trace reported by Syzkaller:

BUG: memory leak unreferenced object 0xffff888067f65500 (size 4096):
  comm "syz-executor043", pid 454, jiffies 4294759719 (age 11.930s)
  hex dump (first 32 bytes):
    73 6c 63 61 6e 30 00 00 00 00 00 00 00 00 00 00 slcan0..........
    00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
  backtrace:
    [&lt;00000000a06eec0d&gt;] __kmalloc+0x18b/0x2c0
    [&lt;0000000083306e66&gt;] kvmalloc_node+0x3a/0xc0
    [&lt;000000006ac27f87&gt;] alloc_netdev_mqs+0x17a/0x1080
    [&lt;0000000061a996c9&gt;] slcan_open+0x3ae/0x9a0
    [&lt;000000001226f0f9&gt;] tty_ldisc_open.isra.1+0x76/0xc0
    [&lt;0000000019289631&gt;] tty_set_ldisc+0x28c/0x5f0
    [&lt;000000004de5a617&gt;] tty_ioctl+0x48d/0x1590
    [&lt;00000000daef496f&gt;] do_vfs_ioctl+0x1c7/0x1510
    [&lt;0000000059068dbc&gt;] ksys_ioctl+0x99/0xb0
    [&lt;000000009a6eb334&gt;] __x64_sys_ioctl+0x78/0xb0
    [&lt;0000000053d0332e&gt;] do_syscall_64+0x16f/0x580
    [&lt;0000000021b83b99&gt;] entry_SYSCALL_64_after_hwframe+0x44/0xa9
    [&lt;000000008ea75434&gt;] 0xfffffffffffffff

Cc: "David S. Miller" &lt;davem@davemloft.net&gt;
Cc: Oliver Hartkopp &lt;socketcan@hartkopp.net&gt;
Cc: Lukas Bulwahn &lt;lukas.bulwahn@gmail.com&gt;
Signed-off-by: Jouni Hogander &lt;jouni.hogander@unikie.com&gt;
Signed-off-by: David S. Miller &lt;davem@davemloft.net&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
</entry>
<entry>
<title>slip: make slhc_free() silently accept an error pointer</title>
<updated>2019-05-02T07:58:56+00:00</updated>
<author>
<name>Linus Torvalds</name>
<email>torvalds@linux-foundation.org</email>
</author>
<published>2019-04-25T23:13:58+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=9c8c39bae89ab3cd6133d244fa19ee2141aabeac'/>
<id>urn:sha1:9c8c39bae89ab3cd6133d244fa19ee2141aabeac</id>
<content type='text'>
commit baf76f0c58aec435a3a864075b8f6d8ee5d1f17e upstream.

This way, slhc_free() accepts what slhc_init() returns, whether that is
an error or not.

In particular, the pattern in sl_alloc_bufs() is

        slcomp = slhc_init(16, 16);
        ...
        slhc_free(slcomp);

for the error handling path, and rather than complicate that code, just
make it ok to always free what was returned by the init function.

That's what the code used to do before commit 4ab42d78e37a ("ppp, slip:
Validate VJ compression slot parameters completely") when slhc_init()
just returned NULL for the error case, with no actual indication of the
details of the error.

Reported-by: syzbot+45474c076a4927533d2e@syzkaller.appspotmail.com
Fixes: 4ab42d78e37a ("ppp, slip: Validate VJ compression slot parameters completely")
Acked-by: Ben Hutchings &lt;ben@decadent.org.uk&gt;
Cc: David Miller &lt;davem@davemloft.net&gt;
Signed-off-by: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;

</content>
</entry>
<entry>
<title>treewide: kzalloc() -&gt; kcalloc()</title>
<updated>2018-06-12T23:19:22+00:00</updated>
<author>
<name>Kees Cook</name>
<email>keescook@chromium.org</email>
</author>
<published>2018-06-12T21:03:40+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=6396bb221514d2876fd6dc0aa2a1f240d99b37bb'/>
<id>urn:sha1:6396bb221514d2876fd6dc0aa2a1f240d99b37bb</id>
<content type='text'>
The kzalloc() function has a 2-factor argument form, kcalloc(). This
patch replaces cases of:

        kzalloc(a * b, gfp)

with:
        kcalloc(a * b, gfp)

as well as handling cases of:

        kzalloc(a * b * c, gfp)

with:

        kzalloc(array3_size(a, b, c), gfp)

as it's slightly less ugly than:

        kzalloc_array(array_size(a, b), c, gfp)

This does, however, attempt to ignore constant size factors like:

        kzalloc(4 * 1024, gfp)

though any constants defined via macros get caught up in the conversion.

Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.

The Coccinelle script used for this was:

// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@

(
  kzalloc(
-	(sizeof(TYPE)) * E
+	sizeof(TYPE) * E
  , ...)
|
  kzalloc(
-	(sizeof(THING)) * E
+	sizeof(THING) * E
  , ...)
)

// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@

(
  kzalloc(
-	sizeof(u8) * (COUNT)
+	COUNT
  , ...)
|
  kzalloc(
-	sizeof(__u8) * (COUNT)
+	COUNT
  , ...)
|
  kzalloc(
-	sizeof(char) * (COUNT)
+	COUNT
  , ...)
|
  kzalloc(
-	sizeof(unsigned char) * (COUNT)
+	COUNT
  , ...)
|
  kzalloc(
-	sizeof(u8) * COUNT
+	COUNT
  , ...)
|
  kzalloc(
-	sizeof(__u8) * COUNT
+	COUNT
  , ...)
|
  kzalloc(
-	sizeof(char) * COUNT
+	COUNT
  , ...)
|
  kzalloc(
-	sizeof(unsigned char) * COUNT
+	COUNT
  , ...)
)

// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@

(
- kzalloc
+ kcalloc
  (
-	sizeof(TYPE) * (COUNT_ID)
+	COUNT_ID, sizeof(TYPE)
  , ...)
|
- kzalloc
+ kcalloc
  (
-	sizeof(TYPE) * COUNT_ID
+	COUNT_ID, sizeof(TYPE)
  , ...)
|
- kzalloc
+ kcalloc
  (
-	sizeof(TYPE) * (COUNT_CONST)
+	COUNT_CONST, sizeof(TYPE)
  , ...)
|
- kzalloc
+ kcalloc
  (
-	sizeof(TYPE) * COUNT_CONST
+	COUNT_CONST, sizeof(TYPE)
  , ...)
|
- kzalloc
+ kcalloc
  (
-	sizeof(THING) * (COUNT_ID)
+	COUNT_ID, sizeof(THING)
  , ...)
|
- kzalloc
+ kcalloc
  (
-	sizeof(THING) * COUNT_ID
+	COUNT_ID, sizeof(THING)
  , ...)
|
- kzalloc
+ kcalloc
  (
-	sizeof(THING) * (COUNT_CONST)
+	COUNT_CONST, sizeof(THING)
  , ...)
|
- kzalloc
+ kcalloc
  (
-	sizeof(THING) * COUNT_CONST
+	COUNT_CONST, sizeof(THING)
  , ...)
)

// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@

- kzalloc
+ kcalloc
  (
-	SIZE * COUNT
+	COUNT, SIZE
  , ...)

// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@

(
  kzalloc(
-	sizeof(TYPE) * (COUNT) * (STRIDE)
+	array3_size(COUNT, STRIDE, sizeof(TYPE))
  , ...)
|
  kzalloc(
-	sizeof(TYPE) * (COUNT) * STRIDE
+	array3_size(COUNT, STRIDE, sizeof(TYPE))
  , ...)
|
  kzalloc(
-	sizeof(TYPE) * COUNT * (STRIDE)
+	array3_size(COUNT, STRIDE, sizeof(TYPE))
  , ...)
|
  kzalloc(
-	sizeof(TYPE) * COUNT * STRIDE
+	array3_size(COUNT, STRIDE, sizeof(TYPE))
  , ...)
|
  kzalloc(
-	sizeof(THING) * (COUNT) * (STRIDE)
+	array3_size(COUNT, STRIDE, sizeof(THING))
  , ...)
|
  kzalloc(
-	sizeof(THING) * (COUNT) * STRIDE
+	array3_size(COUNT, STRIDE, sizeof(THING))
  , ...)
|
  kzalloc(
-	sizeof(THING) * COUNT * (STRIDE)
+	array3_size(COUNT, STRIDE, sizeof(THING))
  , ...)
|
  kzalloc(
-	sizeof(THING) * COUNT * STRIDE
+	array3_size(COUNT, STRIDE, sizeof(THING))
  , ...)
)

// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@

(
  kzalloc(
-	sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+	array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
  , ...)
|
  kzalloc(
-	sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+	array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
  , ...)
|
  kzalloc(
-	sizeof(THING1) * sizeof(THING2) * COUNT
+	array3_size(COUNT, sizeof(THING1), sizeof(THING2))
  , ...)
|
  kzalloc(
-	sizeof(THING1) * sizeof(THING2) * (COUNT)
+	array3_size(COUNT, sizeof(THING1), sizeof(THING2))
  , ...)
|
  kzalloc(
-	sizeof(TYPE1) * sizeof(THING2) * COUNT
+	array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
  , ...)
|
  kzalloc(
-	sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+	array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
  , ...)
)

// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@

(
  kzalloc(
-	(COUNT) * STRIDE * SIZE
+	array3_size(COUNT, STRIDE, SIZE)
  , ...)
|
  kzalloc(
-	COUNT * (STRIDE) * SIZE
+	array3_size(COUNT, STRIDE, SIZE)
  , ...)
|
  kzalloc(
-	COUNT * STRIDE * (SIZE)
+	array3_size(COUNT, STRIDE, SIZE)
  , ...)
|
  kzalloc(
-	(COUNT) * (STRIDE) * SIZE
+	array3_size(COUNT, STRIDE, SIZE)
  , ...)
|
  kzalloc(
-	COUNT * (STRIDE) * (SIZE)
+	array3_size(COUNT, STRIDE, SIZE)
  , ...)
|
  kzalloc(
-	(COUNT) * STRIDE * (SIZE)
+	array3_size(COUNT, STRIDE, SIZE)
  , ...)
|
  kzalloc(
-	(COUNT) * (STRIDE) * (SIZE)
+	array3_size(COUNT, STRIDE, SIZE)
  , ...)
|
  kzalloc(
-	COUNT * STRIDE * SIZE
+	array3_size(COUNT, STRIDE, SIZE)
  , ...)
)

// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@

(
  kzalloc(C1 * C2 * C3, ...)
|
  kzalloc(
-	(E1) * E2 * E3
+	array3_size(E1, E2, E3)
  , ...)
|
  kzalloc(
-	(E1) * (E2) * E3
+	array3_size(E1, E2, E3)
  , ...)
|
  kzalloc(
-	(E1) * (E2) * (E3)
+	array3_size(E1, E2, E3)
  , ...)
|
  kzalloc(
-	E1 * E2 * E3
+	array3_size(E1, E2, E3)
  , ...)
)

// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@

(
  kzalloc(sizeof(THING) * C2, ...)
|
  kzalloc(sizeof(TYPE) * C2, ...)
|
  kzalloc(C1 * C2 * C3, ...)
|
  kzalloc(C1 * C2, ...)
|
- kzalloc
+ kcalloc
  (
-	sizeof(TYPE) * (E2)
+	E2, sizeof(TYPE)
  , ...)
|
- kzalloc
+ kcalloc
  (
-	sizeof(TYPE) * E2
+	E2, sizeof(TYPE)
  , ...)
|
- kzalloc
+ kcalloc
  (
-	sizeof(THING) * (E2)
+	E2, sizeof(THING)
  , ...)
|
- kzalloc
+ kcalloc
  (
-	sizeof(THING) * E2
+	E2, sizeof(THING)
  , ...)
|
- kzalloc
+ kcalloc
  (
-	(E1) * E2
+	E1, E2
  , ...)
|
- kzalloc
+ kcalloc
  (
-	(E1) * (E2)
+	E1, E2
  , ...)
|
- kzalloc
+ kcalloc
  (
-	E1 * E2
+	E1, E2
  , ...)
)

Signed-off-by: Kees Cook &lt;keescook@chromium.org&gt;
</content>
</entry>
<entry>
<title>slip: Check if rstate is initialized before uncompressing</title>
<updated>2018-04-11T14:33:46+00:00</updated>
<author>
<name>Tejaswi Tanikella</name>
<email>tejaswit@codeaurora.org</email>
</author>
<published>2018-04-11T11:04:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=3f01ddb962dc506916c243f9524e8bef97119b77'/>
<id>urn:sha1:3f01ddb962dc506916c243f9524e8bef97119b77</id>
<content type='text'>
On receiving a packet the state index points to the rstate which must be
used to fill up IP and TCP headers. But if the state index points to a
rstate which is unitialized, i.e. filled with zeros, it gets stuck in an
infinite loop inside ip_fast_csum trying to compute the ip checsum of a
header with zero length.

89.666953:   &lt;2&gt; [&lt;ffffff9dd3e94d38&gt;] slhc_uncompress+0x464/0x468
89.666965:   &lt;2&gt; [&lt;ffffff9dd3e87d88&gt;] ppp_receive_nonmp_frame+0x3b4/0x65c
89.666978:   &lt;2&gt; [&lt;ffffff9dd3e89dd4&gt;] ppp_receive_frame+0x64/0x7e0
89.666991:   &lt;2&gt; [&lt;ffffff9dd3e8a708&gt;] ppp_input+0x104/0x198
89.667005:   &lt;2&gt; [&lt;ffffff9dd3e93868&gt;] pppopns_recv_core+0x238/0x370
89.667027:   &lt;2&gt; [&lt;ffffff9dd4428fc8&gt;] __sk_receive_skb+0xdc/0x250
89.667040:   &lt;2&gt; [&lt;ffffff9dd3e939e4&gt;] pppopns_recv+0x44/0x60
89.667053:   &lt;2&gt; [&lt;ffffff9dd4426848&gt;] __sock_queue_rcv_skb+0x16c/0x24c
89.667065:   &lt;2&gt; [&lt;ffffff9dd4426954&gt;] sock_queue_rcv_skb+0x2c/0x38
89.667085:   &lt;2&gt; [&lt;ffffff9dd44f7358&gt;] raw_rcv+0x124/0x154
89.667098:   &lt;2&gt; [&lt;ffffff9dd44f7568&gt;] raw_local_deliver+0x1e0/0x22c
89.667117:   &lt;2&gt; [&lt;ffffff9dd44c8ba0&gt;] ip_local_deliver_finish+0x70/0x24c
89.667131:   &lt;2&gt; [&lt;ffffff9dd44c92f4&gt;] ip_local_deliver+0x100/0x10c

./scripts/faddr2line vmlinux slhc_uncompress+0x464/0x468 output:
 ip_fast_csum at arch/arm64/include/asm/checksum.h:40
 (inlined by) slhc_uncompress at drivers/net/slip/slhc.c:615

Adding a variable to indicate if the current rstate is initialized. If
such a packet arrives, move to toss state.

Signed-off-by: Tejaswi Tanikella &lt;tejaswit@codeaurora.org&gt;
Signed-off-by: David S. Miller &lt;davem@davemloft.net&gt;
</content>
</entry>
<entry>
<title>slip: sl_alloc(): remove unused parameter "dev_t line"</title>
<updated>2017-12-08T19:41:02+00:00</updated>
<author>
<name>Marc Kleine-Budde</name>
<email>mkl@pengutronix.de</email>
</author>
<published>2017-12-08T11:18:59+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=936e5d8bdfa72577e28ea671d9e2ee4fef0d6b3e'/>
<id>urn:sha1:936e5d8bdfa72577e28ea671d9e2ee4fef0d6b3e</id>
<content type='text'>
The first and only parameter of sl_alloc() is unused, so remove it.

Fixes: 5342b77c4123 slip: ("Clean up create and destroy")
Signed-off-by: Marc Kleine-Budde &lt;mkl@pengutronix.de&gt;
Signed-off-by: David S. Miller &lt;davem@davemloft.net&gt;
</content>
</entry>
<entry>
<title>treewide: setup_timer() -&gt; timer_setup()</title>
<updated>2017-11-21T23:57:07+00:00</updated>
<author>
<name>Kees Cook</name>
<email>keescook@chromium.org</email>
</author>
<published>2017-10-16T21:43:17+00:00</published>
<link rel='alternate' type='text/html' href='https://git.radix-linux.su/kernel/linux.git/commit/?id=e99e88a9d2b067465adaa9c111ada99a041bef9a'/>
<id>urn:sha1:e99e88a9d2b067465adaa9c111ada99a041bef9a</id>
<content type='text'>
This converts all remaining cases of the old setup_timer() API into using
timer_setup(), where the callback argument is the structure already
holding the struct timer_list. These should have no behavioral changes,
since they just change which pointer is passed into the callback with
the same available pointers after conversion. It handles the following
examples, in addition to some other variations.

Casting from unsigned long:

    void my_callback(unsigned long data)
    {
        struct something *ptr = (struct something *)data;
    ...
    }
    ...
    setup_timer(&amp;ptr-&gt;my_timer, my_callback, ptr);

and forced object casts:

    void my_callback(struct something *ptr)
    {
    ...
    }
    ...
    setup_timer(&amp;ptr-&gt;my_timer, my_callback, (unsigned long)ptr);

become:

    void my_callback(struct timer_list *t)
    {
        struct something *ptr = from_timer(ptr, t, my_timer);
    ...
    }
    ...
    timer_setup(&amp;ptr-&gt;my_timer, my_callback, 0);

Direct function assignments:

    void my_callback(unsigned long data)
    {
        struct something *ptr = (struct something *)data;
    ...
    }
    ...
    ptr-&gt;my_timer.function = my_callback;

have a temporary cast added, along with converting the args:

    void my_callback(struct timer_list *t)
    {
        struct something *ptr = from_timer(ptr, t, my_timer);
    ...
    }
    ...
    ptr-&gt;my_timer.function = (TIMER_FUNC_TYPE)my_callback;

And finally, callbacks without a data assignment:

    void my_callback(unsigned long data)
    {
    ...
    }
    ...
    setup_timer(&amp;ptr-&gt;my_timer, my_callback, 0);

have their argument renamed to verify they're unused during conversion:

    void my_callback(struct timer_list *unused)
    {
    ...
    }
    ...
    timer_setup(&amp;ptr-&gt;my_timer, my_callback, 0);

The conversion is done with the following Coccinelle script:

spatch --very-quiet --all-includes --include-headers \
	-I ./arch/x86/include -I ./arch/x86/include/generated \
	-I ./include -I ./arch/x86/include/uapi \
	-I ./arch/x86/include/generated/uapi -I ./include/uapi \
	-I ./include/generated/uapi --include ./include/linux/kconfig.h \
	--dir . \
	--cocci-file ~/src/data/timer_setup.cocci

@fix_address_of@
expression e;
@@

 setup_timer(
-&amp;(e)
+&amp;e
 , ...)

// Update any raw setup_timer() usages that have a NULL callback, but
// would otherwise match change_timer_function_usage, since the latter
// will update all function assignments done in the face of a NULL
// function initialization in setup_timer().
@change_timer_function_usage_NULL@
expression _E;
identifier _timer;
type _cast_data;
@@

(
-setup_timer(&amp;_E-&gt;_timer, NULL, _E);
+timer_setup(&amp;_E-&gt;_timer, NULL, 0);
|
-setup_timer(&amp;_E-&gt;_timer, NULL, (_cast_data)_E);
+timer_setup(&amp;_E-&gt;_timer, NULL, 0);
|
-setup_timer(&amp;_E._timer, NULL, &amp;_E);
+timer_setup(&amp;_E._timer, NULL, 0);
|
-setup_timer(&amp;_E._timer, NULL, (_cast_data)&amp;_E);
+timer_setup(&amp;_E._timer, NULL, 0);
)

@change_timer_function_usage@
expression _E;
identifier _timer;
struct timer_list _stl;
identifier _callback;
type _cast_func, _cast_data;
@@

(
-setup_timer(&amp;_E-&gt;_timer, _callback, _E);
+timer_setup(&amp;_E-&gt;_timer, _callback, 0);
|
-setup_timer(&amp;_E-&gt;_timer, &amp;_callback, _E);
+timer_setup(&amp;_E-&gt;_timer, _callback, 0);
|
-setup_timer(&amp;_E-&gt;_timer, _callback, (_cast_data)_E);
+timer_setup(&amp;_E-&gt;_timer, _callback, 0);
|
-setup_timer(&amp;_E-&gt;_timer, &amp;_callback, (_cast_data)_E);
+timer_setup(&amp;_E-&gt;_timer, _callback, 0);
|
-setup_timer(&amp;_E-&gt;_timer, (_cast_func)_callback, _E);
+timer_setup(&amp;_E-&gt;_timer, _callback, 0);
|
-setup_timer(&amp;_E-&gt;_timer, (_cast_func)&amp;_callback, _E);
+timer_setup(&amp;_E-&gt;_timer, _callback, 0);
|
-setup_timer(&amp;_E-&gt;_timer, (_cast_func)_callback, (_cast_data)_E);
+timer_setup(&amp;_E-&gt;_timer, _callback, 0);
|
-setup_timer(&amp;_E-&gt;_timer, (_cast_func)&amp;_callback, (_cast_data)_E);
+timer_setup(&amp;_E-&gt;_timer, _callback, 0);
|
-setup_timer(&amp;_E._timer, _callback, (_cast_data)_E);
+timer_setup(&amp;_E._timer, _callback, 0);
|
-setup_timer(&amp;_E._timer, _callback, (_cast_data)&amp;_E);
+timer_setup(&amp;_E._timer, _callback, 0);
|
-setup_timer(&amp;_E._timer, &amp;_callback, (_cast_data)_E);
+timer_setup(&amp;_E._timer, _callback, 0);
|
-setup_timer(&amp;_E._timer, &amp;_callback, (_cast_data)&amp;_E);
+timer_setup(&amp;_E._timer, _callback, 0);
|
-setup_timer(&amp;_E._timer, (_cast_func)_callback, (_cast_data)_E);
+timer_setup(&amp;_E._timer, _callback, 0);
|
-setup_timer(&amp;_E._timer, (_cast_func)_callback, (_cast_data)&amp;_E);
+timer_setup(&amp;_E._timer, _callback, 0);
|
-setup_timer(&amp;_E._timer, (_cast_func)&amp;_callback, (_cast_data)_E);
+timer_setup(&amp;_E._timer, _callback, 0);
|
-setup_timer(&amp;_E._timer, (_cast_func)&amp;_callback, (_cast_data)&amp;_E);
+timer_setup(&amp;_E._timer, _callback, 0);
|
 _E-&gt;_timer@_stl.function = _callback;
|
 _E-&gt;_timer@_stl.function = &amp;_callback;
|
 _E-&gt;_timer@_stl.function = (_cast_func)_callback;
|
 _E-&gt;_timer@_stl.function = (_cast_func)&amp;_callback;
|
 _E._timer@_stl.function = _callback;
|
 _E._timer@_stl.function = &amp;_callback;
|
 _E._timer@_stl.function = (_cast_func)_callback;
|
 _E._timer@_stl.function = (_cast_func)&amp;_callback;
)

// callback(unsigned long arg)
@change_callback_handle_cast
 depends on change_timer_function_usage@
identifier change_timer_function_usage._callback;
identifier change_timer_function_usage._timer;
type _origtype;
identifier _origarg;
type _handletype;
identifier _handle;
@@

 void _callback(
-_origtype _origarg
+struct timer_list *t
 )
 {
(
	... when != _origarg
	_handletype *_handle =
-(_handletype *)_origarg;
+from_timer(_handle, t, _timer);
	... when != _origarg
|
	... when != _origarg
	_handletype *_handle =
-(void *)_origarg;
+from_timer(_handle, t, _timer);
	... when != _origarg
|
	... when != _origarg
	_handletype *_handle;
	... when != _handle
	_handle =
-(_handletype *)_origarg;
+from_timer(_handle, t, _timer);
	... when != _origarg
|
	... when != _origarg
	_handletype *_handle;
	... when != _handle
	_handle =
-(void *)_origarg;
+from_timer(_handle, t, _timer);
	... when != _origarg
)
 }

// callback(unsigned long arg) without existing variable
@change_callback_handle_cast_no_arg
 depends on change_timer_function_usage &amp;&amp;
                     !change_callback_handle_cast@
identifier change_timer_function_usage._callback;
identifier change_timer_function_usage._timer;
type _origtype;
identifier _origarg;
type _handletype;
@@

 void _callback(
-_origtype _origarg
+struct timer_list *t
 )
 {
+	_handletype *_origarg = from_timer(_origarg, t, _timer);
+
	... when != _origarg
-	(_handletype *)_origarg
+	_origarg
	... when != _origarg
 }

// Avoid already converted callbacks.
@match_callback_converted
 depends on change_timer_function_usage &amp;&amp;
            !change_callback_handle_cast &amp;&amp;
	    !change_callback_handle_cast_no_arg@
identifier change_timer_function_usage._callback;
identifier t;
@@

 void _callback(struct timer_list *t)
 { ... }

// callback(struct something *handle)
@change_callback_handle_arg
 depends on change_timer_function_usage &amp;&amp;
	    !match_callback_converted &amp;&amp;
            !change_callback_handle_cast &amp;&amp;
            !change_callback_handle_cast_no_arg@
identifier change_timer_function_usage._callback;
identifier change_timer_function_usage._timer;
type _handletype;
identifier _handle;
@@

 void _callback(
-_handletype *_handle
+struct timer_list *t
 )
 {
+	_handletype *_handle = from_timer(_handle, t, _timer);
	...
 }

// If change_callback_handle_arg ran on an empty function, remove
// the added handler.
@unchange_callback_handle_arg
 depends on change_timer_function_usage &amp;&amp;
	    change_callback_handle_arg@
identifier change_timer_function_usage._callback;
identifier change_timer_function_usage._timer;
type _handletype;
identifier _handle;
identifier t;
@@

 void _callback(struct timer_list *t)
 {
-	_handletype *_handle = from_timer(_handle, t, _timer);
 }

// We only want to refactor the setup_timer() data argument if we've found
// the matching callback. This undoes changes in change_timer_function_usage.
@unchange_timer_function_usage
 depends on change_timer_function_usage &amp;&amp;
            !change_callback_handle_cast &amp;&amp;
            !change_callback_handle_cast_no_arg &amp;&amp;
	    !change_callback_handle_arg@
expression change_timer_function_usage._E;
identifier change_timer_function_usage._timer;
identifier change_timer_function_usage._callback;
type change_timer_function_usage._cast_data;
@@

(
-timer_setup(&amp;_E-&gt;_timer, _callback, 0);
+setup_timer(&amp;_E-&gt;_timer, _callback, (_cast_data)_E);
|
-timer_setup(&amp;_E._timer, _callback, 0);
+setup_timer(&amp;_E._timer, _callback, (_cast_data)&amp;_E);
)

// If we fixed a callback from a .function assignment, fix the
// assignment cast now.
@change_timer_function_assignment
 depends on change_timer_function_usage &amp;&amp;
            (change_callback_handle_cast ||
             change_callback_handle_cast_no_arg ||
             change_callback_handle_arg)@
expression change_timer_function_usage._E;
identifier change_timer_function_usage._timer;
identifier change_timer_function_usage._callback;
type _cast_func;
typedef TIMER_FUNC_TYPE;
@@

(
 _E-&gt;_timer.function =
-_callback
+(TIMER_FUNC_TYPE)_callback
 ;
|
 _E-&gt;_timer.function =
-&amp;_callback
+(TIMER_FUNC_TYPE)_callback
 ;
|
 _E-&gt;_timer.function =
-(_cast_func)_callback;
+(TIMER_FUNC_TYPE)_callback
 ;
|
 _E-&gt;_timer.function =
-(_cast_func)&amp;_callback
+(TIMER_FUNC_TYPE)_callback
 ;
|
 _E._timer.function =
-_callback
+(TIMER_FUNC_TYPE)_callback
 ;
|
 _E._timer.function =
-&amp;_callback;
+(TIMER_FUNC_TYPE)_callback
 ;
|
 _E._timer.function =
-(_cast_func)_callback
+(TIMER_FUNC_TYPE)_callback
 ;
|
 _E._timer.function =
-(_cast_func)&amp;_callback
+(TIMER_FUNC_TYPE)_callback
 ;
)

// Sometimes timer functions are called directly. Replace matched args.
@change_timer_function_calls
 depends on change_timer_function_usage &amp;&amp;
            (change_callback_handle_cast ||
             change_callback_handle_cast_no_arg ||
             change_callback_handle_arg)@
expression _E;
identifier change_timer_function_usage._timer;
identifier change_timer_function_usage._callback;
type _cast_data;
@@

 _callback(
(
-(_cast_data)_E
+&amp;_E-&gt;_timer
|
-(_cast_data)&amp;_E
+&amp;_E._timer
|
-_E
+&amp;_E-&gt;_timer
)
 )

// If a timer has been configured without a data argument, it can be
// converted without regard to the callback argument, since it is unused.
@match_timer_function_unused_data@
expression _E;
identifier _timer;
identifier _callback;
@@

(
-setup_timer(&amp;_E-&gt;_timer, _callback, 0);
+timer_setup(&amp;_E-&gt;_timer, _callback, 0);
|
-setup_timer(&amp;_E-&gt;_timer, _callback, 0L);
+timer_setup(&amp;_E-&gt;_timer, _callback, 0);
|
-setup_timer(&amp;_E-&gt;_timer, _callback, 0UL);
+timer_setup(&amp;_E-&gt;_timer, _callback, 0);
|
-setup_timer(&amp;_E._timer, _callback, 0);
+timer_setup(&amp;_E._timer, _callback, 0);
|
-setup_timer(&amp;_E._timer, _callback, 0L);
+timer_setup(&amp;_E._timer, _callback, 0);
|
-setup_timer(&amp;_E._timer, _callback, 0UL);
+timer_setup(&amp;_E._timer, _callback, 0);
|
-setup_timer(&amp;_timer, _callback, 0);
+timer_setup(&amp;_timer, _callback, 0);
|
-setup_timer(&amp;_timer, _callback, 0L);
+timer_setup(&amp;_timer, _callback, 0);
|
-setup_timer(&amp;_timer, _callback, 0UL);
+timer_setup(&amp;_timer, _callback, 0);
|
-setup_timer(_timer, _callback, 0);
+timer_setup(_timer, _callback, 0);
|
-setup_timer(_timer, _callback, 0L);
+timer_setup(_timer, _callback, 0);
|
-setup_timer(_timer, _callback, 0UL);
+timer_setup(_timer, _callback, 0);
)

@change_callback_unused_data
 depends on match_timer_function_unused_data@
identifier match_timer_function_unused_data._callback;
type _origtype;
identifier _origarg;
@@

 void _callback(
-_origtype _origarg
+struct timer_list *unused
 )
 {
	... when != _origarg
 }

Signed-off-by: Kees Cook &lt;keescook@chromium.org&gt;
</content>
</entry>
</feed>
