Skip to content

Commit

Permalink
s390/cio: fix measurement characteristics memleak
Browse files Browse the repository at this point in the history
Measurement characteristics are allocated during channel path
registration but not freed during deregistration. Fix this by
embedding these characteristics inside struct channel_path.

Signed-off-by: Sebastian Ott <sebott@linux.vnet.ibm.com>
Reviewed-by: Peter Oberparleiter <oberpar@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
  • Loading branch information
Sebastian Ott authored and Martin Schwidefsky committed Jan 26, 2016
1 parent d8f5122 commit 0d9bfe9
Show file tree
Hide file tree
Showing 3 changed files with 6 additions and 18 deletions.
6 changes: 3 additions & 3 deletions drivers/s390/cio/chp.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,11 @@ static ssize_t chp_measurement_chars_read(struct file *filp,

device = container_of(kobj, struct device, kobj);
chp = to_channelpath(device);
if (!chp->cmg_chars)
if (chp->cmg == -1)
return 0;

return memory_read_from_buffer(buf, count, &off,
chp->cmg_chars, sizeof(struct cmg_chars));
return memory_read_from_buffer(buf, count, &off, &chp->cmg_chars,
sizeof(chp->cmg_chars));
}

static struct bin_attribute chp_measurement_chars_attr = {
Expand Down
2 changes: 1 addition & 1 deletion drivers/s390/cio/chp.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ struct channel_path {
/* Channel-measurement related stuff: */
int cmg;
int shared;
void *cmg_chars;
struct cmg_chars cmg_chars;
};

/* Return channel_path struct for given chpid. */
Expand Down
16 changes: 2 additions & 14 deletions drivers/s390/cio/chsc.c
Original file line number Diff line number Diff line change
Expand Up @@ -967,22 +967,19 @@ static void
chsc_initialize_cmg_chars(struct channel_path *chp, u8 cmcv,
struct cmg_chars *chars)
{
struct cmg_chars *cmg_chars;
int i, mask;

cmg_chars = chp->cmg_chars;
for (i = 0; i < NR_MEASUREMENT_CHARS; i++) {
mask = 0x80 >> (i + 3);
if (cmcv & mask)
cmg_chars->values[i] = chars->values[i];
chp->cmg_chars.values[i] = chars->values[i];
else
cmg_chars->values[i] = 0;
chp->cmg_chars.values[i] = 0;
}
}

int chsc_get_channel_measurement_chars(struct channel_path *chp)
{
struct cmg_chars *cmg_chars;
int ccode, ret;

struct {
Expand All @@ -1006,11 +1003,6 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp)
u32 data[NR_MEASUREMENT_CHARS];
} __attribute__ ((packed)) *scmc_area;

chp->cmg_chars = NULL;
cmg_chars = kmalloc(sizeof(*cmg_chars), GFP_KERNEL);
if (!cmg_chars)
return -ENOMEM;

spin_lock_irq(&chsc_page_lock);
memset(chsc_page, 0, PAGE_SIZE);
scmc_area = chsc_page;
Expand Down Expand Up @@ -1042,14 +1034,10 @@ int chsc_get_channel_measurement_chars(struct channel_path *chp)
/* No cmg-dependent data. */
goto out;
}
chp->cmg_chars = cmg_chars;
chsc_initialize_cmg_chars(chp, scmc_area->cmcv,
(struct cmg_chars *) &scmc_area->data);
out:
spin_unlock_irq(&chsc_page_lock);
if (!chp->cmg_chars)
kfree(cmg_chars);

return ret;
}

Expand Down

0 comments on commit 0d9bfe9

Please sign in to comment.