linux Failing to preserve invariant causes buffer overflow

Function add_uevent_var() shall guarantee that env->buflen > 0 when it succeeds (i.e. returns 0). However, if !HOTPLUG this function behaves incorrectly, succeeding but not writing anything to env->buf so env->buflen == 0. A subsequent call to input_add_uevent_modalias_var() after the env was initialized executes env->buf[env->buflen - 1] = 'x'. The array index is -1, since env->buflen == 0, and this statement overwrites env->envp_idx which is located right before env->buf in the stack.
Bug fixed by commit 60e233a5660
Type BufferOverflow
Config "!HOTPLUG" (1st degree)
Fix-in code
Location drivers/
#include <errno.h>
#include <stdio.h>

#define UEVENT_BUFFER_SIZE		2048	/* buffer for the variables */

static char buf[UEVENT_BUFFER_SIZE];
static int buflen = 0;

#if defined(CONFIG_HOTPLUG)
int add_uevent_var()
{
  int len = sprintf(&buf[buflen], "MODALIAS=");
  buflen += len + 1;
  return 0;
}
#else
int add_uevent_var()
{ return 0; } // (2)
#endif

int input_add_uevent_modalias_var()
{
  if (add_uevent_var())
    return -ENOMEM;

  buf[buflen - 1] = 'x'; // ERROR: buflen == 0, so buf[-1] is written.
  return 0;
}

int main(int argc, char** argv)
{
  input_add_uevent_modalias_var(); // (1)
  return 0;
}
diff --git a/simple/60e233a.c b/simple/60e233a.c
--- a/simple/60e233a.c
+++ b/simple/60e233a.c
@@ -16,7 +16,7 @@
 }
 #else
 int add_uevent_var()
-{ return 0; }
+{ return -ENOMEM; }
 #endif
 
 int input_add_uevent_modalias_var()
#include <errno.h>
#include <stdio.h>

#define UEVENT_BUFFER_SIZE		2048	/* buffer for the variables */

static char buf[UEVENT_BUFFER_SIZE];
static int buflen = 0;

int main(int argc, char** argv)
{
//  input_add_uevent_modalias_var();
  int r;
#if defined(CONFIG_HOTPLUG)
  int len = sprintf(&buf[buflen], "MODALIAS=");
  buflen += len + 1;
  r = 0;
#else
  r = 0;
#endif
  if (r)
    return -ENOMEM;

  buf[buflen - 1] = 'x'; // ERROR: buflen == 0, so buf[-1] is written.
  return 0;
}
. call drivers/base/core.c:310:show_uevent()
. 336: env = kzalloc(sizeof(struct kobj_uevent_env), GFP_KERNEL);
. 341: retval = kset->uevent_ops->uevent(kset, &dev->kobj, env);
.. dyn-call drivers/base/core.c:243:dev_uevent()
.. 246: struct device *dev = kobj_to_dev(kobj);
.. 294: retval = dev->type->uevent(dev, env);
... dyn-call drivers/input/input.c:1485:input_dev_uevent()
... 1519: INPUT_ADD_HOTPLUG_MODALIAS_VAR(dev);
.... call drivers/input/input.c:1446:input_add_uevent_modalias_var()
.... 1451: if (add_uevent_var(env, "MODALIAS="))
...... call include/linux/kobject.h:225:add_uevent_var()
...... 227: return 0;
.... ERROR 1454: len = input_print_modalias(&env->buf[env->buflen - 1],