This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug runtime/16718] New: kernel crash in _stp_copy_from_user()


https://sourceware.org/bugzilla/show_bug.cgi?id=16718

            Bug ID: 16718
           Summary: kernel crash in  _stp_copy_from_user()
           Product: systemtap
           Version: unspecified
            Status: NEW
          Severity: normal
          Priority: P2
         Component: runtime
          Assignee: systemtap at sourceware dot org
          Reporter: dsmith at redhat dot com

I was doing some testing on bug #16716, passing a value of -1 as the 'addrlen'
argument to the bind syscall. This crashed the kernel:

====
[  137.144041] BUG: unable to handle kernel paging request at
ffff88007a77e000
[  137.144041] IP: [<ffffffff813d5ed2>] memset+0x42/0xb0
[  137.144041] PGD 2dc8067 PUD 2dcb067 PMD 78eee063 PTE 800000007a77e161
[  137.144041] Oops: 0003 [#1] SMP
[  137.144041] Modules linked in:
stap_49e2cbecb8a3c3d38ae6787d3e13b19e__1151(OF) nfsv3 rpcsec_gss_krb5
nfsv4 dns_resolver nfs fscache ip6t_rpfilter ip6t_REJECT xt_conntrack
cfg80211 rfkill ebtable_nat ebtable_broute bridge stp llc ebtable_filter
ebtables ip6table_nat nf_conntrack_ipv6 nf_defrag_ipv6 nf_nat_ipv6
ip6table_mangle ip6table_security ip6table_raw ip6table_filter
ip6_tables iptable_nat nf_conntrack_ipv4 nf_defrag_ipv4 nf_nat_ipv4
nf_nat nf_conntrack iptable_mangle iptable_security iptable_raw ppdev
kvm_amd kvm snd_hda_codec_generic snd_hda_intel snd_hda_codec serio_raw
snd_hwdep virtio_balloon snd_seq virtio_console snd_seq_device
virtio_net snd_pcm parport_pc pvpanic parport snd_timer snd i2c_piix4
soundcore nfsd auth_rpcgss nfs_acl lockd sunrpc virtio_blk qxl
drm_kms_helper ttm drm virtio_pci virtio_ring virtio i2c_core
ata_generic pata_acpi
[  137.144041] CPU: 1 PID: 1153 Comm: bind64 Tainted: GF          O
3.14.0-0.rc5.git2.1.fc21.x86_64 #1
[  137.144041] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
[  137.144041] task: ffff88007aed0000 ti: ffff88007ab80000 task.ti:
ffff88007ab80000
[  137.144041] RIP: 0010:[<ffffffff813d5ed2>]  [<ffffffff813d5ed2>]
memset+0x42/0xb0
[  137.144041] RSP: 0018:ffff88007ab81db0  EFLAGS: 00010007
[  137.144041] RAX: 0000000000000000 RBX: ffff88007a770000 RCX:
03fffffffffffc87
[  137.144041] RDX: ffffffffffffffff RSI: 0000000000000000 RDI:
ffff88007a77dfe0
[  137.144041] RBP: ffff88007ab81e10 R08: 00007fff27c52c10 R09:
0000000000000000
[  137.144041] R10: ffff88007a770220 R11: 3531363135353930 R12:
ffff88007a770f18
[  137.144041] R13: ffffffffffffffff R14: ffff88007a7704e8 R15:
ffff88007a771158
[  137.144041] FS:  00007f751d008740(0000) GS:ffff88007d400000(0000)
knlGS:0000000000000000
[  137.144041] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  137.144041] CR2: ffff88007a77e000 CR3: 0000000070f99000 CR4:
00000000000006e0
[  137.144041] Stack:
[  137.144041]  ffffffffa058f760 0000000000000028 ffff88007ab81de0
0000000000000002
[  137.144041]  ffff88007a770220 00007ffffffff000 0000000000000001
ffff88007ab81ed0
[  137.144041]  0000006b6eb55e04 ffffffffa0596ac0 ffffffff8166c251
ffff88007ab81ed0
[  137.144041] Call Trace:
[  137.144041]  [<ffffffffa058f760>] ? probe_2159+0xa70/0xf30
[stap_49e2cbecb8a3c3d38ae6787d3e13b19e__1151]
[  137.144041]  [<ffffffff8166c251>] ? SyS_bind+0x1/0x10
[  137.144041]  [<ffffffffa0591b21>] enter_kprobe_probe+0x161/0x310
[stap_49e2cbecb8a3c3d38ae6787d3e13b19e__1151]
[  137.144041]  [<ffffffff8166c251>] ? SyS_bind+0x1/0x10
[  137.144041]  [<ffffffff817df2fc>] kprobe_ftrace_handler+0xec/0x130
[  137.144041]  [<ffffffff8166c250>] ? SyS_socketpair+0x260/0x260
[  137.144041]  [<ffffffff817e5929>] ? system_call_fastpath+0x16/0x1b
[  137.144041]  [<ffffffff8116c746>] ftrace_ops_list_func+0x126/0x140
[  137.144041]  [<ffffffff817e56c2>] ftrace_regs_call+0x5/0x77
[  137.144041]  [<ffffffff8115472c>] ? __audit_syscall_entry+0x9c/0xf0
[  137.144041]  [<ffffffff8166c250>] ? SyS_socketpair+0x260/0x260
[  137.144041]  [<ffffffff8166c255>] ? SyS_bind+0x5/0x10
[  137.144041]  [<ffffffff817e5929>] ? system_call_fastpath+0x16/0x1b
[  137.144041] Code: f9 41 83 e1 07 75 70 48 89 d1 48 c1 e9 06 74 39 66
0f 1f 84 00 00 00 00 00 48 ff c9 48 89 07 48 89 47 08 48 89 47 10 48 89
47 18 <48> 89 47 20 48 89 47 28 48 89 47 30 48 89 47 38 48 8d 7f 40 75
[  137.144041] RIP  [<ffffffff813d5ed2>] memset+0x42/0xb0
[  137.144041]  RSP <ffff88007ab81db0>
[  137.144041] CR2: ffff88007a77e000
[  137.144041] ---[ end trace 5b5823bf3ac17712 ]---
[  137.144041] BUG: sleeping function called from invalid context at
kernel/locking/rwsem.c:20
[  137.144041] in_atomic(): 1, irqs_disabled(): 1, pid: 1153, name: bind64
[  137.144041] INFO: lockdep is turned off.
[  137.144041] irq event stamp: 3286
[  137.144041] hardirqs last  enabled at (3285): [<ffffffff8111bc59>]
current_kernel_time+0x69/0xd0
[  137.144041] hardirqs last disabled at (3286): [<ffffffff817df23e>]
kprobe_ftrace_handler+0x2e/0x130
[  137.144041] softirqs last  enabled at (3278): [<ffffffff81365620>]
sel_netnode_sid+0x2f0/0x380
[  137.144041] softirqs last disabled at (3276): [<ffffffff813654a2>]
sel_netnode_sid+0x172/0x380
[  137.144041] CPU: 1 PID: 1153 Comm: bind64 Tainted: GF     D    O
3.14.0-0.rc5.git2.1.fc21.x86_64 #1
[  137.144041] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
[  137.144041]  0000000000000000 00000000bcd95af8 ffff88007ab819f8
ffffffff817d1ad2
[  137.144041]  0000000000000000 ffff88007ab81a20 ffffffff810d0165
ffff8800759f8478
[  137.144041]  ffff8800759f84d8 ffff88007aed0000 ffff88007ab81a48
ffffffff817d995a
[  137.144041] Call Trace:
[  137.144041]  [<ffffffff817d1ad2>] dump_stack+0x4d/0x66
[  137.144041]  [<ffffffff810d0165>] __might_sleep+0x175/0x230
[  137.144041]  [<ffffffff817d995a>] down_read+0x2a/0xa0
[  137.144041]  [<ffffffff810aeb23>] exit_signals+0x33/0x150
[  137.144041]  [<ffffffff810995c2>] do_exit+0xd2/0xd00
[  137.144041]  [<ffffffff8110cff8>] ? kmsg_dump+0x1c8/0x250
[  137.144041]  [<ffffffff8110ce64>] ? kmsg_dump+0x34/0x250
[  137.144041]  [<ffffffff817dca3c>] oops_end+0x9c/0xe0
[  137.144041]  [<ffffffff817cbb32>] no_context+0x292/0x2b5
[  137.144041]  [<ffffffff817cbbd3>] __bad_area_nosemaphore+0x7e/0x1d5
[  137.144041]  [<ffffffff817cbd3d>] bad_area_nosemaphore+0x13/0x15
[  137.144041]  [<ffffffff817df811>] __do_page_fault+0xc1/0x600
[  137.144041]  [<ffffffff81199821>] ? irq_work_queue+0x71/0xc0
[  137.144041]  [<ffffffff8110b44c>] ? wake_up_klogd+0x3c/0x50
[  137.144041]  [<ffffffff817dfd5e>] do_page_fault+0xe/0x10
[  137.144041]  [<ffffffff817df388>] do_async_page_fault+0x28/0xa0
[  137.144041]  [<ffffffff817dbde8>] async_page_fault+0x28/0x30
[  137.144041]  [<ffffffff813d5ed2>] ? memset+0x42/0xb0
[  137.144041]  [<ffffffffa058f760>] ? probe_2159+0xa70/0xf30
[stap_49e2cbecb8a3c3d38ae6787d3e13b19e__1151]
[  137.144041]  [<ffffffff8166c251>] ? SyS_bind+0x1/0x10
[  137.144041]  [<ffffffffa0591b21>] enter_kprobe_probe+0x161/0x310
[stap_49e2cbecb8a3c3d38ae6787d3e13b19e__1151]
[  137.144041]  [<ffffffff8166c251>] ? SyS_bind+0x1/0x10
[  137.144041]  [<ffffffff817df2fc>] kprobe_ftrace_handler+0xec/0x130
[  137.144041]  [<ffffffff8166c250>] ? SyS_socketpair+0x260/0x260
[  137.144041]  [<ffffffff817e5929>] ? system_call_fastpath+0x16/0x1b
[  137.144041]  [<ffffffff8116c746>] ftrace_ops_list_func+0x126/0x140
[  137.144041]  [<ffffffff817e56c2>] ftrace_regs_call+0x5/0x77
[  137.144041]  [<ffffffff8115472c>] ? __audit_syscall_entry+0x9c/0xf0
[  137.144041]  [<ffffffff8166c250>] ? SyS_socketpair+0x260/0x260
[  137.144041]  [<ffffffff8166c255>] ? SyS_bind+0x5/0x10
[  137.144041]  [<ffffffff817e5929>] ? system_call_fastpath+0x16/0x1b
[  137.144041] note: bind64[1153] exited with preempt_count 3
[  138.281104] stap_49e2cbecb8a3c3d38ae6787d3e13b19e__1151 context[1]
stuck: kernel.function("SyS_bind@net/socket.c:1519").call
====

I tracked this down to a problem in _stp_copy_from_user(). The syscall.bind
probe alias ends up calling _struct_sockaddr_u_impl(). In this case, 'len' was
-1:

====
function _struct_sockaddr_u_impl:string(uaddr:long, len:long, what:long)
%{ /* pure */

//...

    size_t len = STAP_ARG_len < 128 ? STAP_ARG_len: 128;

// ...

    if (_stp_copy_from_user(CONTEXT->buf, ptr, len))
//...
}

If STAP_ARG_len is -1, len is -1 (since -1 is less than 128), which gets
passed to _stp_copy_from_user(). _stp_copy_from_user() takes an unsigned
value. I'm surprised the compiler didn't complain about signed vs.
unsigned here.


Notice how the last thing before async_page_fault() is memset() in the kernel
backtrace? I thought that was odd until I looked back at _stp_copy_from_user()
and saw this:

===
      if (access_ok(VERIFY_READ, src, count))
             count = __copy_from_user_inatomic(dst, src, count);
      else
             memset(dst, 0, count);
===

In this call, _stp_copy_from_user() got 18446744073709551615 as the length to
copy. The access_ok() call failed (correctly), since that many bytes couldn't
be accessed. So, then we try to zero out that many bytes. Since 'dst' wasn't
that large, we crashed the kernel.

I think the fix here is to make _stp_copy_from_user() just return -EFAULT if
access_ok() fails and let the caller handle things. Looking at all the calls to
_stp_copy_from_user(), all but one call doesn't expect the destination to be
cleared out on failure.

-- 
You are receiving this mail because:
You are the assignee for the bug.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]