Re: [PATCH 1/2] tpm/eventlog/tpm1: Simplify walking over *pos measurements
From: Jarkko Sakkinen <hidden>
Date: 2019-01-18 15:18:37
Also in:
lkml
On Thu, Jan 17, 2019 at 09:32:55AM +0800, Jia Zhang wrote:
On 2019/1/17 上午6:09, Jarkko Sakkinen wrote:quoted
Please use "tpm:" tag for commits, not "tpm/eventlog/tpm1". On Fri, Jan 11, 2019 at 04:59:32PM +0800, Jia Zhang wrote:quoted
The responsibility of tpm1_bios_measurements_start() is to walk over the first *pos measurements, ensuring the skipped and to-be-read measurements are not out-of-boundary. Current logic is complicated a bit. Just employ a do-while loop with necessary sanity check, and then get the goal. Signed-off-by: Jia Zhang <redacted>What does this fix? Even if the current logic is "complicated", it is still a pretty simple functiion.OK. Let me point out the fix part. Here is the original implementation: 87 /* read over *pos measurements */ 88 for (i = 0; i < *pos; i++) { 89 event = addr; 90 91 converted_event_size = 92 do_endian_conversion(event->event_size); 93 converted_event_type = 94 do_endian_conversion(event->event_type); 95 96 if ((addr + sizeof(struct tcpa_event)) < limit) { 97 if ((converted_event_type == 0) && 98 (converted_event_size == 0)) 99 return NULL; 100 addr += (sizeof(struct tcpa_event) + 101 converted_event_size); 102 } 103 } The problem (just ignore all off-by-1 issues) is that accessing to event_size and event_type is not pre-checked carefully. In the latter part of tpm1_bios_measurements_start() and tpm1_bios_measurements_next(), there is a fixed patter to do the sanity check like this: 136 /* now check if current entry is valid */ 137 if ((v + sizeof(struct tcpa_event)) >= limit) 138 return NULL; So if we simply change this read-over chunk with sanity check like this: /* read over *pos measurements */ for (i = 0; i < *pos; i++) { event = addr; if ((addr + sizeof(struct tcpa_event)) >= limit) return NULL; converted_event_size = do_endian_conversion(event->event_size); converted_event_type = do_endian_conversion(event->event_type); if ((converted_event_type == 0) && (converted_event_size == 0)) return NULL; addr += (sizeof(struct tcpa_event) + converted_event_size); } We will get two highly similar code chunks in tpm1_bios_measurements_start(). Here is the latter part: 106 /* now check if current entry is valid */ 107 if ((addr + sizeof(struct tcpa_event)) >= limit) 108 return NULL; 109 110 event = addr; 111 112 converted_event_size = do_endian_conversion(event->event_size); 113 converted_event_type = do_endian_conversion(event->event_type); 114 115 if (((converted_event_type == 0) && (converted_event_size == 0)) 116 || ((addr + sizeof(struct tcpa_event) + converted_event_size) 117 >= limit)) 118 return NULL; 119 120 return addr; So using a do while logic can simply merge them together and thus simply and optimize the logic of walking over *pos measurements. Sorry I admit my initial motivation is to fix up the sanity check problem. If you would like to accept the optimization part, I will split this patch.
OK, got it now. I think I will apply this! Will take a while because of https://lkml.org/lkml/2019/1/18/485. Will not apply new patches before that is rooted. /Jarkko