mirror of https://github.com/dynup/kpatch
fix list corruption in special section handlers
The kpatch_regenerate_* functions use a local list_head to construct the
new list. While the local list_head is copied to the sec->relas after
it is built, the neighboring nodes in the list are not updated, leading
to list corruption.
This commit uses list_replace() which updates the neighbor nodes properly.
Regression introduced by PR #117 5d36dd1
.
Fixes #185.
Signed-off-by: Seth Jennings <sjenning@redhat.com>
This commit is contained in:
parent
d55523f624
commit
2b92531df2
|
@ -1029,7 +1029,7 @@ void kpatch_regenerate_bug_table_rela_section(struct kpatch_elf *kelf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* overwrite with new relas list */
|
/* overwrite with new relas list */
|
||||||
sec->relas = newrelas;
|
list_replace(&newrelas, &sec->relas);
|
||||||
|
|
||||||
/* include both rela and text sections */
|
/* include both rela and text sections */
|
||||||
sec->include = 1;
|
sec->include = 1;
|
||||||
|
@ -1076,7 +1076,7 @@ void kpatch_regenerate_smp_locks_sections(struct kpatch_elf *kelf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* overwrite with new relas list */
|
/* overwrite with new relas list */
|
||||||
sec->relas = newrelas;
|
list_replace(&newrelas, &sec->relas);
|
||||||
|
|
||||||
/* include both rela and text sections */
|
/* include both rela and text sections */
|
||||||
sec->include = 1;
|
sec->include = 1;
|
||||||
|
@ -1141,7 +1141,7 @@ void kpatch_regenerate_parainstructions_sections(struct kpatch_elf *kelf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* overwrite with new relas table */
|
/* overwrite with new relas table */
|
||||||
sec->relas = newrelas;
|
list_replace(&newrelas, &sec->relas);
|
||||||
|
|
||||||
/* mark sections for inclusion */
|
/* mark sections for inclusion */
|
||||||
sec->include = 1;
|
sec->include = 1;
|
||||||
|
|
|
@ -142,6 +142,22 @@ static inline void list_del(struct list_head *entry)
|
||||||
entry->prev = LIST_POISON2;
|
entry->prev = LIST_POISON2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_replace - replace old entry by new one
|
||||||
|
* @old : the element to be replaced
|
||||||
|
* @new : the new element to insert
|
||||||
|
*
|
||||||
|
* If @old was empty, it will be overwritten.
|
||||||
|
*/
|
||||||
|
static inline void list_replace(struct list_head *old,
|
||||||
|
struct list_head *new)
|
||||||
|
{
|
||||||
|
new->next = old->next;
|
||||||
|
new->next->prev = new;
|
||||||
|
new->prev = old->prev;
|
||||||
|
new->prev->next = new;
|
||||||
|
}
|
||||||
|
|
||||||
#define list_entry(ptr, type, member) \
|
#define list_entry(ptr, type, member) \
|
||||||
container_of(ptr, type, member)
|
container_of(ptr, type, member)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue