s390/zcrypt: Fix kernel crash on systems without AP bus support
On systems without AP bus (e.g. KVM) the kernel crashes during init calls when zcrypt is built-in: kernel BUG at drivers/base/driver.c:153! illegal operation: 0001 ilc:1 [#1] SMP Modules linked in: CPU: 1 PID: 1 Comm: swapper/0 Not tainted 4.2.0+ #221 task: 0000000010a40000 ti: 0000000010a48000 task.ti:0000000010a48000 Krnl PSW : 0704c00180000000 0000000000592bd6(driver_register+0x106/0x140) R:0 T:1 IO:1 EX:1 Key:0 M:1 W:0 P:0 AS:3 CC:0 PM:0 EA:3 0000000000000012 0000000000000000 0000000000c45328 0000000000c44e30 00000000009ef63c 000000000067f598 0000000000cf3c58 0000000000000000 000000000000007b 0000000000cb1030 0000000000000002 0000000000000000 0000000000ca8580 0000000010306700 00000000001001d8 0000000010a4bd88 Krnl Code: 0000000000592bc6: f0b00004ebcf srp 4(12,%r0),3023(%r14),0 0000000000592bcc: f0a0000407f4 srp 4(11,%r0),2036,0 #0000000000592bd2: a7f40001 brc 15,592bd4 >0000000000592bd6: e330d0000004 lg %r3,0(%r13) 0000000000592bdc: c0200021edfd larl %r2,9d07d6 0000000000592be2: c0e500126d8f brasl %r14,7e0700 0000000000592be8: e330d0080004 lg %r3,8(%r13) 0000000000592bee: a7f4ffab brc 15,592b44 Call Trace: ([<00000000001001c8>] do_one_initcall+0x90/0x1d0) [<0000000000c6dd34>] kernel_init_freeable+0x1e4/0x2a0 [<00000000007db53a>] kernel_init+0x2a/0x120 [<00000000007e8ece>] kernel_thread_starter+0x6/0xc [<00000000007e8ec8>] kernel_thread_starter+0x0/0xc Last Breaking-Event-Address: [<0000000000592bd2>] driver_register+0x102/0x140 When zcrypt is built as a module, the module loader ensures that the driver modules cannot be loaded if the AP bus module returns an error during initialisation. But if zcrypt and the driver are built-in, the driver is getting initialised even if the AP bus initialisation failed. The driver invokes ap_driver_register() during initialisation, which then causes operations on uninitialised data structures to be performed. Explicitly protect ap_driver_register() by introducing an "initialised" flag that gets set iff the AP bus initialisation was successful. When the AP bus initialisation failed, ap_driver_register() will error out with -ENODEV, causing the driver initialisation to fail as well. Test results: 1. Inside KVM (no AP bus), zcrypt built-in Boots. /sys/bus/ap not present (expected). 2. Inside KVM (no AP bus), zcrypt as module Boots. Loading zcrypt_cex4 fails because loading ap_bus fails (expected). 3. On LPAR with CEX5, zcrypt built-in Boots. /sys/bus/ap/devices/card* present but .../card*/type missing (i.e. zcrypt_device_register() fails, unrelated issue). 4. On LPAR with CEX5, zcrypt as module Boots. Loading zcrypt_cex4 successful, /sys/bus/ap/devices/card*/type present. No further testing (user-space functionality) was done. Signed-off-by: Sascha Silbe <silbe@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
This commit is contained in:
parent
18e22a1772
commit
e387753c5f
|
@ -74,6 +74,7 @@ static struct device *ap_root_device = NULL;
|
|||
static struct ap_config_info *ap_configuration;
|
||||
static DEFINE_SPINLOCK(ap_device_list_lock);
|
||||
static LIST_HEAD(ap_device_list);
|
||||
static bool initialised;
|
||||
|
||||
/*
|
||||
* Workqueue timer for bus rescan.
|
||||
|
@ -1384,6 +1385,9 @@ int ap_driver_register(struct ap_driver *ap_drv, struct module *owner,
|
|||
{
|
||||
struct device_driver *drv = &ap_drv->driver;
|
||||
|
||||
if (!initialised)
|
||||
return -ENODEV;
|
||||
|
||||
drv->bus = &ap_bus_type;
|
||||
drv->probe = ap_device_probe;
|
||||
drv->remove = ap_device_remove;
|
||||
|
@ -1808,6 +1812,7 @@ int __init ap_module_init(void)
|
|||
goto out_pm;
|
||||
|
||||
queue_work(system_long_wq, &ap_scan_work);
|
||||
initialised = true;
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -1837,6 +1842,7 @@ void ap_module_exit(void)
|
|||
{
|
||||
int i;
|
||||
|
||||
initialised = false;
|
||||
ap_reset_domain();
|
||||
ap_poll_thread_stop();
|
||||
del_timer_sync(&ap_config_timer);
|
||||
|
|
Loading…
Reference in New Issue