diff options
author | Pawel Szewczyk <p.szewczyk@samsung.com> | 2015-05-14 14:14:11 +0200 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2015-05-14 14:04:57 -0500 |
commit | a25a23cc85a28090bf8ab0e750b48e7ab283ba8a (patch) | |
tree | d56583d07d7283e68d1df8b2d65795ffdf7f8e10 | |
parent | c94e289f195e0e13cf34d27f9338d28221a85751 (diff) |
usb: gadget: f_midi: fix segfault when reading empty id
When midi function is created, 'id' attribute is initialized with
SNDRV_DEFAULT_STR1, which is NULL pointer. Trying to read this attribute
before filling it ends up with segmentation fault.
This commit fix this issue by preventing null pointer dereference. Now
f_midi_opts_id_show() returns empty string when id is a null pointer.
Reproduction path:
$ mkdir functions/midi.0
$ cat functions/midi.0/id
[ 53.130132] Unable to handle kernel NULL pointer dereference at
virtual address 00000000
[ 53.132630] pgd = ec6cc000
[ 53.135308] [00000000] *pgd=6b759831, *pte=00000000, *ppte=00000000
[ 53.141530] Internal error: Oops: 17 [#1] PREEMPT SMP ARM
[ 53.146904] Modules linked in: usb_f_midi snd_rawmidi libcomposite
[ 53.153071] CPU: 1 PID: 2936 Comm: cat Not tainted
3.19.0-00041-gcf4b216 #7
[ 53.160010] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[ 53.166088] task: ee234c80 ti: ec764000 task.ti: ec764000
[ 53.171482] PC is at strlcpy+0x8/0x60
[ 53.175128] LR is at f_midi_opts_id_show+0x28/0x3c [usb_f_midi]
[ 53.181019] pc : [<c0222a9c>] lr : [<bf01bed0>] psr: 60000053
[ 53.181019] sp : ec765ef8 ip : 00000141 fp : 00000000
[ 53.192474] r10: 00019000 r9 : ed7546c0 r8 : 00010000
[ 53.197682] r7 : ec765f80 r6 : eb46a000 r5 : eb46a000 r4 :
ed754734
[ 53.204192] r3 : ee234c80 r2 : 00001000 r1 : 00000000 r0 :
eb46a000
[ 53.210704] Flags: nZCv IRQs on FIQs off Mode SVC_32 ISA ARM
Segment user
[ 53.217907] Control: 10c5387d Table: 6c6cc04a DAC: 00000015
[ 53.223636] Process cat (pid: 2936, stack limit = 0xec764238)
[ 53.229364] Stack: (0xec765ef8 to 0xec766000)
[ 53.233706] 5ee0:
ed754734 ed7546c0
[ 53.241866] 5f00: eb46a000 bf01bed0 eb753b80 bf01cc44 eb753b98
bf01b0a4 bf01b08c c0125dd0
[ 53.250025] 5f20: 00002f19 00000000 ec432e00 bf01cce8 c0530c00
00019000 00010000 ec765f80
[ 53.258184] 5f40: 00010000 ec764000 00019000 c00cc4ac ec432e00
c00cc55c 00000017 000081a4
[ 53.266343] 5f60: 00000001 00000000 00000000 ec432e00 ec432e00
00010000 00019000 c00cc620
[ 53.274502] 5f80: 00000000 00000000 00000000 00010000 ffff1000
00019000 00000003 c000e9a8
[ 53.282662] 5fa0: 00000000 c000e7e0 00010000 ffff1000 00000003
00019000 00010000 00019000
[ 53.290821] 5fc0: 00010000 ffff1000 00019000 00000003 7fffe000
00000001 00000000 00000000
[ 53.298980] 5fe0: 00000000 be8c68d4 0000b995 b6f0e3e6 40000070
00000003 00000000 00000000
[ 53.307157] [<c0222a9c>] (strlcpy) from [<bf01bed0>]
(f_midi_opts_id_show+0x28/0x3c [usb_f_midi])
[ 53.316006] [<bf01bed0>] (f_midi_opts_id_show [usb_f_midi]) from
[<bf01b0a4>] (f_midi_opts_attr_show+0x18/0x24 )
[ 53.327209] [<bf01b0a4>] (f_midi_opts_attr_show [usb_f_midi]) from
[<c0125dd0>] (configfs_read_file+0x9c/0xec)
[ 53.337180] [<c0125dd0>] (configfs_read_file) from [<c00cc4ac>]
(__vfs_read+0x18/0x4c)
[ 53.345073] [<c00cc4ac>] (__vfs_read) from [<c00cc55c>]
(vfs_read+0x7c/0x100)
[ 53.352190] [<c00cc55c>] (vfs_read) from [<c00cc620>]
(SyS_read+0x40/0x8c)
[ 53.359056] [<c00cc620>] (SyS_read) from [<c000e7e0>]
(ret_fast_syscall+0x0/0x34)
[ 53.366513] Code: ebffe3d3 e8bd8008 e92d4070 e1a05000 (e5d14000)
[ 53.372641] ---[ end trace e4f53a4e233d98d0 ]---
Signed-off-by: Pawel Szewczyk <p.szewczyk@samsung.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
-rw-r--r-- | drivers/usb/gadget/function/f_midi.c | 8 |
1 files changed, 7 insertions, 1 deletions
diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c index 259b656c0b3e..6316aa5b1c49 100644 --- a/drivers/usb/gadget/function/f_midi.c +++ b/drivers/usb/gadget/function/f_midi.c @@ -973,7 +973,13 @@ static ssize_t f_midi_opts_id_show(struct f_midi_opts *opts, char *page) int result; mutex_lock(&opts->lock); - result = strlcpy(page, opts->id, PAGE_SIZE); + if (opts->id) { + result = strlcpy(page, opts->id, PAGE_SIZE); + } else { + page[0] = 0; + result = 0; + } + mutex_unlock(&opts->lock); return result; |