mirror of
https://github.com/dynup/kpatch
synced 2025-02-07 04:31:33 +00:00
kmod/core: Check all patched functions only if replacement is in progress
kpatch_verify_activeness_safety() calls kpatch_backtrace_address_verify() for each address in the call traces of the processes. Among other things, kpatch_backtrace_address_verify() searches the whole set of functions for the ones being replaced (func->op == KPATCH_OP_UNPATCH). This is a waste of time when the patch is loaded or unloaded rather than replaced. Let us do the searching only if patch replacement is in progress. Signed-off-by: Evgenii Shatokhin <eshatokhin@virtuozzo.com>
This commit is contained in:
parent
3bd131612d
commit
f447c6f40e
@ -212,7 +212,8 @@ static inline int kpatch_compare_addresses(unsigned long stack_addr,
|
||||
}
|
||||
|
||||
static int kpatch_backtrace_address_verify(struct kpatch_module *kpmod,
|
||||
unsigned long address)
|
||||
unsigned long address,
|
||||
bool replace)
|
||||
{
|
||||
struct kpatch_func *func;
|
||||
int i;
|
||||
@ -247,8 +248,11 @@ static int kpatch_backtrace_address_verify(struct kpatch_module *kpmod,
|
||||
} while_for_each_linked_func();
|
||||
|
||||
/* in the replace case, need to check the func hash as well */
|
||||
hash_for_each_rcu(kpatch_func_hash, i, func, node) {
|
||||
if (func->op == KPATCH_OP_UNPATCH && !func->force) {
|
||||
if (replace) {
|
||||
hash_for_each_rcu(kpatch_func_hash, i, func, node) {
|
||||
if (func->op != KPATCH_OP_UNPATCH || func->force)
|
||||
continue;
|
||||
|
||||
ret = kpatch_compare_addresses(address,
|
||||
func->new_addr,
|
||||
func->new_size,
|
||||
@ -267,7 +271,8 @@ static int kpatch_backtrace_address_verify(struct kpatch_module *kpmod,
|
||||
*
|
||||
* This function is called from stop_machine() context.
|
||||
*/
|
||||
static int kpatch_verify_activeness_safety(struct kpatch_module *kpmod)
|
||||
static int kpatch_verify_activeness_safety(struct kpatch_module *kpmod,
|
||||
bool replace)
|
||||
{
|
||||
struct task_struct *g, *t;
|
||||
int i;
|
||||
@ -289,7 +294,8 @@ static int kpatch_verify_activeness_safety(struct kpatch_module *kpmod)
|
||||
if (trace.entries[i] == ULONG_MAX)
|
||||
break;
|
||||
ret = kpatch_backtrace_address_verify(kpmod,
|
||||
trace.entries[i]);
|
||||
trace.entries[i],
|
||||
replace);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
@ -365,7 +371,7 @@ static int kpatch_apply_patch(void *data)
|
||||
|
||||
kpmod = args->kpmod;
|
||||
|
||||
ret = kpatch_verify_activeness_safety(kpmod);
|
||||
ret = kpatch_verify_activeness_safety(kpmod, args->replace);
|
||||
if (ret) {
|
||||
kpatch_state_finish(KPATCH_STATE_FAILURE);
|
||||
return ret;
|
||||
@ -440,7 +446,7 @@ static int kpatch_remove_patch(void *data)
|
||||
struct kpatch_object *object;
|
||||
int ret;
|
||||
|
||||
ret = kpatch_verify_activeness_safety(kpmod);
|
||||
ret = kpatch_verify_activeness_safety(kpmod, false);
|
||||
if (ret) {
|
||||
kpatch_state_finish(KPATCH_STATE_FAILURE);
|
||||
return ret;
|
||||
|
Loading…
Reference in New Issue
Block a user