Comment 12 for bug 829980

Revision history for this message
James Hunt (jamesodhunt) wrote :

I believe I now understand the problem. This has nothing to do with Upstart - it's a kernel issue. Well, to be more precise, it's a problem with the firmware on your batteries coupled with the kernel not sanity checking device property values before handing them to userspace.

The file below in the kernel emits udev events on behalf of power supplies and batteries:

    drivers/power/power_supply_sysfs.c

The expectation is that a "struct power_supply"'s 'properties' are encoded in ASCII. But let's look at @smagoun's log...

$ grep "[^[:print:]]" udev_power_supply.txt|od -xc
0000000 4f50 4557 5f52 5553 5050 594c 4d5f 444f
          P O W E R _ S U P P L Y _ M O D
0000020 4c45 4e5f 4d41 3d45 5341 424d 3130 6332
          E L _ N A M E = A S M B 0 1 2 c
0000040 1468 f401 0ae0 4f50 4557 5f52 5553 5050
          h 024 001 364 340 \n P O W E R _ S U P P
0000060 594c 4d5f 4e41 4655 4341 5554 4552 3d52
          L Y _ M A N U F A C T U R E R =
0000100 654e 6577 5472 6365 1468 f401 0ae0 4f50
          N e w e r T e c h 024 001 364 340 \n P O
0000120 4557 5f52 5553 5050 594c 4d5f 444f 4c45
          W E R _ S U P P L Y _ M O D E L
0000140 4e5f 4d41 3d45 5341 424d 3130 6332 1468
          _ N A M E = A S M B 0 1 2 c h 024
0000160 f401 0ae0 4f50 4557 5f52 5553 5050 594c
        001 364 340 \n P O W E R _ S U P P L Y
0000200 4d5f 4e41 4655 4341 5554 4552 3d52 654e
          _ M A N U F A C T U R E R = N e
0000220 6577 5472 6365 1468 f401 0ae0
          w e r T e c h 024 001 364 340 \n
0000234
$

What we *expect* to see for the first entry is:

    POWER_SUPPLY_MODEL_NAME=ASMB012ch\n

What we *actually* see is

   POWER_SUPPLY_MODEL_NAME=ASMB012ch<garbage>\n

Where <garbage> in this case is "024 001 364 340" which are extended / non-printable characters. So this data gets sent across to userspace where it is picked up by udevd which then hands it on to upstart-udev-bridge. The bridge pulls apart the udev message and constructs an upstart event, adding all udev properties to that events environment. upstart_emit_event() does this by calling dbus_message_iter_append_basic(), but then that call barfs since it detects the non-printable characters. Since upstart wraps the call to upstart_emit_event() in an NIH_MUST(), upstart_emit_event() will get called forever until it succeeds (which it won't), thus maxing out your CPU.

One possible (generic) fix would be for lib/kobject_uevent.c:add_uevent_var() to remove all non-printable characters from uevent variables to avoid causing problems in userspace.