mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
xen/livepatch: fix norevert test attempt to open-code revert
The purpose of the norevert test is to install a dummy handler that replaces
the internal Xen revert code, and then perform the revert in the post-revert
hook. For that purpose the usage of the previous common_livepatch_revert() is
not enough, as that just reverts specific functions, but not the whole state of
the payload.
Remove both common_livepatch_{apply,revert}() and instead expose
revert_payload{,_tail}() in order to perform the patch revert from the
post-revert hook.
Fixes: 6047104c3c ('livepatch: Add per-function applied/reverted state tracking marker')
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>
master commit: cdae267ce1
master date: 2024-02-28 16:57:25 +0000
This commit is contained in:
1 parent
50a8f74df7
commit
d81bfc7ff8
3 files changed
+46
-49
No files matched your search
+37
-4
@@ -1366,7 +1366,22 @@ static int apply_payload(struct payload *data)
|
||||
ASSERT(!local_irq_is_enabled());
|
||||
|
||||
for ( i = 0; i < data->nfuncs; i++ )
|
||||
common_livepatch_apply(&data->funcs[i], &data->fstate[i]);
|
||||
{
|
||||
const struct livepatch_func *func = &data->funcs[i];
|
||||
struct livepatch_fstate *state = &data->fstate[i];
|
||||
|
||||
/* If the action has been already executed on this function, do nothing. */
|
||||
if ( state->applied == LIVEPATCH_FUNC_APPLIED )
|
||||
{
|
||||
printk(XENLOG_WARNING LIVEPATCH
|
||||
"%s: %s has been already applied before\n",
|
||||
__func__, func->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
arch_livepatch_apply(func, state);
|
||||
state->applied = LIVEPATCH_FUNC_APPLIED;
|
||||
}
|
||||
|
||||
arch_livepatch_revive();
|
||||
|
||||
@@ -1382,7 +1397,7 @@ static inline void apply_payload_tail(struct payload *data)
|
||||
data->state = LIVEPATCH_STATE_APPLIED;
|
||||
}
|
||||
|
||||
static int revert_payload(struct payload *data)
|
||||
int revert_payload(struct payload *data)
|
||||
{
|
||||
unsigned int i;
|
||||
int rc;
|
||||
@@ -1397,7 +1412,25 @@ static int revert_payload(struct payload *data)
|
||||
}
|
||||
|
||||
for ( i = 0; i < data->nfuncs; i++ )
|
||||
common_livepatch_revert(&data->funcs[i], &data->fstate[i]);
|
||||
{
|
||||
const struct livepatch_func *func = &data->funcs[i];
|
||||
struct livepatch_fstate *state = &data->fstate[i];
|
||||
|
||||
/*
|
||||
* If the apply action hasn't been executed on this function, do
|
||||
* nothing.
|
||||
*/
|
||||
if ( !func->old_addr || state->applied == LIVEPATCH_FUNC_NOT_APPLIED )
|
||||
{
|
||||
printk(XENLOG_WARNING LIVEPATCH
|
||||
"%s: %s has not been applied before\n",
|
||||
__func__, func->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
arch_livepatch_revert(func, state);
|
||||
state->applied = LIVEPATCH_FUNC_NOT_APPLIED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Since we are running with IRQs disabled and the hooks may call common
|
||||
@@ -1415,7 +1448,7 @@ static int revert_payload(struct payload *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void revert_payload_tail(struct payload *data)
|
||||
void revert_payload_tail(struct payload *data)
|
||||
{
|
||||
list_del(&data->applied_list);
|
||||
|
||||
|
||||
@@ -136,35 +136,11 @@ void arch_livepatch_post_action(void);
|
||||
void arch_livepatch_mask(void);
|
||||
void arch_livepatch_unmask(void);
|
||||
|
||||
static inline void common_livepatch_apply(const struct livepatch_func *func,
|
||||
struct livepatch_fstate *state)
|
||||
{
|
||||
/* If the action has been already executed on this function, do nothing. */
|
||||
if ( state->applied == LIVEPATCH_FUNC_APPLIED )
|
||||
{
|
||||
printk(XENLOG_WARNING LIVEPATCH "%s: %s has been already applied before\n",
|
||||
__func__, func->name);
|
||||
return;
|
||||
}
|
||||
/* Only for testing purposes. */
|
||||
struct payload;
|
||||
int revert_payload(struct payload *data);
|
||||
void revert_payload_tail(struct payload *data);
|
||||
|
||||
arch_livepatch_apply(func, state);
|
||||
state->applied = LIVEPATCH_FUNC_APPLIED;
|
||||
}
|
||||
|
||||
static inline void common_livepatch_revert(const struct livepatch_func *func,
|
||||
struct livepatch_fstate *state)
|
||||
{
|
||||
/* If the apply action hasn't been executed on this function, do nothing. */
|
||||
if ( !func->old_addr || state->applied == LIVEPATCH_FUNC_NOT_APPLIED )
|
||||
{
|
||||
printk(XENLOG_WARNING LIVEPATCH "%s: %s has not been applied before\n",
|
||||
__func__, func->name);
|
||||
return;
|
||||
}
|
||||
|
||||
arch_livepatch_revert(func, state);
|
||||
state->applied = LIVEPATCH_FUNC_NOT_APPLIED;
|
||||
}
|
||||
#else
|
||||
|
||||
/*
|
||||
|
||||
@@ -96,26 +96,14 @@ static int revert_hook(livepatch_payload_t *payload)
|
||||
|
||||
static void post_revert_hook(livepatch_payload_t *payload)
|
||||
{
|
||||
int i;
|
||||
unsigned long flags;
|
||||
|
||||
printk(KERN_DEBUG "%s: Hook starting.\n", __func__);
|
||||
|
||||
for (i = 0; i < payload->nfuncs; i++)
|
||||
{
|
||||
const struct livepatch_func *func = &payload->funcs[i];
|
||||
struct livepatch_fstate *fstate = &payload->fstate[i];
|
||||
|
||||
BUG_ON(revert_cnt != 1);
|
||||
BUG_ON(fstate->applied != LIVEPATCH_FUNC_APPLIED);
|
||||
|
||||
/* Outside of quiesce zone: MAY TRIGGER HOST CRASH/UNDEFINED BEHAVIOR */
|
||||
arch_livepatch_quiesce();
|
||||
common_livepatch_revert(payload);
|
||||
arch_livepatch_revive();
|
||||
BUG_ON(fstate->applied == LIVEPATCH_FUNC_APPLIED);
|
||||
|
||||
printk(KERN_DEBUG "%s: post reverted: %s\n", __func__, func->name);
|
||||
}
|
||||
local_irq_save(flags);
|
||||
BUG_ON(revert_payload(payload));
|
||||
revert_payload_tail(payload);
|
||||
local_irq_restore(flags);
|
||||
|
||||
printk(KERN_DEBUG "%s: Hook done.\n", __func__);
|
||||
}
|
||||
|
||||