Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright(c) 2014 Intel Mobile Communications GmbH
0004  * Copyright(c) 2015 Intel Deutschland GmbH
0005  *
0006  * Author: Johannes Berg <johannes@sipsolutions.net>
0007  */
0008 #include <linux/module.h>
0009 #include <linux/device.h>
0010 #include <linux/devcoredump.h>
0011 #include <linux/list.h>
0012 #include <linux/slab.h>
0013 #include <linux/fs.h>
0014 #include <linux/workqueue.h>
0015 
0016 static struct class devcd_class;
0017 
0018 /* global disable flag, for security purposes */
0019 static bool devcd_disabled;
0020 
0021 /* if data isn't read by userspace after 5 minutes then delete it */
0022 #define DEVCD_TIMEOUT   (HZ * 60 * 5)
0023 
0024 struct devcd_entry {
0025     struct device devcd_dev;
0026     void *data;
0027     size_t datalen;
0028     struct module *owner;
0029     ssize_t (*read)(char *buffer, loff_t offset, size_t count,
0030             void *data, size_t datalen);
0031     void (*free)(void *data);
0032     struct delayed_work del_wk;
0033     struct device *failing_dev;
0034 };
0035 
0036 static struct devcd_entry *dev_to_devcd(struct device *dev)
0037 {
0038     return container_of(dev, struct devcd_entry, devcd_dev);
0039 }
0040 
0041 static void devcd_dev_release(struct device *dev)
0042 {
0043     struct devcd_entry *devcd = dev_to_devcd(dev);
0044 
0045     devcd->free(devcd->data);
0046     module_put(devcd->owner);
0047 
0048     /*
0049      * this seems racy, but I don't see a notifier or such on
0050      * a struct device to know when it goes away?
0051      */
0052     if (devcd->failing_dev->kobj.sd)
0053         sysfs_delete_link(&devcd->failing_dev->kobj, &dev->kobj,
0054                   "devcoredump");
0055 
0056     put_device(devcd->failing_dev);
0057     kfree(devcd);
0058 }
0059 
0060 static void devcd_del(struct work_struct *wk)
0061 {
0062     struct devcd_entry *devcd;
0063 
0064     devcd = container_of(wk, struct devcd_entry, del_wk.work);
0065 
0066     device_del(&devcd->devcd_dev);
0067     put_device(&devcd->devcd_dev);
0068 }
0069 
0070 static ssize_t devcd_data_read(struct file *filp, struct kobject *kobj,
0071                    struct bin_attribute *bin_attr,
0072                    char *buffer, loff_t offset, size_t count)
0073 {
0074     struct device *dev = kobj_to_dev(kobj);
0075     struct devcd_entry *devcd = dev_to_devcd(dev);
0076 
0077     return devcd->read(buffer, offset, count, devcd->data, devcd->datalen);
0078 }
0079 
0080 static ssize_t devcd_data_write(struct file *filp, struct kobject *kobj,
0081                 struct bin_attribute *bin_attr,
0082                 char *buffer, loff_t offset, size_t count)
0083 {
0084     struct device *dev = kobj_to_dev(kobj);
0085     struct devcd_entry *devcd = dev_to_devcd(dev);
0086 
0087     mod_delayed_work(system_wq, &devcd->del_wk, 0);
0088 
0089     return count;
0090 }
0091 
0092 static struct bin_attribute devcd_attr_data = {
0093     .attr = { .name = "data", .mode = S_IRUSR | S_IWUSR, },
0094     .size = 0,
0095     .read = devcd_data_read,
0096     .write = devcd_data_write,
0097 };
0098 
0099 static struct bin_attribute *devcd_dev_bin_attrs[] = {
0100     &devcd_attr_data, NULL,
0101 };
0102 
0103 static const struct attribute_group devcd_dev_group = {
0104     .bin_attrs = devcd_dev_bin_attrs,
0105 };
0106 
0107 static const struct attribute_group *devcd_dev_groups[] = {
0108     &devcd_dev_group, NULL,
0109 };
0110 
0111 static int devcd_free(struct device *dev, void *data)
0112 {
0113     struct devcd_entry *devcd = dev_to_devcd(dev);
0114 
0115     flush_delayed_work(&devcd->del_wk);
0116     return 0;
0117 }
0118 
0119 static ssize_t disabled_show(struct class *class, struct class_attribute *attr,
0120                  char *buf)
0121 {
0122     return sysfs_emit(buf, "%d\n", devcd_disabled);
0123 }
0124 
0125 static ssize_t disabled_store(struct class *class, struct class_attribute *attr,
0126                   const char *buf, size_t count)
0127 {
0128     long tmp = simple_strtol(buf, NULL, 10);
0129 
0130     /*
0131      * This essentially makes the attribute write-once, since you can't
0132      * go back to not having it disabled. This is intentional, it serves
0133      * as a system lockdown feature.
0134      */
0135     if (tmp != 1)
0136         return -EINVAL;
0137 
0138     devcd_disabled = true;
0139 
0140     class_for_each_device(&devcd_class, NULL, NULL, devcd_free);
0141 
0142     return count;
0143 }
0144 static CLASS_ATTR_RW(disabled);
0145 
0146 static struct attribute *devcd_class_attrs[] = {
0147     &class_attr_disabled.attr,
0148     NULL,
0149 };
0150 ATTRIBUTE_GROUPS(devcd_class);
0151 
0152 static struct class devcd_class = {
0153     .name       = "devcoredump",
0154     .owner      = THIS_MODULE,
0155     .dev_release    = devcd_dev_release,
0156     .dev_groups = devcd_dev_groups,
0157     .class_groups   = devcd_class_groups,
0158 };
0159 
0160 static ssize_t devcd_readv(char *buffer, loff_t offset, size_t count,
0161                void *data, size_t datalen)
0162 {
0163     return memory_read_from_buffer(buffer, count, &offset, data, datalen);
0164 }
0165 
0166 static void devcd_freev(void *data)
0167 {
0168     vfree(data);
0169 }
0170 
0171 /**
0172  * dev_coredumpv - create device coredump with vmalloc data
0173  * @dev: the struct device for the crashed device
0174  * @data: vmalloc data containing the device coredump
0175  * @datalen: length of the data
0176  * @gfp: allocation flags
0177  *
0178  * This function takes ownership of the vmalloc'ed data and will free
0179  * it when it is no longer used. See dev_coredumpm() for more information.
0180  */
0181 void dev_coredumpv(struct device *dev, void *data, size_t datalen,
0182            gfp_t gfp)
0183 {
0184     dev_coredumpm(dev, NULL, data, datalen, gfp, devcd_readv, devcd_freev);
0185 }
0186 EXPORT_SYMBOL_GPL(dev_coredumpv);
0187 
0188 static int devcd_match_failing(struct device *dev, const void *failing)
0189 {
0190     struct devcd_entry *devcd = dev_to_devcd(dev);
0191 
0192     return devcd->failing_dev == failing;
0193 }
0194 
0195 /**
0196  * devcd_free_sgtable - free all the memory of the given scatterlist table
0197  * (i.e. both pages and scatterlist instances)
0198  * NOTE: if two tables allocated with devcd_alloc_sgtable and then chained
0199  * using the sg_chain function then that function should be called only once
0200  * on the chained table
0201  * @data: pointer to sg_table to free
0202  */
0203 static void devcd_free_sgtable(void *data)
0204 {
0205     _devcd_free_sgtable(data);
0206 }
0207 
0208 /**
0209  * devcd_read_from_sgtable - copy data from sg_table to a given buffer
0210  * and return the number of bytes read
0211  * @buffer: the buffer to copy the data to it
0212  * @buf_len: the length of the buffer
0213  * @data: the scatterlist table to copy from
0214  * @offset: start copy from @offset@ bytes from the head of the data
0215  *  in the given scatterlist
0216  * @data_len: the length of the data in the sg_table
0217  */
0218 static ssize_t devcd_read_from_sgtable(char *buffer, loff_t offset,
0219                        size_t buf_len, void *data,
0220                        size_t data_len)
0221 {
0222     struct scatterlist *table = data;
0223 
0224     if (offset > data_len)
0225         return -EINVAL;
0226 
0227     if (offset + buf_len > data_len)
0228         buf_len = data_len - offset;
0229     return sg_pcopy_to_buffer(table, sg_nents(table), buffer, buf_len,
0230                   offset);
0231 }
0232 
0233 /**
0234  * dev_coredumpm - create device coredump with read/free methods
0235  * @dev: the struct device for the crashed device
0236  * @owner: the module that contains the read/free functions, use %THIS_MODULE
0237  * @data: data cookie for the @read/@free functions
0238  * @datalen: length of the data
0239  * @gfp: allocation flags
0240  * @read: function to read from the given buffer
0241  * @free: function to free the given buffer
0242  *
0243  * Creates a new device coredump for the given device. If a previous one hasn't
0244  * been read yet, the new coredump is discarded. The data lifetime is determined
0245  * by the device coredump framework and when it is no longer needed the @free
0246  * function will be called to free the data.
0247  */
0248 void dev_coredumpm(struct device *dev, struct module *owner,
0249            void *data, size_t datalen, gfp_t gfp,
0250            ssize_t (*read)(char *buffer, loff_t offset, size_t count,
0251                    void *data, size_t datalen),
0252            void (*free)(void *data))
0253 {
0254     static atomic_t devcd_count = ATOMIC_INIT(0);
0255     struct devcd_entry *devcd;
0256     struct device *existing;
0257 
0258     if (devcd_disabled)
0259         goto free;
0260 
0261     existing = class_find_device(&devcd_class, NULL, dev,
0262                      devcd_match_failing);
0263     if (existing) {
0264         put_device(existing);
0265         goto free;
0266     }
0267 
0268     if (!try_module_get(owner))
0269         goto free;
0270 
0271     devcd = kzalloc(sizeof(*devcd), gfp);
0272     if (!devcd)
0273         goto put_module;
0274 
0275     devcd->owner = owner;
0276     devcd->data = data;
0277     devcd->datalen = datalen;
0278     devcd->read = read;
0279     devcd->free = free;
0280     devcd->failing_dev = get_device(dev);
0281 
0282     device_initialize(&devcd->devcd_dev);
0283 
0284     dev_set_name(&devcd->devcd_dev, "devcd%d",
0285              atomic_inc_return(&devcd_count));
0286     devcd->devcd_dev.class = &devcd_class;
0287 
0288     if (device_add(&devcd->devcd_dev))
0289         goto put_device;
0290 
0291     /*
0292      * These should normally not fail, but there is no problem
0293      * continuing without the links, so just warn instead of
0294      * failing.
0295      */
0296     if (sysfs_create_link(&devcd->devcd_dev.kobj, &dev->kobj,
0297                   "failing_device") ||
0298         sysfs_create_link(&dev->kobj, &devcd->devcd_dev.kobj,
0299                       "devcoredump"))
0300         dev_warn(dev, "devcoredump create_link failed\n");
0301 
0302     INIT_DELAYED_WORK(&devcd->del_wk, devcd_del);
0303     schedule_delayed_work(&devcd->del_wk, DEVCD_TIMEOUT);
0304 
0305     return;
0306  put_device:
0307     put_device(&devcd->devcd_dev);
0308  put_module:
0309     module_put(owner);
0310  free:
0311     free(data);
0312 }
0313 EXPORT_SYMBOL_GPL(dev_coredumpm);
0314 
0315 /**
0316  * dev_coredumpsg - create device coredump that uses scatterlist as data
0317  * parameter
0318  * @dev: the struct device for the crashed device
0319  * @table: the dump data
0320  * @datalen: length of the data
0321  * @gfp: allocation flags
0322  *
0323  * Creates a new device coredump for the given device. If a previous one hasn't
0324  * been read yet, the new coredump is discarded. The data lifetime is determined
0325  * by the device coredump framework and when it is no longer needed
0326  * it will free the data.
0327  */
0328 void dev_coredumpsg(struct device *dev, struct scatterlist *table,
0329             size_t datalen, gfp_t gfp)
0330 {
0331     dev_coredumpm(dev, NULL, table, datalen, gfp, devcd_read_from_sgtable,
0332               devcd_free_sgtable);
0333 }
0334 EXPORT_SYMBOL_GPL(dev_coredumpsg);
0335 
0336 static int __init devcoredump_init(void)
0337 {
0338     return class_register(&devcd_class);
0339 }
0340 __initcall(devcoredump_init);
0341 
0342 static void __exit devcoredump_exit(void)
0343 {
0344     class_for_each_device(&devcd_class, NULL, NULL, devcd_free);
0345     class_unregister(&devcd_class);
0346 }
0347 __exitcall(devcoredump_exit);