Skip to content

3.10.y: Attempting to export non-existant gpio crashes kernel #364

@daniel-santos

Description

@daniel-santos

Hey guys. I'm not sure if this one is an upstream bug or not, it doesn't happen on my laptop, but then again, i don't have any real gpio chips in it, so the environment is different. I built this from git 3.10.y on Aug 16th, so the last patch (before mine) was "ARM: Fix FIQ code on VIVT CPUs"

To get this error, I booted up my raspbian system (with my custom-built debug kernel, .config here), logged in and ran:

echo -n 248 > /sys/class/gpio/export

[  222.961384] Unable to handle kernel NULL pointer dereference at virtual address 00000044
[  222.969486] pgd = d97d0000
[  222.972190] [00000044] *pgd=1aaca831, *pte=00000000, *ppte=00000000
[  222.978483] Internal error: Oops: 17 [#1] PREEMPT ARM

Entering kdb (current=0xd97586e0, pid 2021) Oops: (null)
due to oops @ 0xc024a4cc

dCPU: 0 PID: 2021 Comm: bash Not tainted 3.10.7-debug+ #1
dtask: d97586e0 ti: d975c000 task.ti: d975c000
PC is at gpiod_request+0x174/0x1d4
LR is at _raw_spin_lock_irqsave+0x60/0x6c
pc : [<c024a4cc>]    lr : [<c0414bc8>]    psr: a0000093
sp : d975def0  ip : aaaaaaab  fp : 019815f8
r10: c043ba2c  r9 : da890428  r8 : c050ff58
r7 : a0000013  r6 : fffffdfb  r5 : c0b9a120  r4 : 00000000
r3 : 00000000  r2 : 00000000  r1 : 00000000  r0 : c061b158
Flags: NzCv  IRQs off  FIQs on  Mode SVC_32  ISA ARM  Segment user
Control: 00c5387d  Table: 197d0008  DAC: 00000015
dCPU: 0 PID: 2021 Comm: bash Not tainted 3.10.7-debug+ #1
[<c0014894>] (unwind_backtrace+0x0/0x130) from [<c0011a30>] (show_stack+0x10/0x14)
[<c0011a30>] (show_stack+0x10/0x14) from [<c007e3d0>] (kdb_dumpregs+0x28/0x50)
[<c007e3d0>] (kdb_dumpregs+0x28/0x50) from [<c008068c>] (kdb_main_loop+0x3bc/0x6d8)
[<c008068c>] (kdb_main_loop+0x3bc/0x6d8) from [<c0082e08>] (kdb_stub+0x15c/0x390)
[<c0082e08>] (kdb_stub+0x15c/0x390) from [<c007a09c>] (kgdb_handle_exception+0x41c/0x6c4)
[<c007a09c>] (kgdb_handle_exception+0x41c/0x6c4) from [<c0013df4>] (kgdb_notify+0x2c/0x64)
[<c0013df4>] (kgdb_notify+0x2c/0x64) from [<c041739c>] (notifier_call_chain+0x48/0x9c)
[<c041739c>] (notifier_call_chain+0x48/0x9c) from [<c0417454>] (__atomic_notifier_call_chain+0x64/0x94)
[<c0417454>] (__atomic_notifier_call_chain+0x64/0x94) from [<c041749c>] (atomic_notifier_call_chain+0x18/0x20)
[<c041749c>] (atomic_notifier_call_chain+0x18/0x20) from [<c04174dc>] (notify_die+0x38/0x44)
[<c04174dc>] (notify_die+0x38/0x44) from [<c0011b0c>] (die+0xd8/0x274)
[<c0011b0c>] (die+0xd8/0x274) from [<c040dc40>] (__do_kernel_fault.part.8+0x54/0x74)
[<c040dc40>] (__do_kernel_fault.part.8+0x54/0x74) from [<c0417058>] (do_page_fault+0x1ec/0x440)
[<c0417058>] (do_page_fault+0x1ec/0x440) from [<c0008428>] (do_DataAbort+0x34/0x98)
[<c0008428>] (do_DataAbort+0x34/0x98) from [<c041581c>] (__dabt_svc+0x3c/0x60)
Exception stack(0xd975dea8 to 0xd975def0)
dea0:                   c061b158 00000000 00000000 00000000 00000000 c0b9a120
dec0: fffffdfb a0000013 c050ff58 da890428 c043ba2c 019815f8 aaaaaaab d975def0
dee0: c0414bc8 c024a4cc a0000093 ffffffff
[<c041581c>] (__dabt_svc+0x3c/0x60) from [<c024a4cc>] (gpiod_request+0x174/0x1d4)
[<c024a4cc>] (gpiod_request+0x174/0x1d4) from [<c024bad4>] (export_store+0x3c/0xfc)
[<c024bad4>] (export_store+0x3c/0xfc) from [<c0283304>] (class_attr_store+0x18/0x24)
[<c0283304>] (class_attr_store+0x18/0x24) from [<c0134e2c>] (sysfs_write_file+0x16c/0x1a0)
[<c0134e2c>] (sysfs_write_file+0x16c/0x1a0) from [<c00d7400>] (vfs_write+0xb4/0x1c8)
[<c00d7400>] (vfs_write+0xb4/0x1c8) from [<c00d78b4>] (SyS_write+0x3c/0x70)
[<c00d78b4>] (SyS_write+0x3c/0x70) from [<c000e700>] (ret_fast_syscall+0x0/0x48)

kdb> 

Here's some info from kgdb:

gpiod_request (desc=desc@entry=0xc0b9a120 <gpio_desc+2976>, label=label@entry=0xc050ff58 "sysfs") at drivers/gpio/gpiolib.c:1447
1447                    pr_debug("_gpio_request: gpio-%d (%s) status %d\n",
(gdb) bt
#0  gpiod_request (desc=desc@entry=0xc0b9a120 <gpio_desc+2976>, label=label@entry=0xc050ff58 "sysfs") at drivers/gpio/gpiolib.c:1447
#1  0xc024bad4 in export_store (class=<optimized out>, attr=<optimized out>, buf=<optimized out>, len=3) at drivers/gpio/gpiolib.c:671
#2  0xc0283304 in class_attr_store (kobj=<optimized out>, attr=<optimized out>, buf=<optimized out>, count=<optimized out>) at drivers/base/class.c:46
#3  0xc0134e2c in flush_write_buffer (count=3, buffer=0xd94d3660, dentry=<optimized out>) at fs/sysfs/file.c:202
#4  sysfs_write_file (file=<optimized out>, buf=<optimized out>, count=<optimized out>, ppos=0xd975df80) at fs/sysfs/file.c:236
#5  0xc00d7400 in vfs_write (file=file@entry=0xd9542080, 
    buf=buf@entry=0x197dc08 "248serv is /sbin/insserv\n& local \"${upvars[@]}\" && _upvars \"${upargs[@]}\"\n cur cword words=();\n    local upargs=() upvars=() vcur vcword vprev vwords;\n    while getopts \"c:i:n:p:w:\" flag \"$@\"; do\n    "..., 
    count=count@entry=3, pos=pos@entry=0xd975df80) at fs/read_write.c:446
#6  0xc00d78b4 in SYSC_write (count=3, 
    buf=0x197dc08 "248serv is /sbin/insserv\n& local \"${upvars[@]}\" && _upvars \"${upargs[@]}\"\n cur cword words=();\n    local upargs=() upvars=() vcur vcword vprev vwords;\n    while getopts \"c:i:n:p:w:\" flag \"$@\"; do\n    "..., 
    fd=<optimized out>) at fs/read_write.c:494
#7  SyS_write (fd=<optimized out>, buf=26729480, count=3) at fs/read_write.c:487
(gdb) list
1442                    gpiod_get_direction(desc);
1443                    spin_lock_irqsave(&gpio_lock, flags);
1444            }
1445    done:
1446            if (status)
1447                    pr_debug("_gpio_request: gpio-%d (%s) status %d\n",
1448                             desc_to_gpio(desc), label ? : "?", status);
1449            spin_unlock_irqrestore(&gpio_lock, flags);
1450            return status;
1451    }
(gdb) info locals
descriptor = {modname = 0xc0521394 "gpiolib", function = 0xc043742c <__func__.19664> "gpiod_request", filename = 0xc0521368 "drivers/gpio/gpiolib.c", format = 0xc05213f0 "_gpio_request: gpio-%d (%s) status %d\n", lineno = 1448, flags = 1}
chip = 0x0 <__vectors_start>
status = <optimized out>
flags = 2684354579
__func__ = "gpiod_request"
(gdb) print *desc
$1 = {chip = 0x0 <__vectors_start>, flags = 0, label = 0x0 <__vectors_start>}
(gdb) x/s label
0xc050ff58:     "sysfs"
(gdb) list desc_to_gpio
134      * This should disappear in the future but is needed since we still
135      * use GPIO numbers for error messages and sysfs nodes
136      */
137     static int desc_to_gpio(const struct gpio_desc *desc)
138     {
139             return desc->chip->base + gpio_chip_hwgpio(desc);
140     }
141
142
143     /* Warn when drivers omit gpio_request() calls -- legal but ill-advised
(gdb) list gpio_chip_hwgpio
113     /*
114      * Return the GPIO number of the passed descriptor relative to its chip
115      */
116     static int gpio_chip_hwgpio(const struct gpio_desc *desc)
117     {
118             return desc - &desc->chip->desc[0];
119     }
120
121     /**
122      * Convert a GPIO number to its descriptor

So boom, desc->chip is NULL, there's the problem.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions