xorl %eax, %eax

Linux kernel TPM off-by-one Overwrite

leave a comment »

This was fixed in 2.6.30 and it was reported by Eric Paris of Red Hat on 9 June 2009. The bug affects Linux kernel from 2.6.16 and before 2.6.30 release. Here is the vulnerable routine from drivers/char/tpm/tpm_bios.c:

static int get_event_name(char *dest, struct tcpa_event *event,
unsigned char * event_entry)
{
const char *name = “”;
char data[40] = “”;
int i, n_len = 0, d_len = 0;
u32 event_id;

switch(event->event_type) {

case EVENT_TAG:
event_id = be32_to_cpu(*((u32 *)event_entry));

/* ToDo Row data -> Base64 */

switch (event_id) {

case ESCD:
name = tcpa_pc_event_id_strings[event_id];
n_len = strlen(name);
for (i = 0; i < 20; i++) d_len += sprintf(data, "%02x", event_entry[8 + i]); ... } ... } return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]", n_len, name, d_len, data); } [/sourcecode] The bug is located in the ESCD event ID case. Unsigned integer event_id is initialized earlier with event_entry's value if the event's type was that of EVENT_TAG. The bug is that even though data array is defined with a size of 40 bytes, the for loop in the ESCD case will attempt to write 41 since it will iterate 20 times, thus 40 bytes written into data but sprintf() will also NULL terminate the buffer. This NULL byte results in an off-by-one vulnerability. The fix was simple, they performed the following patch: [sourcecode language="c"] const char *name = ""; - char data[40] = ""; + /* 41 so there is room for 40 data and 1 nul */ + char data[41] = ""; int i, n_len = 0, d_len = 0; [/sourcecode]

Written by xorl

June 17, 2009 at 17:03

Posted in bugs, linux

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s