ソースを参照

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
Guillem Jover 16 年 前
コミット
9b494da45e
共有2 個のファイルを変更した24 個の追加10 個の削除を含む
  1. 7 0
      debian/changelog
  2. 17 10
      utils/update-alternatives.c

+ 7 - 0
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 <guillem@debian.org>  Thu, 05 Aug 2010 17:42:51 +0200
+
 dpkg (1.15.8.3) unstable; urgency=low
 
   [ Raphaël Hertzog ]

+ 17 - 10
utils/update-alternatives.c

@@ -667,11 +667,25 @@ alternative_new(const char *name)
 	return alt;
 }
 
+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