]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/base/core.c
Driver core: warn when userspace writes to the uevent file in a non-supported way
[linux-2.6-omap-h63xx.git] / drivers / base / core.c
index bb2cc37a4d439e577fecced9f5ad3e3732949b2c..f69305c7269d1cf7fb294c2576a67c66118f7d64 100644 (file)
@@ -120,6 +120,8 @@ static int dev_uevent_filter(struct kset *kset, struct kobject *kobj)
 
        if (ktype == &ktype_device) {
                struct device *dev = to_dev(kobj);
+               if (dev->uevent_suppress)
+                       return 0;
                if (dev->bus)
                        return 1;
                if (dev->class)
@@ -157,6 +159,11 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
                               "MINOR=%u", MINOR(dev->devt));
        }
 
+       if (dev->type && dev->type->name)
+               add_uevent_var(envp, num_envp, &i,
+                              buffer, buffer_size, &length,
+                              "DEVTYPE=%s", dev->type->name);
+
        if (dev->driver)
                add_uevent_var(envp, num_envp, &i,
                               buffer, buffer_size, &length,
@@ -239,9 +246,59 @@ static struct kset_uevent_ops device_uevent_ops = {
        .uevent =       dev_uevent,
 };
 
+static ssize_t show_uevent(struct device *dev, struct device_attribute *attr,
+                          char *buf)
+{
+       struct kobject *top_kobj;
+       struct kset *kset;
+       char *envp[32];
+       char data[PAGE_SIZE];
+       char *pos;
+       int i;
+       size_t count = 0;
+       int retval;
+
+       /* search the kset, the device belongs to */
+       top_kobj = &dev->kobj;
+       if (!top_kobj->kset && top_kobj->parent) {
+               do {
+                       top_kobj = top_kobj->parent;
+               } while (!top_kobj->kset && top_kobj->parent);
+       }
+       if (!top_kobj->kset)
+               goto out;
+       kset = top_kobj->kset;
+       if (!kset->uevent_ops || !kset->uevent_ops->uevent)
+               goto out;
+
+       /* respect filter */
+       if (kset->uevent_ops && kset->uevent_ops->filter)
+               if (!kset->uevent_ops->filter(kset, &dev->kobj))
+                       goto out;
+
+       /* let the kset specific function add its keys */
+       pos = data;
+       retval = kset->uevent_ops->uevent(kset, &dev->kobj,
+                                         envp, ARRAY_SIZE(envp),
+                                         pos, PAGE_SIZE);
+       if (retval)
+               goto out;
+
+       /* copy keys to file */
+       for (i = 0; envp[i]; i++) {
+               pos = &buf[count];
+               count += sprintf(pos, "%s\n", envp[i]);
+       }
+out:
+       return count;
+}
+
 static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
                            const char *buf, size_t count)
 {
+       if (memcmp(buf, "add", 3) != 0)
+               dev_err(dev, "uevent: unsupported action-string; this will "
+                       "be ignored in a future kernel version");
        kobject_uevent(&dev->kobj, KOBJ_ADD);
        return count;
 }
@@ -614,10 +671,11 @@ int device_add(struct device *dev)
                                             BUS_NOTIFY_ADD_DEVICE, dev);
 
        dev->uevent_attr.attr.name = "uevent";
-       dev->uevent_attr.attr.mode = S_IWUSR;
+       dev->uevent_attr.attr.mode = S_IRUGO | S_IWUSR;
        if (dev->driver)
                dev->uevent_attr.attr.owner = dev->driver->owner;
        dev->uevent_attr.store = store_uevent;
+       dev->uevent_attr.show = show_uevent;
        error = device_create_file(dev, &dev->uevent_attr);
        if (error)
                goto attrError;
@@ -670,10 +728,8 @@ int device_add(struct device *dev)
                goto PMError;
        if ((error = bus_add_device(dev)))
                goto BusError;
-       if (!dev->uevent_suppress)
-               kobject_uevent(&dev->kobj, KOBJ_ADD);
-       if ((error = bus_attach_device(dev)))
-               goto AttachError;
+       kobject_uevent(&dev->kobj, KOBJ_ADD);
+       bus_attach_device(dev);
        if (parent)
                klist_add_tail(&dev->knode_parent, &parent->klist_children);
 
@@ -692,8 +748,6 @@ int device_add(struct device *dev)
        kfree(class_name);
        put_device(dev);
        return error;
- AttachError:
-       bus_remove_device(dev);
  BusError:
        device_pm_remove(dev);
  PMError: