1 /* 2 * This file is provided under the GPLv2 license. 3 * 4 * GPL LICENSE SUMMARY 5 * 6 * Copyright(c) 2014 Intel Mobile Communications GmbH 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of version 2 of the GNU General Public License as 10 * published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * The full GNU General Public License is included in this distribution 18 * in the file called COPYING. 19 * 20 * Contact Information: 21 * Intel Linux Wireless <ilw@linux.intel.com> 22 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 23 * 24 * Author: Johannes Berg <johannes@sipsolutions.net> 25 */ 26 #include <linux/module.h> 27 #include <linux/device.h> 28 #include <linux/devcoredump.h> 29 #include <linux/list.h> 30 #include <linux/slab.h> 31 #include <linux/fs.h> 32 #include <linux/workqueue.h> 33 34 static struct class devcd_class; 35 36 /* global disable flag, for security purposes */ 37 static bool devcd_disabled; 38 39 /* if data isn't read by userspace after 5 minutes then delete it */ 40 #define DEVCD_TIMEOUT (HZ * 60 * 5) 41 42 struct devcd_entry { 43 struct device devcd_dev; 44 const void *data; 45 size_t datalen; 46 struct module *owner; 47 ssize_t (*read)(char *buffer, loff_t offset, size_t count, 48 const void *data, size_t datalen); 49 void (*free)(const void *data); 50 struct delayed_work del_wk; 51 struct device *failing_dev; 52 }; 53 54 static struct devcd_entry *dev_to_devcd(struct device *dev) 55 { 56 return container_of(dev, struct devcd_entry, devcd_dev); 57 } 58 59 static void devcd_dev_release(struct device *dev) 60 { 61 struct devcd_entry *devcd = dev_to_devcd(dev); 62 63 devcd->free(devcd->data); 64 module_put(devcd->owner); 65 66 /* 67 * this seems racy, but I don't see a notifier or such on 68 * a struct device to know when it goes away? 69 */ 70 if (devcd->failing_dev->kobj.sd) 71 sysfs_delete_link(&devcd->failing_dev->kobj, &dev->kobj, 72 "devcoredump"); 73 74 put_device(devcd->failing_dev); 75 kfree(devcd); 76 } 77 78 static void devcd_del(struct work_struct *wk) 79 { 80 struct devcd_entry *devcd; 81 82 devcd = container_of(wk, struct devcd_entry, del_wk.work); 83 84 device_del(&devcd->devcd_dev); 85 put_device(&devcd->devcd_dev); 86 } 87 88 static ssize_t devcd_data_read(struct file *filp, struct kobject *kobj, 89 struct bin_attribute *bin_attr, 90 char *buffer, loff_t offset, size_t count) 91 { 92 struct device *dev = kobj_to_dev(kobj); 93 struct devcd_entry *devcd = dev_to_devcd(dev); 94 95 return devcd->read(buffer, offset, count, devcd->data, devcd->datalen); 96 } 97 98 static ssize_t devcd_data_write(struct file *filp, struct kobject *kobj, 99 struct bin_attribute *bin_attr, 100 char *buffer, loff_t offset, size_t count) 101 { 102 struct device *dev = kobj_to_dev(kobj); 103 struct devcd_entry *devcd = dev_to_devcd(dev); 104 105 mod_delayed_work(system_wq, &devcd->del_wk, 0); 106 107 return count; 108 } 109 110 static struct bin_attribute devcd_attr_data = { 111 .attr = { .name = "data", .mode = S_IRUSR | S_IWUSR, }, 112 .size = 0, 113 .read = devcd_data_read, 114 .write = devcd_data_write, 115 }; 116 117 static struct bin_attribute *devcd_dev_bin_attrs[] = { 118 &devcd_attr_data, NULL, 119 }; 120 121 static const struct attribute_group devcd_dev_group = { 122 .bin_attrs = devcd_dev_bin_attrs, 123 }; 124 125 static const struct attribute_group *devcd_dev_groups[] = { 126 &devcd_dev_group, NULL, 127 }; 128 129 static int devcd_free(struct device *dev, void *data) 130 { 131 struct devcd_entry *devcd = dev_to_devcd(dev); 132 133 flush_delayed_work(&devcd->del_wk); 134 return 0; 135 } 136 137 static ssize_t disabled_show(struct class *class, struct class_attribute *attr, 138 char *buf) 139 { 140 return sprintf(buf, "%d\n", devcd_disabled); 141 } 142 143 static ssize_t disabled_store(struct class *class, struct class_attribute *attr, 144 const char *buf, size_t count) 145 { 146 long tmp = simple_strtol(buf, NULL, 10); 147 148 /* 149 * This essentially makes the attribute write-once, since you can't 150 * go back to not having it disabled. This is intentional, it serves 151 * as a system lockdown feature. 152 */ 153 if (tmp != 1) 154 return -EINVAL; 155 156 devcd_disabled = true; 157 158 class_for_each_device(&devcd_class, NULL, NULL, devcd_free); 159 160 return count; 161 } 162 163 static struct class_attribute devcd_class_attrs[] = { 164 __ATTR_RW(disabled), 165 __ATTR_NULL 166 }; 167 168 static struct class devcd_class = { 169 .name = "devcoredump", 170 .owner = THIS_MODULE, 171 .dev_release = devcd_dev_release, 172 .dev_groups = devcd_dev_groups, 173 .class_attrs = devcd_class_attrs, 174 }; 175 176 static ssize_t devcd_readv(char *buffer, loff_t offset, size_t count, 177 const void *data, size_t datalen) 178 { 179 if (offset > datalen) 180 return -EINVAL; 181 182 if (offset + count > datalen) 183 count = datalen - offset; 184 185 if (count) 186 memcpy(buffer, ((u8 *)data) + offset, count); 187 188 return count; 189 } 190 191 /** 192 * dev_coredumpv - create device coredump with vmalloc data 193 * @dev: the struct device for the crashed device 194 * @data: vmalloc data containing the device coredump 195 * @datalen: length of the data 196 * @gfp: allocation flags 197 * 198 * This function takes ownership of the vmalloc'ed data and will free 199 * it when it is no longer used. See dev_coredumpm() for more information. 200 */ 201 void dev_coredumpv(struct device *dev, const void *data, size_t datalen, 202 gfp_t gfp) 203 { 204 dev_coredumpm(dev, NULL, data, datalen, gfp, devcd_readv, vfree); 205 } 206 EXPORT_SYMBOL_GPL(dev_coredumpv); 207 208 static int devcd_match_failing(struct device *dev, const void *failing) 209 { 210 struct devcd_entry *devcd = dev_to_devcd(dev); 211 212 return devcd->failing_dev == failing; 213 } 214 215 /** 216 * dev_coredumpm - create device coredump with read/free methods 217 * @dev: the struct device for the crashed device 218 * @owner: the module that contains the read/free functions, use %THIS_MODULE 219 * @data: data cookie for the @read/@free functions 220 * @datalen: length of the data 221 * @gfp: allocation flags 222 * @read: function to read from the given buffer 223 * @free: function to free the given buffer 224 * 225 * Creates a new device coredump for the given device. If a previous one hasn't 226 * been read yet, the new coredump is discarded. The data lifetime is determined 227 * by the device coredump framework and when it is no longer needed the @free 228 * function will be called to free the data. 229 */ 230 void dev_coredumpm(struct device *dev, struct module *owner, 231 const void *data, size_t datalen, gfp_t gfp, 232 ssize_t (*read)(char *buffer, loff_t offset, size_t count, 233 const void *data, size_t datalen), 234 void (*free)(const void *data)) 235 { 236 static atomic_t devcd_count = ATOMIC_INIT(0); 237 struct devcd_entry *devcd; 238 struct device *existing; 239 240 if (devcd_disabled) 241 goto free; 242 243 existing = class_find_device(&devcd_class, NULL, dev, 244 devcd_match_failing); 245 if (existing) { 246 put_device(existing); 247 goto free; 248 } 249 250 if (!try_module_get(owner)) 251 goto free; 252 253 devcd = kzalloc(sizeof(*devcd), gfp); 254 if (!devcd) 255 goto put_module; 256 257 devcd->owner = owner; 258 devcd->data = data; 259 devcd->datalen = datalen; 260 devcd->read = read; 261 devcd->free = free; 262 devcd->failing_dev = get_device(dev); 263 264 device_initialize(&devcd->devcd_dev); 265 266 dev_set_name(&devcd->devcd_dev, "devcd%d", 267 atomic_inc_return(&devcd_count)); 268 devcd->devcd_dev.class = &devcd_class; 269 270 if (device_add(&devcd->devcd_dev)) 271 goto put_device; 272 273 if (sysfs_create_link(&devcd->devcd_dev.kobj, &dev->kobj, 274 "failing_device")) 275 /* nothing - symlink will be missing */; 276 277 if (sysfs_create_link(&dev->kobj, &devcd->devcd_dev.kobj, 278 "devcoredump")) 279 /* nothing - symlink will be missing */; 280 281 INIT_DELAYED_WORK(&devcd->del_wk, devcd_del); 282 schedule_delayed_work(&devcd->del_wk, DEVCD_TIMEOUT); 283 284 return; 285 put_device: 286 put_device(&devcd->devcd_dev); 287 put_module: 288 module_put(owner); 289 free: 290 free(data); 291 } 292 EXPORT_SYMBOL_GPL(dev_coredumpm); 293 294 static int __init devcoredump_init(void) 295 { 296 return class_register(&devcd_class); 297 } 298 __initcall(devcoredump_init); 299 300 static void __exit devcoredump_exit(void) 301 { 302 class_for_each_device(&devcd_class, NULL, NULL, devcd_free); 303 class_unregister(&devcd_class); 304 } 305 __exitcall(devcoredump_exit); 306