diff options
| author | Kay Sievers <kay.sievers@vrfy.org> | 2007-08-14 09:15:12 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-10-12 17:51:01 -0400 |
| commit | 7eff2e7a8b65c25920207324e56611150eb1cd9a (patch) | |
| tree | 02a0eeba9d25d996233e30c18f258dfae0ae2139 /arch | |
| parent | 8380770c842faef3001e44662953d64ad9a93663 (diff) | |
Driver core: change add_uevent_var to use a struct
This changes the uevent buffer functions to use a struct instead of a
long list of parameters. It does no longer require the caller to do the
proper buffer termination and size accounting, which is currently wrong
in some places. It fixes a known bug where parts of the uevent
environment are overwritten because of wrong index calculations.
Many thanks to Mathieu Desnoyers for finding bugs and improving the
error handling.
Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Cc: Cornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/ia64/sn/kernel/tiocx.c | 3 | ||||
| -rw-r--r-- | arch/powerpc/kernel/of_device.c | 37 | ||||
| -rw-r--r-- | arch/powerpc/kernel/vio.c | 16 | ||||
| -rw-r--r-- | arch/powerpc/platforms/ps3/system-bus.c | 9 |
4 files changed, 17 insertions, 48 deletions
diff --git a/arch/ia64/sn/kernel/tiocx.c b/arch/ia64/sn/kernel/tiocx.c index 5a289e4de838..a88eba3314d7 100644 --- a/arch/ia64/sn/kernel/tiocx.c +++ b/arch/ia64/sn/kernel/tiocx.c | |||
| @@ -66,8 +66,7 @@ static int tiocx_match(struct device *dev, struct device_driver *drv) | |||
| 66 | 66 | ||
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | static int tiocx_uevent(struct device *dev, char **envp, int num_envp, | 69 | static int tiocx_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 70 | char *buffer, int buffer_size) | ||
| 71 | { | 70 | { |
| 72 | return -ENODEV; | 71 | return -ENODEV; |
| 73 | } | 72 | } |
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index 89b911e83c04..8f3db32fac8b 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c | |||
| @@ -57,26 +57,21 @@ ssize_t of_device_get_modalias(struct of_device *ofdev, | |||
| 57 | return tsize; | 57 | return tsize; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | int of_device_uevent(struct device *dev, | 60 | int of_device_uevent(struct device *dev, struct kobj_uevent_env *env) |
| 61 | char **envp, int num_envp, char *buffer, int buffer_size) | ||
| 62 | { | 61 | { |
| 63 | struct of_device *ofdev; | 62 | struct of_device *ofdev; |
| 64 | const char *compat; | 63 | const char *compat; |
| 65 | int i = 0, length = 0, seen = 0, cplen, sl; | 64 | int seen = 0, cplen, sl; |
| 66 | 65 | ||
| 67 | if (!dev) | 66 | if (!dev) |
| 68 | return -ENODEV; | 67 | return -ENODEV; |
| 69 | 68 | ||
| 70 | ofdev = to_of_device(dev); | 69 | ofdev = to_of_device(dev); |
| 71 | 70 | ||
| 72 | if (add_uevent_var(envp, num_envp, &i, | 71 | if (add_uevent_var(env, "OF_NAME=%s", ofdev->node->name)) |
| 73 | buffer, buffer_size, &length, | ||
| 74 | "OF_NAME=%s", ofdev->node->name)) | ||
| 75 | return -ENOMEM; | 72 | return -ENOMEM; |
| 76 | 73 | ||
| 77 | if (add_uevent_var(envp, num_envp, &i, | 74 | if (add_uevent_var(env, "OF_TYPE=%s", ofdev->node->type)) |
| 78 | buffer, buffer_size, &length, | ||
| 79 | "OF_TYPE=%s", ofdev->node->type)) | ||
| 80 | return -ENOMEM; | 75 | return -ENOMEM; |
| 81 | 76 | ||
| 82 | /* Since the compatible field can contain pretty much anything | 77 | /* Since the compatible field can contain pretty much anything |
| @@ -85,9 +80,7 @@ int of_device_uevent(struct device *dev, | |||
| 85 | 80 | ||
| 86 | compat = of_get_property(ofdev->node, "compatible", &cplen); | 81 | compat = of_get_property(ofdev->node, "compatible", &cplen); |
| 87 | while (compat && *compat && cplen > 0) { | 82 | while (compat && *compat && cplen > 0) { |
| 88 | if (add_uevent_var(envp, num_envp, &i, | 83 | if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat)) |
| 89 | buffer, buffer_size, &length, | ||
| 90 | "OF_COMPATIBLE_%d=%s", seen, compat)) | ||
| 91 | return -ENOMEM; | 84 | return -ENOMEM; |
| 92 | 85 | ||
| 93 | sl = strlen (compat) + 1; | 86 | sl = strlen (compat) + 1; |
| @@ -96,25 +89,17 @@ int of_device_uevent(struct device *dev, | |||
| 96 | seen++; | 89 | seen++; |
| 97 | } | 90 | } |
| 98 | 91 | ||
| 99 | if (add_uevent_var(envp, num_envp, &i, | 92 | if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen)) |
| 100 | buffer, buffer_size, &length, | ||
| 101 | "OF_COMPATIBLE_N=%d", seen)) | ||
| 102 | return -ENOMEM; | 93 | return -ENOMEM; |
| 103 | 94 | ||
| 104 | /* modalias is trickier, we add it in 2 steps */ | 95 | /* modalias is trickier, we add it in 2 steps */ |
| 105 | if (add_uevent_var(envp, num_envp, &i, | 96 | if (add_uevent_var(env, "MODALIAS=")) |
| 106 | buffer, buffer_size, &length, | ||
| 107 | "MODALIAS=")) | ||
| 108 | return -ENOMEM; | 97 | return -ENOMEM; |
| 109 | 98 | sl = of_device_get_modalias(ofdev, &env->buf[env->buflen-1], | |
| 110 | sl = of_device_get_modalias(ofdev, &buffer[length-1], | 99 | sizeof(env->buf) - env->buflen); |
| 111 | buffer_size-length); | 100 | if (sl >= (sizeof(env->buf) - env->buflen)) |
| 112 | if (sl >= (buffer_size-length)) | ||
| 113 | return -ENOMEM; | 101 | return -ENOMEM; |
| 114 | 102 | env->buflen += sl; | |
| 115 | length += sl; | ||
| 116 | |||
| 117 | envp[i] = NULL; | ||
| 118 | 103 | ||
| 119 | return 0; | 104 | return 0; |
| 120 | } | 105 | } |
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index cb22a3557c4e..19a5656001c0 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
| @@ -317,30 +317,20 @@ static int vio_bus_match(struct device *dev, struct device_driver *drv) | |||
| 317 | return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL); | 317 | return (ids != NULL) && (vio_match_device(ids, vio_dev) != NULL); |
| 318 | } | 318 | } |
| 319 | 319 | ||
| 320 | static int vio_hotplug(struct device *dev, char **envp, int num_envp, | 320 | static int vio_hotplug(struct device *dev, struct kobj_uevent_env *env) |
| 321 | char *buffer, int buffer_size) | ||
| 322 | { | 321 | { |
| 323 | const struct vio_dev *vio_dev = to_vio_dev(dev); | 322 | const struct vio_dev *vio_dev = to_vio_dev(dev); |
| 324 | struct device_node *dn; | 323 | struct device_node *dn; |
| 325 | const char *cp; | 324 | const char *cp; |
| 326 | int length; | ||
| 327 | |||
| 328 | if (!num_envp) | ||
| 329 | return -ENOMEM; | ||
| 330 | 325 | ||
| 331 | dn = dev->archdata.of_node; | 326 | dn = dev->archdata.of_node; |
| 332 | if (!dn) | 327 | if (!dn) |
| 333 | return -ENODEV; | 328 | return -ENODEV; |
| 334 | cp = of_get_property(dn, "compatible", &length); | 329 | cp = of_get_property(dn, "compatible", NULL); |
| 335 | if (!cp) | 330 | if (!cp) |
| 336 | return -ENODEV; | 331 | return -ENODEV; |
| 337 | 332 | ||
| 338 | envp[0] = buffer; | 333 | add_uevent_var(env, "MODALIAS=vio:T%sS%s", vio_dev->type, cp); |
| 339 | length = scnprintf(buffer, buffer_size, "MODALIAS=vio:T%sS%s", | ||
| 340 | vio_dev->type, cp); | ||
| 341 | if ((buffer_size - length) <= 0) | ||
| 342 | return -ENOMEM; | ||
| 343 | envp[1] = NULL; | ||
| 344 | return 0; | 334 | return 0; |
| 345 | } | 335 | } |
| 346 | 336 | ||
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index 4bb634a17e43..ea0b2c790412 100644 --- a/arch/powerpc/platforms/ps3/system-bus.c +++ b/arch/powerpc/platforms/ps3/system-bus.c | |||
| @@ -437,18 +437,13 @@ static void ps3_system_bus_shutdown(struct device *_dev) | |||
| 437 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); | 437 | dev_dbg(&dev->core, " <- %s:%d\n", __func__, __LINE__); |
| 438 | } | 438 | } |
| 439 | 439 | ||
| 440 | static int ps3_system_bus_uevent(struct device *_dev, char **envp, | 440 | static int ps3_system_bus_uevent(struct device *_dev, struct kobj_uevent_env *env) |
| 441 | int num_envp, char *buffer, int buffer_size) | ||
| 442 | { | 441 | { |
| 443 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); | 442 | struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); |
| 444 | int i = 0, length = 0; | 443 | int i = 0, length = 0; |
| 445 | 444 | ||
| 446 | if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, | 445 | if (add_uevent_var(env, "MODALIAS=ps3:%d", dev->match_id)) |
| 447 | &length, "MODALIAS=ps3:%d", | ||
| 448 | dev->match_id)) | ||
| 449 | return -ENOMEM; | 446 | return -ENOMEM; |
| 450 | |||
| 451 | envp[i] = NULL; | ||
| 452 | return 0; | 447 | return 0; |
| 453 | } | 448 | } |
| 454 | 449 | ||
