Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e610499e authored by Rusty Russell's avatar Rusty Russell
Browse files

module: __module_address



Impact: New API, cleanup

ksplice wants to know the bounds of a module, not just the module text.

It makes sense to have __module_address.  We then implement
is_module_address and __module_text_address in terms of this (and
change is_module_text_address() to bool while we're at it).

Also, add proper kerneldoc for them all.

Cc: Anders Kaseorg <andersk@mit.edu>
Cc: Jeff Arnold <jbarnold@mit.edu>
Cc: Tim Abbott <tabbott@mit.edu>
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 414fd31b
Loading
Loading
Loading
Loading
+15 −5
Original line number Diff line number Diff line
@@ -365,7 +365,9 @@ static inline int module_is_live(struct module *mod)
/* Is this address in a module? (second is with no locks, for oops) */
struct module *module_text_address(unsigned long addr);
struct module *__module_text_address(unsigned long addr);
int is_module_address(unsigned long addr);
struct module *__module_address(unsigned long addr);
bool is_module_address(unsigned long addr);
bool is_module_text_address(unsigned long addr);

static inline int within_module_core(unsigned long addr, struct module *mod)
{
@@ -494,21 +496,29 @@ search_module_extables(unsigned long addr)
	return NULL;
}

/* Is this address in a module? */
static inline struct module *module_text_address(unsigned long addr)
{
	return NULL;
}

/* Is this address in a module? (don't take a lock, we're oopsing) */
static inline struct module *__module_address(unsigned long addr)
{
	return NULL;
}

static inline struct module *__module_text_address(unsigned long addr)
{
	return NULL;
}

static inline int is_module_address(unsigned long addr)
static inline bool is_module_address(unsigned long addr)
{
	return 0;
	return false;
}

static inline bool is_module_text_address(unsigned long addr)
{
	return false;
}

/* Get/put a kernel symbol (calls should be symmetric) */
+58 −18
Original line number Diff line number Diff line
@@ -76,7 +76,7 @@ static DECLARE_WAIT_QUEUE_HEAD(module_wq);

static BLOCKING_NOTIFIER_HEAD(module_notify_list);

/* Bounds of module allocation, for speeding __module_text_address */
/* Bounds of module allocation, for speeding __module_address */
static unsigned long module_addr_min = -1UL, module_addr_max = 0;

int register_module_notifier(struct notifier_block * nb)
@@ -2745,29 +2745,31 @@ const struct exception_table_entry *search_module_extables(unsigned long addr)
}

/*
 * Is this a valid module address?
 * is_module_address - is this address inside a module?
 * @addr: the address to check.
 *
 * See is_module_text_address() if you simply want to see if the address
 * is code (not data).
 */
int is_module_address(unsigned long addr)
bool is_module_address(unsigned long addr)
{
	struct module *mod;
	bool ret;

	preempt_disable();

	list_for_each_entry_rcu(mod, &modules, list) {
		if (within_module_core(addr, mod)) {
			preempt_enable();
			return 1;
		}
	}

	ret = __module_address(addr) != NULL;
	preempt_enable();

	return 0;
	return ret;
}


/* Is this a valid kernel address? */
__notrace_funcgraph struct module *__module_text_address(unsigned long addr)
/*
 * __module_address - get the module which contains an address.
 * @addr: the address.
 *
 * Must be called with preempt disabled or module mutex held so that
 * module doesn't get freed during this.
 */
__notrace_funcgraph struct module *__module_address(unsigned long addr)
{
	struct module *mod;

@@ -2775,12 +2777,50 @@ __notrace_funcgraph struct module *__module_text_address(unsigned long addr)
		return NULL;

	list_for_each_entry_rcu(mod, &modules, list)
		if (within(addr, mod->module_init, mod->init_text_size)
		    || within(addr, mod->module_core, mod->core_text_size))
		if (within_module_core(addr, mod)
		    || within_module_init(addr, mod))
			return mod;
	return NULL;
}

/*
 * is_module_text_address - is this address inside module code?
 * @addr: the address to check.
 *
 * See is_module_address() if you simply want to see if the address is
 * anywhere in a module.  See kernel_text_address() for testing if an
 * address corresponds to kernel or module code.
 */
bool is_module_text_address(unsigned long addr)
{
	bool ret;

	preempt_disable();
	ret = __module_text_address(addr) != NULL;
	preempt_enable();

	return ret;
}

/*
 * __module_text_address - get the module whose code contains an address.
 * @addr: the address.
 *
 * Must be called with preempt disabled or module mutex held so that
 * module doesn't get freed during this.
 */
struct module *__module_text_address(unsigned long addr)
{
	struct module *mod = __module_address(addr);
	if (mod) {
		/* Make sure it's within the text section. */
		if (!within(addr, mod->module_init, mod->init_text_size)
		    && !within(addr, mod->module_core, mod->core_text_size))
			mod = NULL;
	}
	return mod;
}

struct module *module_text_address(unsigned long addr)
{
	struct module *mod;