[libvirt] [security-notice PATCH 3/9] scripts: add ability to handle a fixed commit hash

Daniel P. Berrangé berrange at redhat.com
Mon May 13 11:52:00 UTC 2019


Currently when given a broken commit hash we assume everything newer
than this is broken. If we are retroactively recording info on a flaw that
is already fixed in git though, we might know a fixed commit hash. Use
this info to know when to stop reporting broken tags and branches.

Note this only works for branches containing the original primary fixed
commit. This does not try to identify cherry-picks to branches.

Signed-off-by: Daniel P. Berrangé <berrange at redhat.com>
---
 scripts/report-vulnerable-tags.pl | 74 +++++++++++++++++++++++++++----
 1 file changed, 66 insertions(+), 8 deletions(-)

diff --git a/scripts/report-vulnerable-tags.pl b/scripts/report-vulnerable-tags.pl
index 8a6c2e4..431a7bf 100644
--- a/scripts/report-vulnerable-tags.pl
+++ b/scripts/report-vulnerable-tags.pl
@@ -5,15 +5,18 @@ use warnings;
 
 use Sort::Versions;
 
-if (int(@ARGV) != 1) {
-    die "syntax: $0 CHANGESET\n";
+if (int(@ARGV) != 1 && int(@ARGV) != 2) {
+    die "syntax: $0 BROKEN-CHANGESET [FIXED-CHANGESET]\n";
 }
 
-my $changeset = shift @ARGV;
+my $broken = shift @ARGV;
+my $fixed = shift @ARGV;
 
 # branch name to hash with keys
 #   - brokenchanges -> list of commit ids
 #   - brokentags -> hash of tag names to '1'
+#   - fixedchanges -> list of commit ids
+#   - fixedtags -> hash of tag names to '1'
 my %branches;
 
 # tag name to '0' (fixed) or '1' (broken)
@@ -68,11 +71,22 @@ sub add_branch {
     return if exists $branches{$name};
 
     $branches{$name} = {
-       "brokenchanges" => [$changeset],
+       "brokenchanges" => [$broken],
        "brokentags" => {},
+       "fixedchanges" => [],
+       "fixedtags" => {},
     };
 }
 
+sub delete_branch {
+    my $name = shift @_;
+
+    if (int(keys %{$branches{$name}->{"brokentags"}})) {
+	print "Branch $name shouldn't have broken tags\n";
+    }
+    delete $branches{$name};
+}
+
 sub add_broken_tag {
     my $branch = shift @_;
     my $tag = shift @_;
@@ -81,16 +95,51 @@ sub add_broken_tag {
     $branches{$branch}->{"brokentags"}->{$tag} = 1;
 }
 
+sub add_fixed_tag {
+    my $branch = shift @_;
+    my $tag = shift @_;
+
+    $tags{$tag} = 0;
+    $branches{$branch}->{"fixedtags"}->{$tag} = 1;
+}
+
+sub add_fixed_commit {
+    my $branch = shift @_;
+    my $commit = shift @_;
+
+    push @{$branches{$branch}->{"fixedchanges"}}, $commit;
+}
+
 add_branch("master");
 
+if (defined $fixed) {
+    # Mark any tags containing the fix as known so they
+    # get excluded when later finding vulnerable tags
+    for my $tag (get_tags("--contains", $fixed)) {
+       $tags{$tag} = 0;
+    }
+
+
+    # Record the first tag in master which has the fix, if any
+    my @fixedtags = sort versioncmp get_tags("--contains", $fixed, "--merged", "master");
+    if (int(@fixedtags)) {
+	add_fixed_tag("master", $fixedtags[0]);
+    }
+
+    add_fixed_commit("master", $fixed);
+}
+
 # Most tags live on master so lets get them first
-for my $tag (get_tags("--contains", $changeset, "--merged", "master")) {
+for my $tag (get_tags("--contains", $broken, "--merged", "master")) {
+
+    next if exists $tags{$tag};
+
     add_broken_tag("master", $tag);
 }
 
 # Now we need slower work to find branches for
 # few remaining tags
-for my $tag (get_tags("--contains", $changeset)) {
+for my $tag (get_tags("--contains", $broken)) {
 
     next if exists $tags{$tag};
 
@@ -117,6 +166,12 @@ for my $branch (get_branches($broken)) {
     add_branch($branch);
 }
 
+if (defined $fixed) {
+    for my $branch (get_branches($fixed)) {
+	delete_branch($branch);
+    }
+}
+
 foreach my $branch (sort versioncmp keys %branches) {
     print "    <branch>\n";
     print "      <name>$branch</name>\n";
@@ -127,8 +182,11 @@ foreach my $branch (sort versioncmp keys %branches) {
 	print "      <change state=\"vulnerable\">$commit</change>\n";
     }
 
-    if ($branch eq "master") {
-	print "      <change state=\"fixed\">$fixed</change>\n";
+    foreach my $tag (sort versioncmp keys %{$branches{$branch}->{"fixedtags"}}) {
+        print "      <tag state=\"fixed\">$tag</tag>\n";
+    }
+    foreach my $commit (@{$branches{$branch}->{"fixedchanges"}}) {
+	print "      <change state=\"fixed\">$commit</change>\n";
     }
     print "    </branch>\n";
 }
-- 
2.21.0




More information about the libvir-list mailing list