Skip to content

Commit

Permalink
driver/base/memory.c: validate memory block size early
Browse files Browse the repository at this point in the history
Let's validate the memory block size early, when initializing the memory
device infrastructure.  Fail hard in case the value is not suitable.

As nobody checks the return value of memory_dev_init(), turn it into a
void function and fail with a panic in all scenarios instead.  Otherwise,
we'll crash later during boot when core/drivers expect that the memory
device infrastructure (including memory_block_size_bytes()) works as
expected.

I think long term, we should move the whole memory block size
configuration (set_memory_block_size_order() and
memory_block_size_bytes()) into drivers/base/memory.c.

Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: David Hildenbrand <[email protected]>
Cc: Greg Kroah-Hartman <[email protected]>
Cc: "Rafael J. Wysocki" <[email protected]>
Cc: Pavel Tatashin <[email protected]>
Cc: Michal Hocko <[email protected]>
Cc: Dan Williams <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
davidhildenbrand authored and torvalds committed Sep 24, 2019
1 parent f915fb7 commit 902ce63
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 25 deletions.
31 changes: 9 additions & 22 deletions drivers/base/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,21 +100,6 @@ unsigned long __weak memory_block_size_bytes(void)
}
EXPORT_SYMBOL_GPL(memory_block_size_bytes);

static unsigned long get_memory_block_size(void)
{
unsigned long block_sz;

block_sz = memory_block_size_bytes();

/* Validate blk_sz is a power of 2 and not less than section size */
if ((block_sz & (block_sz - 1)) || (block_sz < MIN_MEMORY_BLOCK_SIZE)) {
WARN_ON(1);
block_sz = MIN_MEMORY_BLOCK_SIZE;
}

return block_sz;
}

/*
* Show the first physical section index (number) of this memory block.
*/
Expand Down Expand Up @@ -461,7 +446,7 @@ static DEVICE_ATTR_RO(removable);
static ssize_t block_size_bytes_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
return sprintf(buf, "%lx\n", get_memory_block_size());
return sprintf(buf, "%lx\n", memory_block_size_bytes());
}

static DEVICE_ATTR_RO(block_size_bytes);
Expand Down Expand Up @@ -812,19 +797,22 @@ static const struct attribute_group *memory_root_attr_groups[] = {
/*
* Initialize the sysfs support for memory devices...
*/
int __init memory_dev_init(void)
void __init memory_dev_init(void)
{
int ret;
int err;
unsigned long block_sz, nr;

/* Validate the configured memory block size */
block_sz = memory_block_size_bytes();
if (!is_power_of_2(block_sz) || block_sz < MIN_MEMORY_BLOCK_SIZE)
panic("Memory block size not suitable: 0x%lx\n", block_sz);
sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;

ret = subsys_system_register(&memory_subsys, memory_root_attr_groups);
if (ret)
goto out;

block_sz = get_memory_block_size();
sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;

/*
* Create entries for memory sections that were found
* during boot and have been initialized
Expand All @@ -840,8 +828,7 @@ int __init memory_dev_init(void)

out:
if (ret)
printk(KERN_ERR "%s() failed: %d\n", __func__, ret);
return ret;
panic("%s() failed: %d\n", __func__, ret);
}

/**
Expand Down
6 changes: 3 additions & 3 deletions include/linux/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ struct mem_section;
#define IPC_CALLBACK_PRI 10

#ifndef CONFIG_MEMORY_HOTPLUG_SPARSE
static inline int memory_dev_init(void)
static inline void memory_dev_init(void)
{
return 0;
return;
}
static inline int register_memory_notifier(struct notifier_block *nb)
{
Expand Down Expand Up @@ -113,7 +113,7 @@ extern int register_memory_isolate_notifier(struct notifier_block *nb);
extern void unregister_memory_isolate_notifier(struct notifier_block *nb);
int create_memory_block_devices(unsigned long start, unsigned long size);
void remove_memory_block_devices(unsigned long start, unsigned long size);
extern int memory_dev_init(void);
extern void memory_dev_init(void);
extern int memory_notify(unsigned long val, void *v);
extern int memory_isolate_notify(unsigned long val, void *v);
extern struct memory_block *find_memory_block(struct mem_section *);
Expand Down

0 comments on commit 902ce63

Please sign in to comment.