mirror of https://gitee.com/openkylin/linux.git
[PATCH] tpmdd: remove global event log
Remove global event log in the tpm bios event measurement log code that would have caused problems when the code was run concurrently. A log is now allocated and attached to the seq file upon open and destroyed appropriately. Signed-off-by: Kylene Jo Hall <kjhall@us.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
parent
5e38291d80
commit
d09cf7d77f
|
@ -29,6 +29,11 @@
|
||||||
#define MAX_TEXT_EVENT 1000 /* Max event string length */
|
#define MAX_TEXT_EVENT 1000 /* Max event string length */
|
||||||
#define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */
|
#define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */
|
||||||
|
|
||||||
|
struct tpm_bios_log {
|
||||||
|
void *bios_event_log;
|
||||||
|
void *bios_event_log_end;
|
||||||
|
};
|
||||||
|
|
||||||
struct acpi_tcpa {
|
struct acpi_tcpa {
|
||||||
struct acpi_table_header hdr;
|
struct acpi_table_header hdr;
|
||||||
u16 reserved;
|
u16 reserved;
|
||||||
|
@ -117,39 +122,34 @@ static const char* tcpa_pc_event_id_strings[] = {
|
||||||
"S-CRTM POST Contents",
|
"S-CRTM POST Contents",
|
||||||
};
|
};
|
||||||
|
|
||||||
/* (Binary) bios measurement buffer */
|
|
||||||
static void *tcg_eventlog;
|
|
||||||
static void *tcg_eventlog_addr_limit; /* MAX */
|
|
||||||
|
|
||||||
/* returns pointer to start of pos. entry of tcg log */
|
/* returns pointer to start of pos. entry of tcg log */
|
||||||
static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
|
static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos)
|
||||||
{
|
{
|
||||||
loff_t i;
|
loff_t i;
|
||||||
void *addr = tcg_eventlog;
|
struct tpm_bios_log *log = m->private;
|
||||||
|
void *addr = log->bios_event_log;
|
||||||
|
void *limit = log->bios_event_log_end;
|
||||||
struct tcpa_event *event;
|
struct tcpa_event *event;
|
||||||
|
|
||||||
/* read over *pos measurements */
|
/* read over *pos measurements */
|
||||||
for (i = 0; i < *pos; i++) {
|
for (i = 0; i < *pos; i++) {
|
||||||
event = addr;
|
event = addr;
|
||||||
|
|
||||||
if ((addr + sizeof(struct tcpa_event)) <
|
if ((addr + sizeof(struct tcpa_event)) < limit) {
|
||||||
tcg_eventlog_addr_limit) {
|
|
||||||
if (event->event_type == 0 && event->event_size == 0)
|
if (event->event_type == 0 && event->event_size == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
addr +=
|
addr += sizeof(struct tcpa_event) + event->event_size;
|
||||||
sizeof(struct tcpa_event) + event->event_size;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now check if current entry is valid */
|
/* now check if current entry is valid */
|
||||||
if ((addr + sizeof(struct tcpa_event)) >= tcg_eventlog_addr_limit)
|
if ((addr + sizeof(struct tcpa_event)) >= limit)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
event = addr;
|
event = addr;
|
||||||
|
|
||||||
if ((event->event_type == 0 && event->event_size == 0) ||
|
if ((event->event_type == 0 && event->event_size == 0) ||
|
||||||
((addr + sizeof(struct tcpa_event) + event->event_size) >=
|
((addr + sizeof(struct tcpa_event) + event->event_size) >= limit))
|
||||||
tcg_eventlog_addr_limit))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return addr;
|
return addr;
|
||||||
|
@ -159,11 +159,13 @@ static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
|
||||||
loff_t *pos)
|
loff_t *pos)
|
||||||
{
|
{
|
||||||
struct tcpa_event *event = v;
|
struct tcpa_event *event = v;
|
||||||
|
struct tpm_bios_log *log = m->private;
|
||||||
|
void *limit = log->bios_event_log_end;
|
||||||
|
|
||||||
v += sizeof(struct tcpa_event) + event->event_size;
|
v += sizeof(struct tcpa_event) + event->event_size;
|
||||||
|
|
||||||
/* now check if current entry is valid */
|
/* now check if current entry is valid */
|
||||||
if ((v + sizeof(struct tcpa_event)) >= tcg_eventlog_addr_limit)
|
if ((v + sizeof(struct tcpa_event)) >= limit)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
event = v;
|
event = v;
|
||||||
|
@ -172,8 +174,7 @@ static void *tpm_bios_measurements_next(struct seq_file *m, void *v,
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if ((event->event_type == 0 && event->event_size == 0) ||
|
if ((event->event_type == 0 && event->event_size == 0) ||
|
||||||
((v + sizeof(struct tcpa_event) + event->event_size) >=
|
((v + sizeof(struct tcpa_event) + event->event_size) >= limit))
|
||||||
tcg_eventlog_addr_limit))
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
(*pos)++;
|
(*pos)++;
|
||||||
|
@ -312,10 +313,14 @@ static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v)
|
||||||
static int tpm_bios_measurements_release(struct inode *inode,
|
static int tpm_bios_measurements_release(struct inode *inode,
|
||||||
struct file *file)
|
struct file *file)
|
||||||
{
|
{
|
||||||
if (tcg_eventlog) {
|
struct seq_file *seq = file->private_data;
|
||||||
kfree(tcg_eventlog);
|
struct tpm_bios_log *log = seq->private;
|
||||||
tcg_eventlog = NULL;
|
|
||||||
|
if (log) {
|
||||||
|
kfree(log->bios_event_log);
|
||||||
|
kfree(log);
|
||||||
}
|
}
|
||||||
|
|
||||||
return seq_release(inode, file);
|
return seq_release(inode, file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,13 +372,13 @@ static struct seq_operations tpm_binary_b_measurments_seqops = {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* read binary bios log */
|
/* read binary bios log */
|
||||||
static int read_log(void)
|
static int read_log(struct tpm_bios_log *log)
|
||||||
{
|
{
|
||||||
struct acpi_tcpa *buff;
|
struct acpi_tcpa *buff;
|
||||||
acpi_status status;
|
acpi_status status;
|
||||||
void *virt;
|
void *virt;
|
||||||
|
|
||||||
if (tcg_eventlog != NULL) {
|
if (log->bios_event_log != NULL) {
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
"%s: ERROR - Eventlog already initialized\n",
|
"%s: ERROR - Eventlog already initialized\n",
|
||||||
__func__);
|
__func__);
|
||||||
|
@ -393,25 +398,24 @@ static int read_log(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buff->log_max_len == 0) {
|
if (buff->log_max_len == 0) {
|
||||||
printk(KERN_ERR "%s: ERROR - TCPA log area empty\n",
|
printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__);
|
||||||
__func__);
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* malloc EventLog space */
|
/* malloc EventLog space */
|
||||||
tcg_eventlog = kmalloc(buff->log_max_len, GFP_KERNEL);
|
log->bios_event_log = kmalloc(buff->log_max_len, GFP_KERNEL);
|
||||||
if (!tcg_eventlog) {
|
if (!log->bios_event_log) {
|
||||||
printk
|
printk
|
||||||
("%s: ERROR - Not enough Memory for BIOS measurements\n",
|
("%s: ERROR - Not enough Memory for BIOS measurements\n",
|
||||||
__func__);
|
__func__);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
tcg_eventlog_addr_limit = tcg_eventlog + buff->log_max_len;
|
log->bios_event_log_end = log->bios_event_log + buff->log_max_len;
|
||||||
|
|
||||||
acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, &virt);
|
acpi_os_map_memory(buff->log_start_addr, buff->log_max_len, &virt);
|
||||||
|
|
||||||
memcpy(tcg_eventlog, virt, buff->log_max_len);
|
memcpy(log->bios_event_log, virt, buff->log_max_len);
|
||||||
|
|
||||||
acpi_os_unmap_memory(virt, buff->log_max_len);
|
acpi_os_unmap_memory(virt, buff->log_max_len);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -421,12 +425,26 @@ static int tpm_ascii_bios_measurements_open(struct inode *inode,
|
||||||
struct file *file)
|
struct file *file)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
struct tpm_bios_log *log;
|
||||||
|
struct seq_file *seq;
|
||||||
|
|
||||||
if ((err = read_log()))
|
log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
|
||||||
|
if (!log)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if ((err = read_log(log)))
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
/* now register seq file */
|
/* now register seq file */
|
||||||
return seq_open(file, &tpm_ascii_b_measurments_seqops);
|
err = seq_open(file, &tpm_ascii_b_measurments_seqops);
|
||||||
|
if (!err) {
|
||||||
|
seq = file->private_data;
|
||||||
|
seq->private = log;
|
||||||
|
} else {
|
||||||
|
kfree(log->bios_event_log);
|
||||||
|
kfree(log);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct file_operations tpm_ascii_bios_measurements_ops = {
|
struct file_operations tpm_ascii_bios_measurements_ops = {
|
||||||
|
@ -440,12 +458,26 @@ static int tpm_binary_bios_measurements_open(struct inode *inode,
|
||||||
struct file *file)
|
struct file *file)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
struct tpm_bios_log *log;
|
||||||
|
struct seq_file *seq;
|
||||||
|
|
||||||
if ((err = read_log()))
|
log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL);
|
||||||
|
if (!log)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
if ((err = read_log(log)))
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
/* now register seq file */
|
/* now register seq file */
|
||||||
return seq_open(file, &tpm_binary_b_measurments_seqops);
|
err = seq_open(file, &tpm_binary_b_measurments_seqops);
|
||||||
|
if (!err) {
|
||||||
|
seq = file->private_data;
|
||||||
|
seq->private = log;
|
||||||
|
} else {
|
||||||
|
kfree(log->bios_event_log);
|
||||||
|
kfree(log);
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct file_operations tpm_binary_bios_measurements_ops = {
|
struct file_operations tpm_binary_bios_measurements_ops = {
|
||||||
|
|
Loading…
Reference in New Issue