mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: David Howells <dhowells@redhat.com>
To: keyrings@vger.kernel.org
Cc: dhowells@redhat.com, linux-security-module@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH 4/6] KEYS: Provide a script to extract the sys cert list from a vmlinux file
Date: Wed, 21 Oct 2015 15:27:14 +0100	[thread overview]
Message-ID: <20151021142714.31251.49687.stgit@warthog.procyon.org.uk> (raw)
In-Reply-To: <20151021142646.31251.6867.stgit@warthog.procyon.org.uk>

The supplied script takes a vmlinux file - and if necessary a System.map
file - locates the system certificates list and extracts it to the named
file.

Call as:

    ./scripts/extract-sys-certs vmlinux certs

if vmlinux contains symbols and:

    ./scripts/extract-sys-certs -s System.map vmlinux certs

if it does not.

It prints something like the following to stdout:

	Have 27 sections
	No symbols in vmlinux, trying System.map
	Have 80088 symbols
	Have 1346 bytes of certs at VMA 0xffffffff8201c540
	Certificate list in section .init.data
	Certificate list at file offset 0x141c540

If vmlinux contains symbols then that is used rather than System.map - even
if one is given.

Signed-off-by: David Howells <dhowells@redhat.com>
---

 scripts/extract-sys-certs.pl |  144 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 144 insertions(+)
 create mode 100755 scripts/extract-sys-certs.pl

diff --git a/scripts/extract-sys-certs.pl b/scripts/extract-sys-certs.pl
new file mode 100755
index 000000000000..d476e7d1fd88
--- /dev/null
+++ b/scripts/extract-sys-certs.pl
@@ -0,0 +1,144 @@
+#!/usr/bin/perl -w
+#
+use strict;
+use Math::BigInt;
+use Fcntl "SEEK_SET";
+
+die "Format: $0 [-s <systemmap-file>] <vmlinux-file> <keyring-file>\n"
+    if ($#ARGV != 1 && $#ARGV != 3 ||
+	$#ARGV == 3 && $ARGV[0] ne "-s");
+
+my $sysmap = "";
+if ($#ARGV == 3) {
+    shift;
+    $sysmap = $ARGV[0];
+    shift;
+}
+
+my $vmlinux = $ARGV[0];
+my $keyring = $ARGV[1];
+
+#
+# Parse the vmlinux section table
+#
+open FD, "objdump -h $vmlinux |" || die $vmlinux;
+my @lines = <FD>;
+close(FD) || die $vmlinux;
+
+my @sections = ();
+
+foreach my $line (@lines) {
+    chomp($line);
+    if ($line =~ /\s*([0-9]+)\s+(\S+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+([0-9a-f]+)\s+2[*][*]([0-9]+)/
+	) {
+	my $seg  = $1;
+	my $name = $2;
+	my $len  = Math::BigInt->new("0x" . $3);
+	my $vma  = Math::BigInt->new("0x" . $4);
+	my $lma  = Math::BigInt->new("0x" . $5);
+	my $foff = Math::BigInt->new("0x" . $6);
+	my $align = 2 ** $7;
+
+	push @sections, { name => $name,
+			  vma => $vma,
+			  len => $len,
+			  foff => $foff };
+    }
+}
+
+print "Have $#sections sections\n";
+
+#
+# Try and parse the vmlinux symbol table.  If the vmlinux file has been created
+# from a vmlinuz file with extract-vmlinux then the symbol table will be empty.
+#
+open FD, "nm $vmlinux 2>/dev/null |" || die $vmlinux;
+@lines = <FD>;
+close(FD) || die $vmlinux;
+
+my %symbols = ();
+my $nr_symbols = 0;
+
+sub parse_symbols(@) {
+    foreach my $line (@_) {
+	chomp($line);
+	if ($line =~ /([0-9a-f]+)\s([a-zA-Z])\s(\S+)/
+	    ) {
+	    my $addr = "0x" . $1;
+	    my $type = $2;
+	    my $name = $3;
+
+	    $symbols{$name} = $addr;
+	    $nr_symbols++;
+	}
+    }
+}
+parse_symbols(@lines);
+
+if ($nr_symbols == 0 && $sysmap ne "") {
+    print "No symbols in vmlinux, trying $sysmap\n";
+
+    open FD, "<$sysmap" || die $sysmap;
+    @lines = <FD>;
+    close(FD) || die $sysmap;
+    parse_symbols(@lines);
+}
+
+die "No symbols available\n"
+    if ($nr_symbols == 0);
+
+print "Have $nr_symbols symbols\n";
+
+die "Can't find system certificate list"
+    unless (exists($symbols{"__cert_list_start"}) &&
+	    exists($symbols{"__cert_list_end"}));
+
+my $start = Math::BigInt->new($symbols{"__cert_list_start"});
+my $end = Math::BigInt->new($symbols{"__cert_list_end"});
+my $size = $end - $start;
+
+printf "Have %u bytes of certs at VMA 0x%x\n", $size, $start;
+
+my $s = undef;
+foreach my $sec (@sections) {
+    my $s_name = $sec->{name};
+    my $s_vma = $sec->{vma};
+    my $s_len = $sec->{len};
+    my $s_foff = $sec->{foff};
+    my $s_vend = $s_vma + $s_len;
+
+    next unless ($start >= $s_vma);
+    next if ($start >= $s_vend);
+
+    die "Cert object partially overflows section $s_name\n"
+	if ($end > $s_vend);
+
+    die "Cert object in multiple sections: ", $s_name, " and ", $s->{name}, "\n"
+	if ($s);
+    $s = $sec;
+}
+
+die "Cert object not inside a section\n"
+    unless ($s);
+
+print "Certificate list in section ", $s->{name}, "\n";
+
+my $foff = $start - $s->{vma} + $s->{foff};
+
+printf "Certificate list at file offset 0x%x\n", $foff;
+
+open FD, "<$vmlinux" || die $vmlinux;
+binmode(FD);
+die $vmlinux if (!defined(sysseek(FD, $foff, SEEK_SET)));
+my $buf = "";
+my $len = sysread(FD, $buf, $size);
+die "$vmlinux" if (!defined($len));
+die "Short read on $vmlinux\n" if ($len != $size);
+close(FD) || die $vmlinux;
+
+open FD, ">$keyring" || die $keyring;
+binmode(FD);
+$len = syswrite(FD, $buf, $size);
+die "$keyring" if (!defined($len));
+die "Short write on $keyring\n" if ($len != $size);
+close(FD) || die $keyring;


  parent reply	other threads:[~2015-10-21 14:27 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-10-21 14:26 [PATCH 1/6] KEYS: use kvfree() in add_key David Howells
2015-10-21 14:26 ` [PATCH 2/6] certs: add .gitignore to stop git nagging about x509_certificate_list David Howells
2015-10-21 14:27 ` [PATCH 3/6] keys: Be more consistent in selection of union members used David Howells
2015-10-21 14:27 ` David Howells [this message]
2015-10-21 14:27 ` [PATCH 5/6] KEYS: Provide a script to extract a module signature David Howells
2015-10-21 14:27 ` [PATCH 6/6] KEYS: Merge the type-specific data with the payload data David Howells
2015-10-21 14:29 ` [PATCH 1/6] KEYS: use kvfree() in add_key David Howells

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20151021142714.31251.49687.stgit@warthog.procyon.org.uk \
    --to=dhowells@redhat.com \
    --cc=keyrings@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®