/
*
Allocate
and
load the module: note that size of section
0
is
always
zero,
and
we rely on this
for
optional sections.
*
/
static
int
load_module(struct load_info
*
info, const char __user
*
uargs,
int
flags)
{
struct module
*
mod;
long
err
=
0
;
char
*
after_dashes;
/
*
*
Do the signature check (
if
any
) first.
All
that
*
the signature check needs
is
info
-
>
len
, it does
*
not
need
any
of the section info. That can be
*
set
up later. This will minimize the chances
*
of a corrupt module causing problems before
*
we even get to the signature check.
*
*
The check will also adjust info
-
>
len
by stripping
*
off the sig length at the end of the module, making
*
checks against info
-
>
len
more correct.
*
/
err
=
module_sig_check(info, flags);
/
/
第一处签名校验
if
(err)
goto free_copy;
/
*
*
Do basic sanity checks against the ELF header
and
*
sections.
*
/
err
=
elf_validity_check(info);
if
(err) {
pr_err(
"Module has invalid ELF structures\n"
);
goto free_copy;
}
/
*
*
Everything checks out, so
set
up the section info
*
in
the info structure.
*
/
err
=
setup_load_info(info, flags);
if
(err)
goto free_copy;
/
*
*
Now that we know we have the correct module name, check
*
if
it's blacklisted.
*
/
if
(blacklisted(info
-
>name)) {
err
=
-
EPERM;
goto free_copy;
}
err
=
rewrite_section_headers(info, flags);
if
(err)
goto free_copy;
/
/
modstruct 版本校验
/
*
Check module struct version now, before we
try
to use module.
*
/
if
(!check_modstruct_version(info, info
-
>mod)) {
err
=
-
ENOEXEC;
goto free_copy;
}
/
*
Figure out module layout,
and
allocate
all
the memory.
*
/
mod
=
layout_and_allocate(info, flags);
if
(IS_ERR(mod)) {
err
=
PTR_ERR(mod);
goto free_copy;
}
audit_log_kern_module(mod
-
>name);
/
*
Reserve our place
in
the
list
.
*
/
err
=
add_unformed_module(mod);
if
(err)
goto free_module;
/
*
第二处签名校验
*
/
mod
-
>sig_ok
=
info
-
>sig_ok;
if
(!mod
-
>sig_ok) {
pr_notice_once(
"%s: module verification failed: signature "
"and/or required key missing - tainting "
"kernel\n"
, mod
-
>name);
add_taint_module(mod, TAINT_UNSIGNED_MODULE, LOCKDEP_STILL_OK);
}
/
*
To avoid stressing percpu allocator, do this once we're unique.
*
/
err
=
percpu_modalloc(mod, info);
if
(err)
goto unlink_mod;
/
*
Now module
is
in
final location, initialize linked lists, etc.
*
/
err
=
module_unload_init(mod);
if
(err)
goto unlink_mod;
init_param_lock(mod);
/
*
Now we've got everything
in
the final locations, we can
*
find optional sections.
*
/
err
=
find_module_sections(mod, info);
if
(err)
goto free_unload;
err
=
check_module_license_and_versions(mod);
if
(err)
goto free_unload;
/
*
Set
up MODINFO_ATTR fields
*
/
setup_modinfo(mod, info);
/
*
Fix up syms, so that st_value
is
a pointer to location.
*
/
err
=
simplify_symbols(mod, info);
if
(err <
0
)
goto free_modinfo;
err
=
apply_relocations(mod, info);
if
(err <
0
)
goto free_modinfo;
err
=
post_relocation(mod, info);
if
(err <
0
)
goto free_modinfo;
flush_module_icache(mod);
/
*
Now copy
in
args
*
/
mod
-
>args
=
strndup_user(uargs, ~
0UL
>>
1
);
if
(IS_ERR(mod
-
>args)) {
err
=
PTR_ERR(mod
-
>args);
goto free_arch_cleanup;
}
dynamic_debug_setup(mod, info
-
>debug, info
-
>num_debug);
/
*
Ftrace init must be called
in
the MODULE_STATE_UNFORMED state
*
/
ftrace_module_init(mod);
/
*
Finally it's fully formed, ready to start executing.
*
/
err
=
complete_formation(mod, info);
if
(err)
goto ddebug_cleanup;
err
=
prepare_coming_module(mod);
if
(err)
goto bug_cleanup;
/
*
Module
is
ready to execute: parsing args may do that.
*
/
after_dashes
=
parse_args(mod
-
>name, mod
-
>args, mod
-
>kp, mod
-
>num_kp,
-
32768
,
32767
, mod,
unknown_module_param_cb);
if
(IS_ERR(after_dashes)) {
err
=
PTR_ERR(after_dashes);
goto coming_cleanup;
}
else
if
(after_dashes) {
pr_warn(
"%s: parameters '%s' after `--' ignored\n"
,
mod
-
>name, after_dashes);
}
/
*
Link
in
to sysfs.
*
/
err
=
mod_sysfs_setup(mod, info, mod
-
>kp, mod
-
>num_kp);
if
(err <
0
)
goto coming_cleanup;
if
(is_livepatch_module(mod)) {
err
=
copy_module_elf(mod, info);
if
(err <
0
)
goto sysfs_cleanup;
}
/
*
Get rid of temporary copy.
*
/
free_copy(info);
/
*
Done!
*
/
trace_module_load(mod);
return
do_init_module(mod);
sysfs_cleanup:
mod_sysfs_teardown(mod);
coming_cleanup:
mod
-
>state
=
MODULE_STATE_GOING;
destroy_params(mod
-
>kp, mod
-
>num_kp);
blocking_notifier_call_chain(&module_notify_list,
MODULE_STATE_GOING, mod);
klp_module_going(mod);
bug_cleanup:
mod
-
>state
=
MODULE_STATE_GOING;
/
*
module_bug_cleanup needs module_mutex protection
*
/
mutex_lock(&module_mutex);
module_bug_cleanup(mod);
mutex_unlock(&module_mutex);
ddebug_cleanup:
ftrace_release_mod(mod);
dynamic_debug_remove(mod, info
-
>debug);
synchronize_rcu();
kfree(mod
-
>args);
free_arch_cleanup:
module_arch_cleanup(mod);
free_modinfo:
free_modinfo(mod);
free_unload:
module_unload_free(mod);
unlink_mod:
mutex_lock(&module_mutex);
/
*
Unlink carefully: kallsyms could be walking
list
.
*
/
list_del_rcu(&mod
-
>
list
);
mod_tree_remove(mod);
wake_up_all(&module_wq);
/
*
Wait
for
RCU
-
sched synchronizing before releasing mod
-
>
list
.
*
/
synchronize_rcu();
mutex_unlock(&module_mutex);
free_module:
/
*
Free lock
-
classes; relies on the preceding sync_rcu()
*
/
lockdep_free_key_range(mod
-
>core_layout.base, mod
-
>core_layout.size);
module_deallocate(mod, info);
free_copy:
free_copy(info);
return
err;
}