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

Reply via email to