The following commit has been merged in the sid branch: commit 9b494da45eb2883a1b397a42aac4adc1f7899b6b Author: Guillem Jover <guil...@debian.org> Date: Thu Aug 5 17:48:45 2010 +0200
u-a: Fix use after free causing segfaults on --remove-all Refactor alternative_choices_free function and use it from alternative_reset() and for --remove-all. This was causing segfaults or bogus operation by not removing all choices. Closes: #591653, #591654 diff --git a/debian/changelog b/debian/changelog index 1e4f02c..6a748fc 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,10 @@ +dpkg (1.15.8.4) UNRELEASED; urgency=low + + * Fix use after free segfault on update-alternatives --remove-all. + Closes: #591653, #591654 + + -- Guillem Jover <guil...@debian.org> Thu, 05 Aug 2010 17:42:51 +0200 + dpkg (1.15.8.3) unstable; urgency=low [ Raphaƫl Hertzog ] diff --git a/utils/update-alternatives.c b/utils/update-alternatives.c index 52148c3..b1fc315 100644 --- a/utils/update-alternatives.c +++ b/utils/update-alternatives.c @@ -668,10 +668,24 @@ alternative_new(const char *name) } static void +alternative_choices_free(struct alternative *a) +{ + struct fileset *fs; + + if (a->choices) + a->modified = true; + + while (a->choices) { + fs = a->choices; + a->choices = fs->next; + fileset_free(fs); + } +} + +static void alternative_reset(struct alternative *alt) { struct slave_link *slave; - struct fileset *fs; struct commit_operation *commit_op; free(alt->master_link); @@ -681,11 +695,7 @@ alternative_reset(struct alternative *alt) alt->slaves = slave->next; slave_link_free(slave); } - while (alt->choices) { - fs = alt->choices; - alt->choices = fs->next; - fileset_free(fs); - } + alternative_choices_free(alt); while (alt->commit_ops) { commit_op = alt->commit_ops; alt->commit_ops = commit_op->next; @@ -2351,10 +2361,7 @@ main(int argc, char **argv) new_choice = best->master_file; } } else if (strcmp(action, "remove-all") == 0) { - struct fileset *fs; - - for (fs = a->choices; fs; fs = fs->next) - alternative_remove_choice(a, fs->master_file); + alternative_choices_free(a); } else if (strcmp(action, "install") == 0) { if (a->master_link) { /* Alternative already exists, check if anything got -- dpkg's main repository -- To UNSUBSCRIBE, email to debian-dpkg-cvs-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org