Commit 0c8c77d35582c3f7989f1316368da5ae7f14ad4b

Authored by Christian Borntraeger
Committed by Greg Kroah-Hartman
1 parent b44b214026

s390/ccwgroup: Fix memory corruption

commit 0b60f9ead5d4816e7e3d6e28f4a0d22d4a1b2513 (s390: use
device_remove_file_self() instead of device_schedule_callback())

caused random memory corruption on my s390 box. Turns out that the
last element of the ccwgroup structure is of dynamic size, so we
must move the newly introduced work structure _before_ the zero
length array.

Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
CC: Tejun Heo <tj@kernel.org>
CC: Martin Schwidefsky <schwidefsky@de.ibm.com>
CC: Heiko Carstens <heiko.carstens@de.ibm.com>
CC: Sebastian Ott <sebott@linux.vnet.ibm.com>
CC: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
Acked-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Showing 1 changed file with 1 additions and 1 deletions Inline Diff

arch/s390/include/asm/ccwgroup.h
1 #ifndef S390_CCWGROUP_H 1 #ifndef S390_CCWGROUP_H
2 #define S390_CCWGROUP_H 2 #define S390_CCWGROUP_H
3 3
4 struct ccw_device; 4 struct ccw_device;
5 struct ccw_driver; 5 struct ccw_driver;
6 6
7 /** 7 /**
8 * struct ccwgroup_device - ccw group device 8 * struct ccwgroup_device - ccw group device
9 * @state: online/offline state 9 * @state: online/offline state
10 * @count: number of attached slave devices 10 * @count: number of attached slave devices
11 * @dev: embedded device structure 11 * @dev: embedded device structure
12 * @cdev: variable number of slave devices, allocated as needed 12 * @cdev: variable number of slave devices, allocated as needed
13 */ 13 */
14 struct ccwgroup_device { 14 struct ccwgroup_device {
15 enum { 15 enum {
16 CCWGROUP_OFFLINE, 16 CCWGROUP_OFFLINE,
17 CCWGROUP_ONLINE, 17 CCWGROUP_ONLINE,
18 } state; 18 } state;
19 /* private: */ 19 /* private: */
20 atomic_t onoff; 20 atomic_t onoff;
21 struct mutex reg_mutex; 21 struct mutex reg_mutex;
22 /* public: */ 22 /* public: */
23 unsigned int count; 23 unsigned int count;
24 struct device dev; 24 struct device dev;
25 struct ccw_device *cdev[0];
26 struct work_struct ungroup_work; 25 struct work_struct ungroup_work;
26 struct ccw_device *cdev[0];
27 }; 27 };
28 28
29 /** 29 /**
30 * struct ccwgroup_driver - driver for ccw group devices 30 * struct ccwgroup_driver - driver for ccw group devices
31 * @setup: function called during device creation to setup the device 31 * @setup: function called during device creation to setup the device
32 * @remove: function called on remove 32 * @remove: function called on remove
33 * @set_online: function called when device is set online 33 * @set_online: function called when device is set online
34 * @set_offline: function called when device is set offline 34 * @set_offline: function called when device is set offline
35 * @shutdown: function called when device is shut down 35 * @shutdown: function called when device is shut down
36 * @prepare: prepare for pm state transition 36 * @prepare: prepare for pm state transition
37 * @complete: undo work done in @prepare 37 * @complete: undo work done in @prepare
38 * @freeze: callback for freezing during hibernation snapshotting 38 * @freeze: callback for freezing during hibernation snapshotting
39 * @thaw: undo work done in @freeze 39 * @thaw: undo work done in @freeze
40 * @restore: callback for restoring after hibernation 40 * @restore: callback for restoring after hibernation
41 * @driver: embedded driver structure 41 * @driver: embedded driver structure
42 */ 42 */
43 struct ccwgroup_driver { 43 struct ccwgroup_driver {
44 int (*setup) (struct ccwgroup_device *); 44 int (*setup) (struct ccwgroup_device *);
45 void (*remove) (struct ccwgroup_device *); 45 void (*remove) (struct ccwgroup_device *);
46 int (*set_online) (struct ccwgroup_device *); 46 int (*set_online) (struct ccwgroup_device *);
47 int (*set_offline) (struct ccwgroup_device *); 47 int (*set_offline) (struct ccwgroup_device *);
48 void (*shutdown)(struct ccwgroup_device *); 48 void (*shutdown)(struct ccwgroup_device *);
49 int (*prepare) (struct ccwgroup_device *); 49 int (*prepare) (struct ccwgroup_device *);
50 void (*complete) (struct ccwgroup_device *); 50 void (*complete) (struct ccwgroup_device *);
51 int (*freeze)(struct ccwgroup_device *); 51 int (*freeze)(struct ccwgroup_device *);
52 int (*thaw) (struct ccwgroup_device *); 52 int (*thaw) (struct ccwgroup_device *);
53 int (*restore)(struct ccwgroup_device *); 53 int (*restore)(struct ccwgroup_device *);
54 54
55 struct device_driver driver; 55 struct device_driver driver;
56 }; 56 };
57 57
58 extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver); 58 extern int ccwgroup_driver_register (struct ccwgroup_driver *cdriver);
59 extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver); 59 extern void ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver);
60 int ccwgroup_create_dev(struct device *root, struct ccwgroup_driver *gdrv, 60 int ccwgroup_create_dev(struct device *root, struct ccwgroup_driver *gdrv,
61 int num_devices, const char *buf); 61 int num_devices, const char *buf);
62 62
63 extern int ccwgroup_set_online(struct ccwgroup_device *gdev); 63 extern int ccwgroup_set_online(struct ccwgroup_device *gdev);
64 extern int ccwgroup_set_offline(struct ccwgroup_device *gdev); 64 extern int ccwgroup_set_offline(struct ccwgroup_device *gdev);
65 65
66 extern int ccwgroup_probe_ccwdev(struct ccw_device *cdev); 66 extern int ccwgroup_probe_ccwdev(struct ccw_device *cdev);
67 extern void ccwgroup_remove_ccwdev(struct ccw_device *cdev); 67 extern void ccwgroup_remove_ccwdev(struct ccw_device *cdev);
68 68
69 #define to_ccwgroupdev(x) container_of((x), struct ccwgroup_device, dev) 69 #define to_ccwgroupdev(x) container_of((x), struct ccwgroup_device, dev)
70 #define to_ccwgroupdrv(x) container_of((x), struct ccwgroup_driver, driver) 70 #define to_ccwgroupdrv(x) container_of((x), struct ccwgroup_driver, driver)
71 #endif 71 #endif