From 7eff2e7a8b65c25920207324e56611150eb1cd9a Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 14 Aug 2007 15:15:12 +0200 Subject: 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 Cc: Mathieu Desnoyers Cc: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- drivers/input/input.c | 62 +++++++++++++++++---------------------------------- 1 file changed, 20 insertions(+), 42 deletions(-) (limited to 'drivers/input/input.c') diff --git a/drivers/input/input.c b/drivers/input/input.c index 5fe7555..5dc361c 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -859,87 +859,66 @@ static void input_dev_release(struct device *device) * Input uevent interface - loading event handlers based on * device bitfields. */ -static int input_add_uevent_bm_var(char **envp, int num_envp, int *cur_index, - char *buffer, int buffer_size, int *cur_len, +static int input_add_uevent_bm_var(struct kobj_uevent_env *env, const char *name, unsigned long *bitmap, int max) { - if (*cur_index >= num_envp - 1) - return -ENOMEM; - - envp[*cur_index] = buffer + *cur_len; + int len; - *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), name); - if (*cur_len >= buffer_size) + if (add_uevent_var(env, "%s=", name)) return -ENOMEM; - *cur_len += input_print_bitmap(buffer + *cur_len, - max(buffer_size - *cur_len, 0), - bitmap, max, 0) + 1; - if (*cur_len > buffer_size) + len = input_print_bitmap(&env->buf[env->buflen - 1], + sizeof(env->buf) - env->buflen, + bitmap, max, 0); + if (len >= (sizeof(env->buf) - env->buflen)) return -ENOMEM; - (*cur_index)++; + env->buflen += len; return 0; } -static int input_add_uevent_modalias_var(char **envp, int num_envp, int *cur_index, - char *buffer, int buffer_size, int *cur_len, +static int input_add_uevent_modalias_var(struct kobj_uevent_env *env, struct input_dev *dev) { - if (*cur_index >= num_envp - 1) - return -ENOMEM; - - envp[*cur_index] = buffer + *cur_len; + int len; - *cur_len += snprintf(buffer + *cur_len, max(buffer_size - *cur_len, 0), - "MODALIAS="); - if (*cur_len >= buffer_size) + if (add_uevent_var(env, "MODALIAS=")) return -ENOMEM; - *cur_len += input_print_modalias(buffer + *cur_len, - max(buffer_size - *cur_len, 0), - dev, 0) + 1; - if (*cur_len > buffer_size) + len = input_print_modalias(&env->buf[env->buflen - 1], + sizeof(env->buf) - env->buflen, + dev, 0); + if (len >= (sizeof(env->buf) - env->buflen)) return -ENOMEM; - (*cur_index)++; + env->buflen += len; return 0; } #define INPUT_ADD_HOTPLUG_VAR(fmt, val...) \ do { \ - int err = add_uevent_var(envp, num_envp, &i, \ - buffer, buffer_size, &len, \ - fmt, val); \ + int err = add_uevent_var(env, fmt, val); \ if (err) \ return err; \ } while (0) #define INPUT_ADD_HOTPLUG_BM_VAR(name, bm, max) \ do { \ - int err = input_add_uevent_bm_var(envp, num_envp, &i, \ - buffer, buffer_size, &len, \ - name, bm, max); \ + int err = input_add_uevent_bm_var(env, name, bm, max); \ if (err) \ return err; \ } while (0) #define INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev) \ do { \ - int err = input_add_uevent_modalias_var(envp, \ - num_envp, &i, \ - buffer, buffer_size, &len, \ - dev); \ + int err = input_add_uevent_modalias_var(env, dev); \ if (err) \ return err; \ } while (0) -static int input_dev_uevent(struct device *device, char **envp, - int num_envp, char *buffer, int buffer_size) +static int input_dev_uevent(struct device *device, struct kobj_uevent_env *env) { struct input_dev *dev = to_input_dev(device); - int i = 0; - int len = 0; INPUT_ADD_HOTPLUG_VAR("PRODUCT=%x/%x/%x/%x", dev->id.bustype, dev->id.vendor, @@ -971,7 +950,6 @@ static int input_dev_uevent(struct device *device, char **envp, INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev); - envp[i] = NULL; return 0; } -- cgit v1.1