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:
Seth Jennings 2014-05-15 15:22:52 -05:00
parent d55523f624
commit 2b92531df2
2 changed files with 19 additions and 3 deletions

View File

@ -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;

View File

@ -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)