2019-05-27 14:55:01 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
2005-04-17 06:20:36 +08:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Copyright (C) Alan Cox GW4PTS (alan@lxorguk.ukuu.org.uk)
|
|
|
|
* Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
|
|
|
|
* Copyright (C) Steven Whitehouse GW7RRM (stevew@acm.org)
|
|
|
|
* Copyright (C) Joerg Reuter DL1BKE (jreuter@yaina.de)
|
|
|
|
* Copyright (C) Hans-Joachim Hetscher DD8NE (dd8ne@bnv-bamberg.de)
|
|
|
|
* Copyright (C) Frederic Rible F1OAT (frible@teaser.fr)
|
|
|
|
*/
|
2006-01-12 04:17:47 +08:00
|
|
|
|
|
|
|
#include <linux/capability.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/errno.h>
|
|
|
|
#include <linux/types.h>
|
|
|
|
#include <linux/socket.h>
|
|
|
|
#include <linux/timer.h>
|
|
|
|
#include <linux/in.h>
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/sched.h>
|
|
|
|
#include <linux/string.h>
|
|
|
|
#include <linux/sockios.h>
|
|
|
|
#include <linux/net.h>
|
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit slab.h inclusion from percpu.h
percpu.h is included by sched.h and module.h and thus ends up being
included when building most .c files. percpu.h includes slab.h which
in turn includes gfp.h making everything defined by the two files
universally available and complicating inclusion dependencies.
percpu.h -> slab.h dependency is about to be removed. Prepare for
this change by updating users of gfp and slab facilities include those
headers directly instead of assuming availability. As this conversion
needs to touch large number of source files, the following script is
used as the basis of conversion.
http://userweb.kernel.org/~tj/misc/slabh-sweep.py
The script does the followings.
* Scan files for gfp and slab usages and update includes such that
only the necessary includes are there. ie. if only gfp is used,
gfp.h, if slab is used, slab.h.
* When the script inserts a new include, it looks at the include
blocks and try to put the new include such that its order conforms
to its surrounding. It's put in the include block which contains
core kernel includes, in the same order that the rest are ordered -
alphabetical, Christmas tree, rev-Xmas-tree or at the end if there
doesn't seem to be any matching order.
* If the script can't find a place to put a new include (mostly
because the file doesn't have fitting include block), it prints out
an error message indicating which .h file needs to be added to the
file.
The conversion was done in the following steps.
1. The initial automatic conversion of all .c files updated slightly
over 4000 files, deleting around 700 includes and adding ~480 gfp.h
and ~3000 slab.h inclusions. The script emitted errors for ~400
files.
2. Each error was manually checked. Some didn't need the inclusion,
some needed manual addition while adding it to implementation .h or
embedding .c file was more appropriate for others. This step added
inclusions to around 150 files.
3. The script was run again and the output was compared to the edits
from #2 to make sure no file was left behind.
4. Several build tests were done and a couple of problems were fixed.
e.g. lib/decompress_*.c used malloc/free() wrappers around slab
APIs requiring slab.h to be added manually.
5. The script was run on all .h files but without automatically
editing them as sprinkling gfp.h and slab.h inclusions around .h
files could easily lead to inclusion dependency hell. Most gfp.h
inclusion directives were ignored as stuff from gfp.h was usually
wildly available and often used in preprocessor macros. Each
slab.h inclusion directive was examined and added manually as
necessary.
6. percpu.h was updated not to include slab.h.
7. Build test were done on the following configurations and failures
were fixed. CONFIG_GCOV_KERNEL was turned off for all tests (as my
distributed build env didn't work with gcov compiles) and a few
more options had to be turned off depending on archs to make things
build (like ipr on powerpc/64 which failed due to missing writeq).
* x86 and x86_64 UP and SMP allmodconfig and a custom test config.
* powerpc and powerpc64 SMP allmodconfig
* sparc and sparc64 SMP allmodconfig
* ia64 SMP allmodconfig
* s390 SMP allmodconfig
* alpha SMP allmodconfig
* um on x86_64 SMP allmodconfig
8. percpu.h modifications were reverted so that it could be applied as
a separate patch and serve as bisection point.
Given the fact that I had only a couple of failures from tests on step
6, I'm fairly confident about the coverage of this conversion patch.
If there is a breakage, it's likely to be something in one of the arch
headers which should be easily discoverable easily on most builds of
the specific arch.
Signed-off-by: Tejun Heo <tj@kernel.org>
Guess-its-ok-by: Christoph Lameter <cl@linux-foundation.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Lee Schermerhorn <Lee.Schermerhorn@hp.com>
2010-03-24 16:04:11 +08:00
|
|
|
#include <linux/slab.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <net/ax25.h>
|
|
|
|
#include <linux/inet.h>
|
|
|
|
#include <linux/netdevice.h>
|
|
|
|
#include <linux/if_arp.h>
|
|
|
|
#include <linux/skbuff.h>
|
|
|
|
#include <linux/spinlock.h>
|
|
|
|
#include <net/sock.h>
|
2016-12-25 03:46:01 +08:00
|
|
|
#include <linux/uaccess.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
#include <linux/fcntl.h>
|
|
|
|
#include <linux/mm.h>
|
|
|
|
#include <linux/interrupt.h>
|
|
|
|
#include <linux/init.h>
|
|
|
|
#include <linux/seq_file.h>
|
2011-07-15 23:47:34 +08:00
|
|
|
#include <linux/export.h>
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
static ax25_route *ax25_route_list;
|
ax25: fix possible use-after-free
syzbot found that ax25 routes where not properly protected
against concurrent use [1].
In this particular report the bug happened while
copying ax25->digipeat.
Fix this problem by making sure we call ax25_get_route()
while ax25_route_lock is held, so that no modification
could happen while using the route.
The current two ax25_get_route() callers do not sleep,
so this change should be fine.
Once we do that, ax25_get_route() no longer needs to
grab a reference on the found route.
[1]
ax25_connect(): syz-executor0 uses autobind, please contact jreuter@yaina.de
BUG: KASAN: use-after-free in memcpy include/linux/string.h:352 [inline]
BUG: KASAN: use-after-free in kmemdup+0x42/0x60 mm/util.c:113
Read of size 66 at addr ffff888066641a80 by task syz-executor2/531
ax25_connect(): syz-executor0 uses autobind, please contact jreuter@yaina.de
CPU: 1 PID: 531 Comm: syz-executor2 Not tainted 5.0.0-rc2+ #10
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+0x1db/0x2d0 lib/dump_stack.c:113
print_address_description.cold+0x7c/0x20d mm/kasan/report.c:187
kasan_report.cold+0x1b/0x40 mm/kasan/report.c:317
check_memory_region_inline mm/kasan/generic.c:185 [inline]
check_memory_region+0x123/0x190 mm/kasan/generic.c:191
memcpy+0x24/0x50 mm/kasan/common.c:130
memcpy include/linux/string.h:352 [inline]
kmemdup+0x42/0x60 mm/util.c:113
kmemdup include/linux/string.h:425 [inline]
ax25_rt_autobind+0x25d/0x750 net/ax25/ax25_route.c:424
ax25_connect.cold+0x30/0xa4 net/ax25/af_ax25.c:1224
__sys_connect+0x357/0x490 net/socket.c:1664
__do_sys_connect net/socket.c:1675 [inline]
__se_sys_connect net/socket.c:1672 [inline]
__x64_sys_connect+0x73/0xb0 net/socket.c:1672
do_syscall_64+0x1a3/0x800 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x458099
Code: 6d b7 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 3b b7 fb ff c3 66 2e 0f 1f 84 00 00 00 00
RSP: 002b:00007f870ee22c78 EFLAGS: 00000246 ORIG_RAX: 000000000000002a
RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 0000000000458099
RDX: 0000000000000048 RSI: 0000000020000080 RDI: 0000000000000005
RBP: 000000000073bf00 R08: 0000000000000000 R09: 0000000000000000
ax25_connect(): syz-executor4 uses autobind, please contact jreuter@yaina.de
R10: 0000000000000000 R11: 0000000000000246 R12: 00007f870ee236d4
R13: 00000000004be48e R14: 00000000004ce9a8 R15: 00000000ffffffff
Allocated by task 526:
save_stack+0x45/0xd0 mm/kasan/common.c:73
set_track mm/kasan/common.c:85 [inline]
__kasan_kmalloc mm/kasan/common.c:496 [inline]
__kasan_kmalloc.constprop.0+0xcf/0xe0 mm/kasan/common.c:469
kasan_kmalloc+0x9/0x10 mm/kasan/common.c:504
ax25_connect(): syz-executor5 uses autobind, please contact jreuter@yaina.de
kmem_cache_alloc_trace+0x151/0x760 mm/slab.c:3609
kmalloc include/linux/slab.h:545 [inline]
ax25_rt_add net/ax25/ax25_route.c:95 [inline]
ax25_rt_ioctl+0x3b9/0x1270 net/ax25/ax25_route.c:233
ax25_ioctl+0x322/0x10b0 net/ax25/af_ax25.c:1763
sock_do_ioctl+0xe2/0x400 net/socket.c:950
sock_ioctl+0x32f/0x6c0 net/socket.c:1074
vfs_ioctl fs/ioctl.c:46 [inline]
file_ioctl fs/ioctl.c:509 [inline]
do_vfs_ioctl+0x107b/0x17d0 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+0x1a3/0x800 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
ax25_connect(): syz-executor5 uses autobind, please contact jreuter@yaina.de
Freed by task 550:
save_stack+0x45/0xd0 mm/kasan/common.c:73
set_track mm/kasan/common.c:85 [inline]
__kasan_slab_free+0x102/0x150 mm/kasan/common.c:458
kasan_slab_free+0xe/0x10 mm/kasan/common.c:466
__cache_free mm/slab.c:3487 [inline]
kfree+0xcf/0x230 mm/slab.c:3806
ax25_rt_add net/ax25/ax25_route.c:92 [inline]
ax25_rt_ioctl+0x304/0x1270 net/ax25/ax25_route.c:233
ax25_ioctl+0x322/0x10b0 net/ax25/af_ax25.c:1763
sock_do_ioctl+0xe2/0x400 net/socket.c:950
sock_ioctl+0x32f/0x6c0 net/socket.c:1074
vfs_ioctl fs/ioctl.c:46 [inline]
file_ioctl fs/ioctl.c:509 [inline]
do_vfs_ioctl+0x107b/0x17d0 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+0x1a3/0x800 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
The buggy address belongs to the object at ffff888066641a80
which belongs to the cache kmalloc-96 of size 96
The buggy address is located 0 bytes inside of
96-byte region [ffff888066641a80, ffff888066641ae0)
The buggy address belongs to the page:
page:ffffea0001999040 count:1 mapcount:0 mapping:ffff88812c3f04c0 index:0x0
flags: 0x1fffc0000000200(slab)
ax25_connect(): syz-executor4 uses autobind, please contact jreuter@yaina.de
raw: 01fffc0000000200 ffffea0001817948 ffffea0002341dc8 ffff88812c3f04c0
raw: 0000000000000000 ffff888066641000 0000000100000020 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff888066641980: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
ffff888066641a00: 00 00 00 00 00 00 00 00 02 fc fc fc fc fc fc fc
>ffff888066641a80: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
^
ffff888066641b00: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
ffff888066641b80: 00 00 00 00 00 00 00 00 00 00 00 00 fc fc fc fc
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-01-23 02:40:59 +08:00
|
|
|
DEFINE_RWLOCK(ax25_route_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
void ax25_rt_device_down(struct net_device *dev)
|
|
|
|
{
|
|
|
|
ax25_route *s, *t, *ax25_rt;
|
|
|
|
|
2008-02-12 13:26:43 +08:00
|
|
|
write_lock_bh(&ax25_route_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
ax25_rt = ax25_route_list;
|
|
|
|
while (ax25_rt != NULL) {
|
|
|
|
s = ax25_rt;
|
|
|
|
ax25_rt = ax25_rt->next;
|
|
|
|
|
|
|
|
if (s->dev == dev) {
|
|
|
|
if (ax25_route_list == s) {
|
|
|
|
ax25_route_list = s->next;
|
2005-11-09 01:41:34 +08:00
|
|
|
kfree(s->digipeat);
|
2005-04-17 06:20:36 +08:00
|
|
|
kfree(s);
|
|
|
|
} else {
|
|
|
|
for (t = ax25_route_list; t != NULL; t = t->next) {
|
|
|
|
if (t->next == s) {
|
|
|
|
t->next = s->next;
|
2005-11-09 01:41:34 +08:00
|
|
|
kfree(s->digipeat);
|
2005-04-17 06:20:36 +08:00
|
|
|
kfree(s);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-02-12 13:26:43 +08:00
|
|
|
write_unlock_bh(&ax25_route_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
2006-12-15 07:49:28 +08:00
|
|
|
static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
ax25_route *ax25_rt;
|
|
|
|
ax25_dev *ax25_dev;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (route->digi_count > AX25_MAX_DIGIS)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2024-06-12 13:13:20 +08:00
|
|
|
ax25_dev = ax25_addr_ax25dev(&route->port_addr);
|
|
|
|
if (!ax25_dev)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2008-02-12 13:26:43 +08:00
|
|
|
write_lock_bh(&ax25_route_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
ax25_rt = ax25_route_list;
|
|
|
|
while (ax25_rt != NULL) {
|
|
|
|
if (ax25cmp(&ax25_rt->callsign, &route->dest_addr) == 0 &&
|
2007-02-09 22:24:31 +08:00
|
|
|
ax25_rt->dev == ax25_dev->dev) {
|
2005-11-09 01:41:34 +08:00
|
|
|
kfree(ax25_rt->digipeat);
|
|
|
|
ax25_rt->digipeat = NULL;
|
2005-04-17 06:20:36 +08:00
|
|
|
if (route->digi_count != 0) {
|
|
|
|
if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
|
2008-02-12 13:26:43 +08:00
|
|
|
write_unlock_bh(&ax25_route_lock);
|
2024-06-12 13:13:20 +08:00
|
|
|
ax25_dev_put(ax25_dev);
|
2005-04-17 06:20:36 +08:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
ax25_rt->digipeat->lastrepeat = -1;
|
|
|
|
ax25_rt->digipeat->ndigi = route->digi_count;
|
|
|
|
for (i = 0; i < route->digi_count; i++) {
|
|
|
|
ax25_rt->digipeat->repeated[i] = 0;
|
|
|
|
ax25_rt->digipeat->calls[i] = route->digi_addr[i];
|
|
|
|
}
|
|
|
|
}
|
2008-02-12 13:26:43 +08:00
|
|
|
write_unlock_bh(&ax25_route_lock);
|
2024-06-12 13:13:20 +08:00
|
|
|
ax25_dev_put(ax25_dev);
|
2005-04-17 06:20:36 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
ax25_rt = ax25_rt->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((ax25_rt = kmalloc(sizeof(ax25_route), GFP_ATOMIC)) == NULL) {
|
2008-02-12 13:26:43 +08:00
|
|
|
write_unlock_bh(&ax25_route_lock);
|
2024-06-12 13:13:20 +08:00
|
|
|
ax25_dev_put(ax25_dev);
|
2005-04-17 06:20:36 +08:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
2017-07-04 20:53:30 +08:00
|
|
|
refcount_set(&ax25_rt->refcount, 1);
|
2005-04-17 06:20:36 +08:00
|
|
|
ax25_rt->callsign = route->dest_addr;
|
|
|
|
ax25_rt->dev = ax25_dev->dev;
|
|
|
|
ax25_rt->digipeat = NULL;
|
|
|
|
ax25_rt->ip_mode = ' ';
|
|
|
|
if (route->digi_count != 0) {
|
|
|
|
if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
|
2008-02-12 13:26:43 +08:00
|
|
|
write_unlock_bh(&ax25_route_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
kfree(ax25_rt);
|
2024-06-12 13:13:20 +08:00
|
|
|
ax25_dev_put(ax25_dev);
|
2005-04-17 06:20:36 +08:00
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
ax25_rt->digipeat->lastrepeat = -1;
|
|
|
|
ax25_rt->digipeat->ndigi = route->digi_count;
|
|
|
|
for (i = 0; i < route->digi_count; i++) {
|
|
|
|
ax25_rt->digipeat->repeated[i] = 0;
|
|
|
|
ax25_rt->digipeat->calls[i] = route->digi_addr[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ax25_rt->next = ax25_route_list;
|
|
|
|
ax25_route_list = ax25_rt;
|
2008-02-12 13:26:43 +08:00
|
|
|
write_unlock_bh(&ax25_route_lock);
|
2024-06-12 13:13:20 +08:00
|
|
|
ax25_dev_put(ax25_dev);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-07-04 10:30:18 +08:00
|
|
|
void __ax25_put_route(ax25_route *ax25_rt)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
2006-07-04 10:30:18 +08:00
|
|
|
kfree(ax25_rt->digipeat);
|
|
|
|
kfree(ax25_rt);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int ax25_rt_del(struct ax25_routes_struct *route)
|
|
|
|
{
|
|
|
|
ax25_route *s, *t, *ax25_rt;
|
|
|
|
ax25_dev *ax25_dev;
|
|
|
|
|
|
|
|
if ((ax25_dev = ax25_addr_ax25dev(&route->port_addr)) == NULL)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2008-02-12 13:26:43 +08:00
|
|
|
write_lock_bh(&ax25_route_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
ax25_rt = ax25_route_list;
|
|
|
|
while (ax25_rt != NULL) {
|
|
|
|
s = ax25_rt;
|
|
|
|
ax25_rt = ax25_rt->next;
|
|
|
|
if (s->dev == ax25_dev->dev &&
|
|
|
|
ax25cmp(&route->dest_addr, &s->callsign) == 0) {
|
|
|
|
if (ax25_route_list == s) {
|
|
|
|
ax25_route_list = s->next;
|
2006-07-04 10:30:18 +08:00
|
|
|
ax25_put_route(s);
|
2005-04-17 06:20:36 +08:00
|
|
|
} else {
|
|
|
|
for (t = ax25_route_list; t != NULL; t = t->next) {
|
|
|
|
if (t->next == s) {
|
|
|
|
t->next = s->next;
|
2006-07-04 10:30:18 +08:00
|
|
|
ax25_put_route(s);
|
2005-04-17 06:20:36 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-02-12 13:26:43 +08:00
|
|
|
write_unlock_bh(&ax25_route_lock);
|
2024-06-12 13:13:20 +08:00
|
|
|
ax25_dev_put(ax25_dev);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ax25_rt_opt(struct ax25_route_opt_struct *rt_option)
|
|
|
|
{
|
|
|
|
ax25_route *ax25_rt;
|
|
|
|
ax25_dev *ax25_dev;
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
if ((ax25_dev = ax25_addr_ax25dev(&rt_option->port_addr)) == NULL)
|
|
|
|
return -EINVAL;
|
|
|
|
|
2008-02-12 13:26:43 +08:00
|
|
|
write_lock_bh(&ax25_route_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
ax25_rt = ax25_route_list;
|
|
|
|
while (ax25_rt != NULL) {
|
|
|
|
if (ax25_rt->dev == ax25_dev->dev &&
|
|
|
|
ax25cmp(&rt_option->dest_addr, &ax25_rt->callsign) == 0) {
|
|
|
|
switch (rt_option->cmd) {
|
|
|
|
case AX25_SET_RT_IPMODE:
|
|
|
|
switch (rt_option->arg) {
|
|
|
|
case ' ':
|
|
|
|
case 'D':
|
|
|
|
case 'V':
|
|
|
|
ax25_rt->ip_mode = rt_option->arg;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
err = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
err = -EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ax25_rt = ax25_rt->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
2008-02-12 13:26:43 +08:00
|
|
|
write_unlock_bh(&ax25_route_lock);
|
2024-06-12 13:13:20 +08:00
|
|
|
ax25_dev_put(ax25_dev);
|
2005-04-17 06:20:36 +08:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ax25_rt_ioctl(unsigned int cmd, void __user *arg)
|
|
|
|
{
|
|
|
|
struct ax25_route_opt_struct rt_option;
|
|
|
|
struct ax25_routes_struct route;
|
|
|
|
|
|
|
|
switch (cmd) {
|
|
|
|
case SIOCADDRT:
|
|
|
|
if (copy_from_user(&route, arg, sizeof(route)))
|
|
|
|
return -EFAULT;
|
|
|
|
return ax25_rt_add(&route);
|
|
|
|
|
|
|
|
case SIOCDELRT:
|
|
|
|
if (copy_from_user(&route, arg, sizeof(route)))
|
|
|
|
return -EFAULT;
|
|
|
|
return ax25_rt_del(&route);
|
|
|
|
|
|
|
|
case SIOCAX25OPTRT:
|
|
|
|
if (copy_from_user(&rt_option, arg, sizeof(rt_option)))
|
|
|
|
return -EFAULT;
|
|
|
|
return ax25_rt_opt(&rt_option);
|
|
|
|
|
|
|
|
default:
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef CONFIG_PROC_FS
|
|
|
|
|
|
|
|
static void *ax25_rt_seq_start(struct seq_file *seq, loff_t *pos)
|
2008-01-14 14:29:41 +08:00
|
|
|
__acquires(ax25_route_lock)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
struct ax25_route *ax25_rt;
|
|
|
|
int i = 1;
|
2007-02-09 22:24:31 +08:00
|
|
|
|
|
|
|
read_lock(&ax25_route_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
if (*pos == 0)
|
|
|
|
return SEQ_START_TOKEN;
|
|
|
|
|
|
|
|
for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
|
|
|
|
if (i == *pos)
|
|
|
|
return ax25_rt;
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *ax25_rt_seq_next(struct seq_file *seq, void *v, loff_t *pos)
|
|
|
|
{
|
|
|
|
++*pos;
|
2007-02-09 22:24:31 +08:00
|
|
|
return (v == SEQ_START_TOKEN) ? ax25_route_list :
|
2005-04-17 06:20:36 +08:00
|
|
|
((struct ax25_route *) v)->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ax25_rt_seq_stop(struct seq_file *seq, void *v)
|
2008-01-14 14:29:41 +08:00
|
|
|
__releases(ax25_route_lock)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
read_unlock(&ax25_route_lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int ax25_rt_seq_show(struct seq_file *seq, void *v)
|
|
|
|
{
|
2005-09-07 06:49:39 +08:00
|
|
|
char buf[11];
|
|
|
|
|
2005-04-17 06:20:36 +08:00
|
|
|
if (v == SEQ_START_TOKEN)
|
|
|
|
seq_puts(seq, "callsign dev mode digipeaters\n");
|
|
|
|
else {
|
|
|
|
struct ax25_route *ax25_rt = v;
|
|
|
|
const char *callsign;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0)
|
|
|
|
callsign = "default";
|
|
|
|
else
|
2005-09-07 06:49:39 +08:00
|
|
|
callsign = ax2asc(buf, &ax25_rt->callsign);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
seq_printf(seq, "%-9s %-4s",
|
|
|
|
callsign,
|
|
|
|
ax25_rt->dev ? ax25_rt->dev->name : "???");
|
|
|
|
|
|
|
|
switch (ax25_rt->ip_mode) {
|
|
|
|
case 'V':
|
|
|
|
seq_puts(seq, " vc");
|
|
|
|
break;
|
|
|
|
case 'D':
|
|
|
|
seq_puts(seq, " dg");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
seq_puts(seq, " *");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ax25_rt->digipeat != NULL)
|
|
|
|
for (i = 0; i < ax25_rt->digipeat->ndigi; i++)
|
2005-09-07 06:49:39 +08:00
|
|
|
seq_printf(seq, " %s",
|
|
|
|
ax2asc(buf, &ax25_rt->digipeat->calls[i]));
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
seq_puts(seq, "\n");
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-04-14 01:44:18 +08:00
|
|
|
const struct seq_operations ax25_rt_seqops = {
|
2005-04-17 06:20:36 +08:00
|
|
|
.start = ax25_rt_seq_start,
|
|
|
|
.next = ax25_rt_seq_next,
|
|
|
|
.stop = ax25_rt_seq_stop,
|
|
|
|
.show = ax25_rt_seq_show,
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find AX.25 route
|
|
|
|
*
|
2006-05-04 14:22:36 +08:00
|
|
|
* Only routes with a reference count of zero can be destroyed.
|
ax25: fix possible use-after-free
syzbot found that ax25 routes where not properly protected
against concurrent use [1].
In this particular report the bug happened while
copying ax25->digipeat.
Fix this problem by making sure we call ax25_get_route()
while ax25_route_lock is held, so that no modification
could happen while using the route.
The current two ax25_get_route() callers do not sleep,
so this change should be fine.
Once we do that, ax25_get_route() no longer needs to
grab a reference on the found route.
[1]
ax25_connect(): syz-executor0 uses autobind, please contact jreuter@yaina.de
BUG: KASAN: use-after-free in memcpy include/linux/string.h:352 [inline]
BUG: KASAN: use-after-free in kmemdup+0x42/0x60 mm/util.c:113
Read of size 66 at addr ffff888066641a80 by task syz-executor2/531
ax25_connect(): syz-executor0 uses autobind, please contact jreuter@yaina.de
CPU: 1 PID: 531 Comm: syz-executor2 Not tainted 5.0.0-rc2+ #10
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+0x1db/0x2d0 lib/dump_stack.c:113
print_address_description.cold+0x7c/0x20d mm/kasan/report.c:187
kasan_report.cold+0x1b/0x40 mm/kasan/report.c:317
check_memory_region_inline mm/kasan/generic.c:185 [inline]
check_memory_region+0x123/0x190 mm/kasan/generic.c:191
memcpy+0x24/0x50 mm/kasan/common.c:130
memcpy include/linux/string.h:352 [inline]
kmemdup+0x42/0x60 mm/util.c:113
kmemdup include/linux/string.h:425 [inline]
ax25_rt_autobind+0x25d/0x750 net/ax25/ax25_route.c:424
ax25_connect.cold+0x30/0xa4 net/ax25/af_ax25.c:1224
__sys_connect+0x357/0x490 net/socket.c:1664
__do_sys_connect net/socket.c:1675 [inline]
__se_sys_connect net/socket.c:1672 [inline]
__x64_sys_connect+0x73/0xb0 net/socket.c:1672
do_syscall_64+0x1a3/0x800 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x458099
Code: 6d b7 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 3b b7 fb ff c3 66 2e 0f 1f 84 00 00 00 00
RSP: 002b:00007f870ee22c78 EFLAGS: 00000246 ORIG_RAX: 000000000000002a
RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 0000000000458099
RDX: 0000000000000048 RSI: 0000000020000080 RDI: 0000000000000005
RBP: 000000000073bf00 R08: 0000000000000000 R09: 0000000000000000
ax25_connect(): syz-executor4 uses autobind, please contact jreuter@yaina.de
R10: 0000000000000000 R11: 0000000000000246 R12: 00007f870ee236d4
R13: 00000000004be48e R14: 00000000004ce9a8 R15: 00000000ffffffff
Allocated by task 526:
save_stack+0x45/0xd0 mm/kasan/common.c:73
set_track mm/kasan/common.c:85 [inline]
__kasan_kmalloc mm/kasan/common.c:496 [inline]
__kasan_kmalloc.constprop.0+0xcf/0xe0 mm/kasan/common.c:469
kasan_kmalloc+0x9/0x10 mm/kasan/common.c:504
ax25_connect(): syz-executor5 uses autobind, please contact jreuter@yaina.de
kmem_cache_alloc_trace+0x151/0x760 mm/slab.c:3609
kmalloc include/linux/slab.h:545 [inline]
ax25_rt_add net/ax25/ax25_route.c:95 [inline]
ax25_rt_ioctl+0x3b9/0x1270 net/ax25/ax25_route.c:233
ax25_ioctl+0x322/0x10b0 net/ax25/af_ax25.c:1763
sock_do_ioctl+0xe2/0x400 net/socket.c:950
sock_ioctl+0x32f/0x6c0 net/socket.c:1074
vfs_ioctl fs/ioctl.c:46 [inline]
file_ioctl fs/ioctl.c:509 [inline]
do_vfs_ioctl+0x107b/0x17d0 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+0x1a3/0x800 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
ax25_connect(): syz-executor5 uses autobind, please contact jreuter@yaina.de
Freed by task 550:
save_stack+0x45/0xd0 mm/kasan/common.c:73
set_track mm/kasan/common.c:85 [inline]
__kasan_slab_free+0x102/0x150 mm/kasan/common.c:458
kasan_slab_free+0xe/0x10 mm/kasan/common.c:466
__cache_free mm/slab.c:3487 [inline]
kfree+0xcf/0x230 mm/slab.c:3806
ax25_rt_add net/ax25/ax25_route.c:92 [inline]
ax25_rt_ioctl+0x304/0x1270 net/ax25/ax25_route.c:233
ax25_ioctl+0x322/0x10b0 net/ax25/af_ax25.c:1763
sock_do_ioctl+0xe2/0x400 net/socket.c:950
sock_ioctl+0x32f/0x6c0 net/socket.c:1074
vfs_ioctl fs/ioctl.c:46 [inline]
file_ioctl fs/ioctl.c:509 [inline]
do_vfs_ioctl+0x107b/0x17d0 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+0x1a3/0x800 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
The buggy address belongs to the object at ffff888066641a80
which belongs to the cache kmalloc-96 of size 96
The buggy address is located 0 bytes inside of
96-byte region [ffff888066641a80, ffff888066641ae0)
The buggy address belongs to the page:
page:ffffea0001999040 count:1 mapcount:0 mapping:ffff88812c3f04c0 index:0x0
flags: 0x1fffc0000000200(slab)
ax25_connect(): syz-executor4 uses autobind, please contact jreuter@yaina.de
raw: 01fffc0000000200 ffffea0001817948 ffffea0002341dc8 ffff88812c3f04c0
raw: 0000000000000000 ffff888066641000 0000000100000020 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff888066641980: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
ffff888066641a00: 00 00 00 00 00 00 00 00 02 fc fc fc fc fc fc fc
>ffff888066641a80: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
^
ffff888066641b00: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
ffff888066641b80: 00 00 00 00 00 00 00 00 00 00 00 00 fc fc fc fc
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-01-23 02:40:59 +08:00
|
|
|
* Must be called with ax25_route_lock read locked.
|
2005-04-17 06:20:36 +08:00
|
|
|
*/
|
2006-07-04 10:30:18 +08:00
|
|
|
ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev)
|
2005-04-17 06:20:36 +08:00
|
|
|
{
|
|
|
|
ax25_route *ax25_spe_rt = NULL;
|
|
|
|
ax25_route *ax25_def_rt = NULL;
|
|
|
|
ax25_route *ax25_rt;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Bind to the physical interface we heard them on, or the default
|
|
|
|
* route if none is found;
|
|
|
|
*/
|
|
|
|
for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) {
|
|
|
|
if (dev == NULL) {
|
|
|
|
if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev != NULL)
|
|
|
|
ax25_spe_rt = ax25_rt;
|
|
|
|
if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev != NULL)
|
|
|
|
ax25_def_rt = ax25_rt;
|
|
|
|
} else {
|
|
|
|
if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev == dev)
|
|
|
|
ax25_spe_rt = ax25_rt;
|
|
|
|
if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0 && ax25_rt->dev == dev)
|
|
|
|
ax25_def_rt = ax25_rt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ax25_rt = ax25_def_rt;
|
|
|
|
if (ax25_spe_rt != NULL)
|
|
|
|
ax25_rt = ax25_spe_rt;
|
|
|
|
|
|
|
|
return ax25_rt;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Adjust path: If you specify a default route and want to connect
|
|
|
|
* a target on the digipeater path but w/o having a special route
|
|
|
|
* set before, the path has to be truncated from your target on.
|
|
|
|
*/
|
|
|
|
static inline void ax25_adjust_path(ax25_address *addr, ax25_digi *digipeat)
|
|
|
|
{
|
|
|
|
int k;
|
|
|
|
|
|
|
|
for (k = 0; k < digipeat->ndigi; k++) {
|
|
|
|
if (ax25cmp(addr, &digipeat->calls[k]) == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
digipeat->ndigi = k;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find which interface to use.
|
|
|
|
*/
|
|
|
|
int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
|
|
|
|
{
|
2005-08-24 01:11:45 +08:00
|
|
|
ax25_uid_assoc *user;
|
2005-04-17 06:20:36 +08:00
|
|
|
ax25_route *ax25_rt;
|
2010-08-16 14:26:57 +08:00
|
|
|
int err = 0;
|
2005-04-17 06:20:36 +08:00
|
|
|
|
ax25: fix possible use-after-free
syzbot found that ax25 routes where not properly protected
against concurrent use [1].
In this particular report the bug happened while
copying ax25->digipeat.
Fix this problem by making sure we call ax25_get_route()
while ax25_route_lock is held, so that no modification
could happen while using the route.
The current two ax25_get_route() callers do not sleep,
so this change should be fine.
Once we do that, ax25_get_route() no longer needs to
grab a reference on the found route.
[1]
ax25_connect(): syz-executor0 uses autobind, please contact jreuter@yaina.de
BUG: KASAN: use-after-free in memcpy include/linux/string.h:352 [inline]
BUG: KASAN: use-after-free in kmemdup+0x42/0x60 mm/util.c:113
Read of size 66 at addr ffff888066641a80 by task syz-executor2/531
ax25_connect(): syz-executor0 uses autobind, please contact jreuter@yaina.de
CPU: 1 PID: 531 Comm: syz-executor2 Not tainted 5.0.0-rc2+ #10
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+0x1db/0x2d0 lib/dump_stack.c:113
print_address_description.cold+0x7c/0x20d mm/kasan/report.c:187
kasan_report.cold+0x1b/0x40 mm/kasan/report.c:317
check_memory_region_inline mm/kasan/generic.c:185 [inline]
check_memory_region+0x123/0x190 mm/kasan/generic.c:191
memcpy+0x24/0x50 mm/kasan/common.c:130
memcpy include/linux/string.h:352 [inline]
kmemdup+0x42/0x60 mm/util.c:113
kmemdup include/linux/string.h:425 [inline]
ax25_rt_autobind+0x25d/0x750 net/ax25/ax25_route.c:424
ax25_connect.cold+0x30/0xa4 net/ax25/af_ax25.c:1224
__sys_connect+0x357/0x490 net/socket.c:1664
__do_sys_connect net/socket.c:1675 [inline]
__se_sys_connect net/socket.c:1672 [inline]
__x64_sys_connect+0x73/0xb0 net/socket.c:1672
do_syscall_64+0x1a3/0x800 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x458099
Code: 6d b7 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 3b b7 fb ff c3 66 2e 0f 1f 84 00 00 00 00
RSP: 002b:00007f870ee22c78 EFLAGS: 00000246 ORIG_RAX: 000000000000002a
RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 0000000000458099
RDX: 0000000000000048 RSI: 0000000020000080 RDI: 0000000000000005
RBP: 000000000073bf00 R08: 0000000000000000 R09: 0000000000000000
ax25_connect(): syz-executor4 uses autobind, please contact jreuter@yaina.de
R10: 0000000000000000 R11: 0000000000000246 R12: 00007f870ee236d4
R13: 00000000004be48e R14: 00000000004ce9a8 R15: 00000000ffffffff
Allocated by task 526:
save_stack+0x45/0xd0 mm/kasan/common.c:73
set_track mm/kasan/common.c:85 [inline]
__kasan_kmalloc mm/kasan/common.c:496 [inline]
__kasan_kmalloc.constprop.0+0xcf/0xe0 mm/kasan/common.c:469
kasan_kmalloc+0x9/0x10 mm/kasan/common.c:504
ax25_connect(): syz-executor5 uses autobind, please contact jreuter@yaina.de
kmem_cache_alloc_trace+0x151/0x760 mm/slab.c:3609
kmalloc include/linux/slab.h:545 [inline]
ax25_rt_add net/ax25/ax25_route.c:95 [inline]
ax25_rt_ioctl+0x3b9/0x1270 net/ax25/ax25_route.c:233
ax25_ioctl+0x322/0x10b0 net/ax25/af_ax25.c:1763
sock_do_ioctl+0xe2/0x400 net/socket.c:950
sock_ioctl+0x32f/0x6c0 net/socket.c:1074
vfs_ioctl fs/ioctl.c:46 [inline]
file_ioctl fs/ioctl.c:509 [inline]
do_vfs_ioctl+0x107b/0x17d0 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+0x1a3/0x800 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
ax25_connect(): syz-executor5 uses autobind, please contact jreuter@yaina.de
Freed by task 550:
save_stack+0x45/0xd0 mm/kasan/common.c:73
set_track mm/kasan/common.c:85 [inline]
__kasan_slab_free+0x102/0x150 mm/kasan/common.c:458
kasan_slab_free+0xe/0x10 mm/kasan/common.c:466
__cache_free mm/slab.c:3487 [inline]
kfree+0xcf/0x230 mm/slab.c:3806
ax25_rt_add net/ax25/ax25_route.c:92 [inline]
ax25_rt_ioctl+0x304/0x1270 net/ax25/ax25_route.c:233
ax25_ioctl+0x322/0x10b0 net/ax25/af_ax25.c:1763
sock_do_ioctl+0xe2/0x400 net/socket.c:950
sock_ioctl+0x32f/0x6c0 net/socket.c:1074
vfs_ioctl fs/ioctl.c:46 [inline]
file_ioctl fs/ioctl.c:509 [inline]
do_vfs_ioctl+0x107b/0x17d0 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+0x1a3/0x800 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
The buggy address belongs to the object at ffff888066641a80
which belongs to the cache kmalloc-96 of size 96
The buggy address is located 0 bytes inside of
96-byte region [ffff888066641a80, ffff888066641ae0)
The buggy address belongs to the page:
page:ffffea0001999040 count:1 mapcount:0 mapping:ffff88812c3f04c0 index:0x0
flags: 0x1fffc0000000200(slab)
ax25_connect(): syz-executor4 uses autobind, please contact jreuter@yaina.de
raw: 01fffc0000000200 ffffea0001817948 ffffea0002341dc8 ffff88812c3f04c0
raw: 0000000000000000 ffff888066641000 0000000100000020 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff888066641980: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
ffff888066641a00: 00 00 00 00 00 00 00 00 02 fc fc fc fc fc fc fc
>ffff888066641a80: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
^
ffff888066641b00: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
ffff888066641b80: 00 00 00 00 00 00 00 00 00 00 00 00 fc fc fc fc
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-01-23 02:40:59 +08:00
|
|
|
ax25_route_lock_use();
|
|
|
|
ax25_rt = ax25_get_route(addr, NULL);
|
|
|
|
if (!ax25_rt) {
|
|
|
|
ax25_route_lock_unuse();
|
2005-04-17 06:20:36 +08:00
|
|
|
return -EHOSTUNREACH;
|
ax25: fix possible use-after-free
syzbot found that ax25 routes where not properly protected
against concurrent use [1].
In this particular report the bug happened while
copying ax25->digipeat.
Fix this problem by making sure we call ax25_get_route()
while ax25_route_lock is held, so that no modification
could happen while using the route.
The current two ax25_get_route() callers do not sleep,
so this change should be fine.
Once we do that, ax25_get_route() no longer needs to
grab a reference on the found route.
[1]
ax25_connect(): syz-executor0 uses autobind, please contact jreuter@yaina.de
BUG: KASAN: use-after-free in memcpy include/linux/string.h:352 [inline]
BUG: KASAN: use-after-free in kmemdup+0x42/0x60 mm/util.c:113
Read of size 66 at addr ffff888066641a80 by task syz-executor2/531
ax25_connect(): syz-executor0 uses autobind, please contact jreuter@yaina.de
CPU: 1 PID: 531 Comm: syz-executor2 Not tainted 5.0.0-rc2+ #10
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+0x1db/0x2d0 lib/dump_stack.c:113
print_address_description.cold+0x7c/0x20d mm/kasan/report.c:187
kasan_report.cold+0x1b/0x40 mm/kasan/report.c:317
check_memory_region_inline mm/kasan/generic.c:185 [inline]
check_memory_region+0x123/0x190 mm/kasan/generic.c:191
memcpy+0x24/0x50 mm/kasan/common.c:130
memcpy include/linux/string.h:352 [inline]
kmemdup+0x42/0x60 mm/util.c:113
kmemdup include/linux/string.h:425 [inline]
ax25_rt_autobind+0x25d/0x750 net/ax25/ax25_route.c:424
ax25_connect.cold+0x30/0xa4 net/ax25/af_ax25.c:1224
__sys_connect+0x357/0x490 net/socket.c:1664
__do_sys_connect net/socket.c:1675 [inline]
__se_sys_connect net/socket.c:1672 [inline]
__x64_sys_connect+0x73/0xb0 net/socket.c:1672
do_syscall_64+0x1a3/0x800 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x458099
Code: 6d b7 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 3b b7 fb ff c3 66 2e 0f 1f 84 00 00 00 00
RSP: 002b:00007f870ee22c78 EFLAGS: 00000246 ORIG_RAX: 000000000000002a
RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 0000000000458099
RDX: 0000000000000048 RSI: 0000000020000080 RDI: 0000000000000005
RBP: 000000000073bf00 R08: 0000000000000000 R09: 0000000000000000
ax25_connect(): syz-executor4 uses autobind, please contact jreuter@yaina.de
R10: 0000000000000000 R11: 0000000000000246 R12: 00007f870ee236d4
R13: 00000000004be48e R14: 00000000004ce9a8 R15: 00000000ffffffff
Allocated by task 526:
save_stack+0x45/0xd0 mm/kasan/common.c:73
set_track mm/kasan/common.c:85 [inline]
__kasan_kmalloc mm/kasan/common.c:496 [inline]
__kasan_kmalloc.constprop.0+0xcf/0xe0 mm/kasan/common.c:469
kasan_kmalloc+0x9/0x10 mm/kasan/common.c:504
ax25_connect(): syz-executor5 uses autobind, please contact jreuter@yaina.de
kmem_cache_alloc_trace+0x151/0x760 mm/slab.c:3609
kmalloc include/linux/slab.h:545 [inline]
ax25_rt_add net/ax25/ax25_route.c:95 [inline]
ax25_rt_ioctl+0x3b9/0x1270 net/ax25/ax25_route.c:233
ax25_ioctl+0x322/0x10b0 net/ax25/af_ax25.c:1763
sock_do_ioctl+0xe2/0x400 net/socket.c:950
sock_ioctl+0x32f/0x6c0 net/socket.c:1074
vfs_ioctl fs/ioctl.c:46 [inline]
file_ioctl fs/ioctl.c:509 [inline]
do_vfs_ioctl+0x107b/0x17d0 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+0x1a3/0x800 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
ax25_connect(): syz-executor5 uses autobind, please contact jreuter@yaina.de
Freed by task 550:
save_stack+0x45/0xd0 mm/kasan/common.c:73
set_track mm/kasan/common.c:85 [inline]
__kasan_slab_free+0x102/0x150 mm/kasan/common.c:458
kasan_slab_free+0xe/0x10 mm/kasan/common.c:466
__cache_free mm/slab.c:3487 [inline]
kfree+0xcf/0x230 mm/slab.c:3806
ax25_rt_add net/ax25/ax25_route.c:92 [inline]
ax25_rt_ioctl+0x304/0x1270 net/ax25/ax25_route.c:233
ax25_ioctl+0x322/0x10b0 net/ax25/af_ax25.c:1763
sock_do_ioctl+0xe2/0x400 net/socket.c:950
sock_ioctl+0x32f/0x6c0 net/socket.c:1074
vfs_ioctl fs/ioctl.c:46 [inline]
file_ioctl fs/ioctl.c:509 [inline]
do_vfs_ioctl+0x107b/0x17d0 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+0x1a3/0x800 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
The buggy address belongs to the object at ffff888066641a80
which belongs to the cache kmalloc-96 of size 96
The buggy address is located 0 bytes inside of
96-byte region [ffff888066641a80, ffff888066641ae0)
The buggy address belongs to the page:
page:ffffea0001999040 count:1 mapcount:0 mapping:ffff88812c3f04c0 index:0x0
flags: 0x1fffc0000000200(slab)
ax25_connect(): syz-executor4 uses autobind, please contact jreuter@yaina.de
raw: 01fffc0000000200 ffffea0001817948 ffffea0002341dc8 ffff88812c3f04c0
raw: 0000000000000000 ffff888066641000 0000000100000020 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff888066641980: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
ffff888066641a00: 00 00 00 00 00 00 00 00 02 fc fc fc fc fc fc fc
>ffff888066641a80: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
^
ffff888066641b00: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
ffff888066641b80: 00 00 00 00 00 00 00 00 00 00 00 00 fc fc fc fc
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-01-23 02:40:59 +08:00
|
|
|
}
|
2005-04-17 06:20:36 +08:00
|
|
|
if ((ax25->ax25_dev = ax25_dev_ax25dev(ax25_rt->dev)) == NULL) {
|
|
|
|
err = -EHOSTUNREACH;
|
|
|
|
goto put;
|
|
|
|
}
|
|
|
|
|
2008-11-14 07:39:06 +08:00
|
|
|
user = ax25_findbyuid(current_euid());
|
2005-08-24 01:11:45 +08:00
|
|
|
if (user) {
|
|
|
|
ax25->source_addr = user->call;
|
|
|
|
ax25_uid_put(user);
|
|
|
|
} else {
|
2005-04-17 06:20:36 +08:00
|
|
|
if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) {
|
|
|
|
err = -EPERM;
|
|
|
|
goto put;
|
|
|
|
}
|
2005-08-24 01:11:45 +08:00
|
|
|
ax25->source_addr = *(ax25_address *)ax25->ax25_dev->dev->dev_addr;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ax25_rt->digipeat != NULL) {
|
2006-11-17 22:43:07 +08:00
|
|
|
ax25->digipeat = kmemdup(ax25_rt->digipeat, sizeof(ax25_digi),
|
|
|
|
GFP_ATOMIC);
|
|
|
|
if (ax25->digipeat == NULL) {
|
2005-04-17 06:20:36 +08:00
|
|
|
err = -ENOMEM;
|
|
|
|
goto put;
|
|
|
|
}
|
|
|
|
ax25_adjust_path(addr, ax25->digipeat);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ax25->sk != NULL) {
|
2019-06-16 07:40:52 +08:00
|
|
|
local_bh_disable();
|
2005-04-17 06:20:36 +08:00
|
|
|
bh_lock_sock(ax25->sk);
|
|
|
|
sock_reset_flag(ax25->sk, SOCK_ZAPPED);
|
|
|
|
bh_unlock_sock(ax25->sk);
|
2019-06-16 07:40:52 +08:00
|
|
|
local_bh_enable();
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
put:
|
ax25: fix possible use-after-free
syzbot found that ax25 routes where not properly protected
against concurrent use [1].
In this particular report the bug happened while
copying ax25->digipeat.
Fix this problem by making sure we call ax25_get_route()
while ax25_route_lock is held, so that no modification
could happen while using the route.
The current two ax25_get_route() callers do not sleep,
so this change should be fine.
Once we do that, ax25_get_route() no longer needs to
grab a reference on the found route.
[1]
ax25_connect(): syz-executor0 uses autobind, please contact jreuter@yaina.de
BUG: KASAN: use-after-free in memcpy include/linux/string.h:352 [inline]
BUG: KASAN: use-after-free in kmemdup+0x42/0x60 mm/util.c:113
Read of size 66 at addr ffff888066641a80 by task syz-executor2/531
ax25_connect(): syz-executor0 uses autobind, please contact jreuter@yaina.de
CPU: 1 PID: 531 Comm: syz-executor2 Not tainted 5.0.0-rc2+ #10
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+0x1db/0x2d0 lib/dump_stack.c:113
print_address_description.cold+0x7c/0x20d mm/kasan/report.c:187
kasan_report.cold+0x1b/0x40 mm/kasan/report.c:317
check_memory_region_inline mm/kasan/generic.c:185 [inline]
check_memory_region+0x123/0x190 mm/kasan/generic.c:191
memcpy+0x24/0x50 mm/kasan/common.c:130
memcpy include/linux/string.h:352 [inline]
kmemdup+0x42/0x60 mm/util.c:113
kmemdup include/linux/string.h:425 [inline]
ax25_rt_autobind+0x25d/0x750 net/ax25/ax25_route.c:424
ax25_connect.cold+0x30/0xa4 net/ax25/af_ax25.c:1224
__sys_connect+0x357/0x490 net/socket.c:1664
__do_sys_connect net/socket.c:1675 [inline]
__se_sys_connect net/socket.c:1672 [inline]
__x64_sys_connect+0x73/0xb0 net/socket.c:1672
do_syscall_64+0x1a3/0x800 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
RIP: 0033:0x458099
Code: 6d b7 fb ff c3 66 2e 0f 1f 84 00 00 00 00 00 66 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 0f 83 3b b7 fb ff c3 66 2e 0f 1f 84 00 00 00 00
RSP: 002b:00007f870ee22c78 EFLAGS: 00000246 ORIG_RAX: 000000000000002a
RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 0000000000458099
RDX: 0000000000000048 RSI: 0000000020000080 RDI: 0000000000000005
RBP: 000000000073bf00 R08: 0000000000000000 R09: 0000000000000000
ax25_connect(): syz-executor4 uses autobind, please contact jreuter@yaina.de
R10: 0000000000000000 R11: 0000000000000246 R12: 00007f870ee236d4
R13: 00000000004be48e R14: 00000000004ce9a8 R15: 00000000ffffffff
Allocated by task 526:
save_stack+0x45/0xd0 mm/kasan/common.c:73
set_track mm/kasan/common.c:85 [inline]
__kasan_kmalloc mm/kasan/common.c:496 [inline]
__kasan_kmalloc.constprop.0+0xcf/0xe0 mm/kasan/common.c:469
kasan_kmalloc+0x9/0x10 mm/kasan/common.c:504
ax25_connect(): syz-executor5 uses autobind, please contact jreuter@yaina.de
kmem_cache_alloc_trace+0x151/0x760 mm/slab.c:3609
kmalloc include/linux/slab.h:545 [inline]
ax25_rt_add net/ax25/ax25_route.c:95 [inline]
ax25_rt_ioctl+0x3b9/0x1270 net/ax25/ax25_route.c:233
ax25_ioctl+0x322/0x10b0 net/ax25/af_ax25.c:1763
sock_do_ioctl+0xe2/0x400 net/socket.c:950
sock_ioctl+0x32f/0x6c0 net/socket.c:1074
vfs_ioctl fs/ioctl.c:46 [inline]
file_ioctl fs/ioctl.c:509 [inline]
do_vfs_ioctl+0x107b/0x17d0 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+0x1a3/0x800 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
ax25_connect(): syz-executor5 uses autobind, please contact jreuter@yaina.de
Freed by task 550:
save_stack+0x45/0xd0 mm/kasan/common.c:73
set_track mm/kasan/common.c:85 [inline]
__kasan_slab_free+0x102/0x150 mm/kasan/common.c:458
kasan_slab_free+0xe/0x10 mm/kasan/common.c:466
__cache_free mm/slab.c:3487 [inline]
kfree+0xcf/0x230 mm/slab.c:3806
ax25_rt_add net/ax25/ax25_route.c:92 [inline]
ax25_rt_ioctl+0x304/0x1270 net/ax25/ax25_route.c:233
ax25_ioctl+0x322/0x10b0 net/ax25/af_ax25.c:1763
sock_do_ioctl+0xe2/0x400 net/socket.c:950
sock_ioctl+0x32f/0x6c0 net/socket.c:1074
vfs_ioctl fs/ioctl.c:46 [inline]
file_ioctl fs/ioctl.c:509 [inline]
do_vfs_ioctl+0x107b/0x17d0 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+0x1a3/0x800 arch/x86/entry/common.c:290
entry_SYSCALL_64_after_hwframe+0x49/0xbe
The buggy address belongs to the object at ffff888066641a80
which belongs to the cache kmalloc-96 of size 96
The buggy address is located 0 bytes inside of
96-byte region [ffff888066641a80, ffff888066641ae0)
The buggy address belongs to the page:
page:ffffea0001999040 count:1 mapcount:0 mapping:ffff88812c3f04c0 index:0x0
flags: 0x1fffc0000000200(slab)
ax25_connect(): syz-executor4 uses autobind, please contact jreuter@yaina.de
raw: 01fffc0000000200 ffffea0001817948 ffffea0002341dc8 ffff88812c3f04c0
raw: 0000000000000000 ffff888066641000 0000000100000020 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff888066641980: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
ffff888066641a00: 00 00 00 00 00 00 00 00 02 fc fc fc fc fc fc fc
>ffff888066641a80: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
^
ffff888066641b00: fb fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
ffff888066641b80: 00 00 00 00 00 00 00 00 00 00 00 00 fc fc fc fc
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2019-01-23 02:40:59 +08:00
|
|
|
ax25_route_lock_unuse();
|
2010-08-16 14:26:57 +08:00
|
|
|
return err;
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
struct sk_buff *ax25_rt_build_path(struct sk_buff *skb, ax25_address *src,
|
|
|
|
ax25_address *dest, ax25_digi *digi)
|
|
|
|
{
|
|
|
|
struct sk_buff *skbn;
|
|
|
|
unsigned char *bp;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
len = digi->ndigi * AX25_ADDR_LEN;
|
|
|
|
|
|
|
|
if (skb_headroom(skb) < len) {
|
|
|
|
if ((skbn = skb_realloc_headroom(skb, len)) == NULL) {
|
|
|
|
printk(KERN_CRIT "AX.25: ax25_dg_build_path - out of memory\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (skb->sk != NULL)
|
|
|
|
skb_set_owner_w(skbn, skb->sk);
|
|
|
|
|
2012-06-04 09:17:19 +08:00
|
|
|
consume_skb(skb);
|
2005-04-17 06:20:36 +08:00
|
|
|
|
|
|
|
skb = skbn;
|
|
|
|
}
|
|
|
|
|
|
|
|
bp = skb_push(skb, len);
|
|
|
|
|
|
|
|
ax25_addr_build(bp, src, dest, digi, AX25_COMMAND, AX25_MODULUS);
|
|
|
|
|
|
|
|
return skb;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Free all memory associated with routing structures.
|
|
|
|
*/
|
|
|
|
void __exit ax25_rt_free(void)
|
|
|
|
{
|
|
|
|
ax25_route *s, *ax25_rt = ax25_route_list;
|
|
|
|
|
2008-02-12 13:26:43 +08:00
|
|
|
write_lock_bh(&ax25_route_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
while (ax25_rt != NULL) {
|
|
|
|
s = ax25_rt;
|
|
|
|
ax25_rt = ax25_rt->next;
|
|
|
|
|
2005-11-09 01:41:34 +08:00
|
|
|
kfree(s->digipeat);
|
2005-04-17 06:20:36 +08:00
|
|
|
kfree(s);
|
|
|
|
}
|
2008-02-12 13:26:43 +08:00
|
|
|
write_unlock_bh(&ax25_route_lock);
|
2005-04-17 06:20:36 +08:00
|
|
|
}
|