All of lore.kernel.org
 help / color / mirror / Atom feed
From: Rusty Russell <rusty@rustcorp.com.au>
To: David Howells <dhowells@redhat.com>
Cc: David Woodhouse <dwmw2@infradead.org>, Greg KH <greg@kroah.com>,
	Arjan van de Ven <arjanv@redhat.com>,
	Joy Latten <latten@us.ibm.com>,
	lkml - Kernel Mailing List <linux-kernel@vger.kernel.org>
Subject: Re: Fw: signed kernel modules?
Date: Thu, 14 Oct 2004 09:01:21 +1000	[thread overview]
Message-ID: <1097707986.14303.36.camel@localhost.localdomain> (raw)
In-Reply-To: <27277.1097702318@redhat.com>

On Thu, 2004-10-14 at 07:18, David Howells wrote:
> > Write the code.  Then come back and tell me it "isn't that hard".
> 
> It isn't that hard.

I see.  Well, the good news is that I think your canonicalization step
now covers all the exploits I can think of.

@@ -1536,8 +1538,59 @@ static struct module *load_module(void _
 		goto free_hdr;
 	}
 
-	if (len < hdr->e_shoff + hdr->e_shnum * sizeof(Elf_Shdr))
-		goto truncated;
+	/* verify the module (validates ELF and checks signature) */
+	gpgsig_ok = 0;
+	err = module_verify(hdr, len);
+	if (err < 0)
+		goto free_hdr;
+	if (err == 1)
+		gpgsig_ok = 1;
 
 	/* Convenience variables */
 	sechdrs = (void *)hdr + hdr->e_shoff;

I'd prefer to see:
	err = module_verify(hdr, len, &gpgsig_ok);
	if (err)
		goto free_hdr;

And then have module_verify for the !CONFIG_MODULE_SIG case (in
module-verify.h) simply be:

	if (len < hdr->e_shoff + hdr->e_shnum * sizeof(Elf_Shdr))
		return -EINVAL;
	*gpgsig_ok = 1;

+/*****************************************************************************/
+/*
+ * verify the ELF structure of a module
+ */
+static int module_verify_elf(struct module_verify_data *mvdata)
+{
+	const Elf_Ehdr *hdr = mvdata->hdr;
+	const Elf_Shdr *section, *section2, *secstop;
+	const Elf_Rela *relas, *rela, *relastop;
+	const Elf_Rel *rels, *rel, *relstop;
+	const Elf_Sym *symbol, *symstop;
+	size_t size, sssize, *secsize, tmp, tmp2;
+	int line;
+
+	size = mvdata->size;
+	mvdata->nsects = hdr->e_shnum;
+
+#define elfcheck(X) \
+do { if (unlikely(!(X))) { line = __LINE__; goto elfcheck_error; } } while(0)
+
+#define seccheck(X) \
+do { if (unlikely(!(X))) { line = __LINE__; goto seccheck_error; } } while(0)
+
+#define symcheck(X) \
+do { if (unlikely(!(X))) { line = __LINE__; goto symcheck_error; } } while(0)
+
+#define relcheck(X) \
+do { if (unlikely(!(X))) { line = __LINE__; goto relcheck_error; } } while(0)
+
+#define relacheck(X) \
+do { if (unlikely(!(X))) { line = __LINE__; goto relacheck_error; } } while(0)
+
+	/* validate the ELF header */
+	elfcheck(hdr->e_ehsize < size);
+	elfcheck(hdr->e_entry == 0);
+	elfcheck(hdr->e_phoff == 0);
+	elfcheck(hdr->e_phnum == 0);
+
+	elfcheck(hdr->e_shoff < size);
+	elfcheck(hdr->e_shoff >= hdr->e_ehsize);
+	elfcheck((hdr->e_shoff & (sizeof(long) - 1)) == 0);
+	elfcheck(hdr->e_shstrndx > 0);
+	elfcheck(hdr->e_shstrndx < hdr->e_shnum);
+
+	tmp = (size_t) hdr->e_shentsize * (size_t) hdr->e_shnum;
+	elfcheck(tmp < size - hdr->e_shoff);

Multiplicative overflow.  Also check that hdr->e_shentsize is
sizeof(Elf_Shdr) since you assume that below.

+	/* allocate a table to hold in-file section sizes */
+	mvdata->secsizes = kmalloc(hdr->e_shnum * sizeof(size_t), GFP_KERNEL);
+	if (!mvdata->secsizes)
+		return -ENOMEM;
+	memset(mvdata->secsizes, 0, hdr->e_shnum * sizeof(size_t));

Multiplicative overflow again: we could kmalloc 0 bytes and overflow below.

+	/* validate the ELF section headers */
+	mvdata->sections = mvdata->buffer + hdr->e_shoff;
+	secstop = mvdata->sections + mvdata->nsects;

Subtler multiplicative overflow.

+	sssize = mvdata->sections[hdr->e_shstrndx].sh_size;
+	elfcheck(sssize > 0);
+
+	section = mvdata->sections;
+	seccheck(section->sh_type == SHT_NULL);
+	seccheck(section->sh_size == 0);
+	seccheck(section->sh_offset == 0);
+
+	secsize = mvdata->secsizes + 1;
+	for (section++; section < secstop; secsize++, section++) {
+		seccheck(section->sh_name < sssize);
+		seccheck(section->sh_addr == 0);
+		seccheck(section->sh_link < hdr->e_shnum);
+
+		if (section->sh_entsize > 0)
+			seccheck(section->sh_size % section->sh_entsize == 0);

Divide by zero (thanks Alan!).

+		seccheck(section->sh_offset >= hdr->e_ehsize);
+		seccheck(section->sh_offset < size);
+
+		/* determine the section's in-file size */
+		tmp = size - section->sh_offset;
+		if (section->sh_offset < hdr->e_shoff)
+			tmp = hdr->e_shoff - section->sh_offset;
+
+		for (section2 = mvdata->sections + 1; section2 < secstop; section2++) {
+			if (section->sh_offset < section2->sh_offset) {
+				tmp2 = section2->sh_offset - section->sh_offset;
+				if (tmp2 < tmp)
+					tmp = tmp2;
+			}
+		}
+		*secsize = tmp;
+
+		_debug("Section %ld: %zx bytes at %lx\n",
+		       section - mvdata->sections,
+		       *secsize,
+		       section->sh_offset);
+
+		/* perform section type specific checks */
+		switch (section->sh_type) {
+		case SHT_NOBITS:
+			break;
+
+		case SHT_REL:
+		case SHT_RELA:
+			seccheck(section->sh_info > 0);
+			seccheck(section->sh_info < hdr->e_shnum);
+			/* fall through */
+
+		default:
+			/* most types of section must be contained entirely
+			 * within the file */
+			seccheck(section->sh_size <= *secsize);
+			break;
+		}
+	}
+
+	/* validate the ELF section names */
+	section = &mvdata->sections[hdr->e_shstrndx];
+
+	seccheck(section->sh_offset != hdr->e_shoff);
+
+	mvdata->secstrings = mvdata->buffer + section->sh_offset;
+
+	for (section = mvdata->sections + 1; section < secstop; section++) {
+		const char *secname;
+		tmp = sssize - section->sh_name;
+		secname = mvdata->secstrings + section->sh_name;
+		seccheck(secname[0] != 0);
+		seccheck(memchr(secname, 0, tmp) != NULL);
+	}
+
+	/* look for various sections in the module */
+	for (section = mvdata->sections + 1; section < secstop; section++) {
+		switch (section->sh_type) {
+		case SHT_SYMTAB:
+			if (strcmp(mvdata->secstrings + section->sh_name,
+				   ".symtab") == 0
+			    ) {
+				seccheck(mvdata->symbols == NULL);
+				mvdata->symbols =
+					mvdata->buffer + section->sh_offset;
+				mvdata->nsyms =
+					section->sh_size / sizeof(Elf_Sym);
+				seccheck(section->sh_size > 0);
+			}
+			break;
+
+		case SHT_STRTAB:
+			if (strcmp(mvdata->secstrings + section->sh_name,
+				   ".strtab") == 0
+			    ) {
+				seccheck(mvdata->strings == NULL);
+				mvdata->strings =
+					mvdata->buffer + section->sh_offset;
+				sssize = mvdata->nstrings = section->sh_size;
+				seccheck(section->sh_size > 0);
+			}
+			break;
+		}
+	}
+
+	if (!mvdata->symbols) {
+		printk("Couldn't locate module symbol table\n");
+		goto format_error;
+	}
+
+	if (!mvdata->strings) {
+		printk("Couldn't locate module strings table\n");
+		goto format_error;
+	}
+
+	/* validate the symbol table */
+	symstop = mvdata->symbols + mvdata->nsyms;
+
+	symbol = mvdata->symbols;
+	symcheck(ELF_ST_TYPE(symbol[0].st_info) == STT_NOTYPE);
+	symcheck(symbol[0].st_shndx == SHN_UNDEF);
+	symcheck(symbol[0].st_value == 0);
+	symcheck(symbol[0].st_size == 0);
+
+	for (symbol++; symbol < symstop; symbol++) {
+		symcheck(symbol->st_name < sssize);

I think you have to check (as above) that st_name is nul terminated
within size.

+		symcheck(symbol->st_shndx < mvdata->nsects ||
+			 symbol->st_shndx >= SHN_LORESERVE);
+	}
+
+	/* validate each relocation table as best we can */
+	for (section = mvdata->sections + 1; section < secstop; section++) {
+		section2 = mvdata->sections + section->sh_info;
+
+		switch (section->sh_type) {
+		case SHT_REL:
+			rels = mvdata->buffer + section->sh_offset;
+			relstop = mvdata->buffer + section->sh_offset + section->sh_size;
+
+			for (rel = rels; rel < relstop; rel++) {
+				relcheck(rel->r_offset < section2->sh_size);
+				relcheck(ELF_R_SYM(rel->r_info) > 0);
+				relcheck(ELF_R_SYM(rel->r_info) < mvdata->nsyms);

I think you can overflow here.  For REL and RELA sections, you don't
check that sh_size is <= *secsize.

That's all I found,
Rusty.
-- 
Anyone who quotes me in their signature is an idiot -- Rusty Russell


  parent reply	other threads:[~2004-10-13 23:01 UTC|newest]

Thread overview: 85+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <1096411448.3230.22.camel@localhost.localdomain>
     [not found] ` <1092403984.29463.11.camel@bach>
     [not found]   ` <1092369784.25194.225.camel@bach>
     [not found]     ` <20040812092029.GA30255@devserv.devel.redhat.com>
     [not found]       ` <20040811211719.GD21894@kroah.com>
     [not found]         ` <OF4B7132F5.8BE9D947-ON87256EEB.007192D0-86256EEB.00740B23@us.ibm.com>
     [not found]           ` <1092097278.20335.51.camel@bach>
     [not found]             ` <20040810002741.GA7764@kroah.com>
     [not found]               ` <1092189167.22236.67.camel@bach>
     [not found]                 ` <19388.1092301990@redhat.com>
     [not found]                   ` <30797.1092308768@redhat.com>
     [not found]                     ` <20040812111853.GB25950@devserv.devel.redhat.com>
     [not found]                       ` <20040812200917.GD2952@kroah.com>
     [not found]                         ` <26280.1092388799@redhat.com>
     [not found]                           ` <27175.1095936746@redhat.com>
     [not found]                             ` <30591.1096451074@redhat.com>
     [not found]                               ` <1096544201.8043.816.camel@localhost.localdomain>
2004-10-11 15:11                                 ` Fw: signed kernel modules? David Howells
2004-10-11 15:15                                   ` David Woodhouse
2004-10-11 22:34                                     ` Rusty Russell (IBM)
2004-10-12  8:35                                       ` David Woodhouse
2004-10-12 19:08                                         ` Greg KH
2004-10-12 19:16                                           ` David Howells
2004-10-12 20:43                                           ` David Howells
2004-10-13  0:20                                           ` Rusty Russell (IBM)
2004-10-13  8:24                                             ` David Woodhouse
2004-10-13  0:11                                         ` Rusty Russell (IBM)
2004-10-13  9:16                                           ` David Woodhouse
2004-10-13 21:21                                             ` Rusty Russell (IBM)
2004-10-13  9:24                                           ` David Howells
2004-10-13 10:42                                           ` Alan Cox
2004-10-13 22:40                                             ` Rusty Russell (IBM)
2004-10-14 10:17                                               ` David Howells
2004-10-15  0:28                                                 ` Rusty Russell (IBM)
2004-10-14 23:44                                               ` Alan Cox
2004-10-15  1:00                                                 ` Rusty Russell (IBM)
2004-10-13 21:18                                           ` David Howells
2004-10-13 21:51                                             ` Roman Zippel
2004-10-14 11:12                                               ` David Howells
2004-10-14 12:01                                                 ` Roman Zippel
2004-10-14 12:11                                                   ` David Woodhouse
2004-10-14 14:22                                                     ` Roman Zippel
2004-10-14 14:30                                                       ` David Woodhouse
2004-10-14 21:03                                                         ` Roman Zippel
2004-10-14 21:24                                                           ` David Woodhouse
2004-10-14 21:36                                                             ` Roman Zippel
2004-10-14 21:52                                                               ` David Woodhouse
2004-10-14 22:15                                                                 ` Roman Zippel
2004-10-14 22:32                                                                   ` David Howells
2004-10-14 22:38                                                                     ` Roman Zippel
2004-10-14 12:14                                                   ` David Howells
2004-10-14 13:08                                                     ` Richard B. Johnson
2004-10-14 14:18                                                       ` Geert Uytterhoeven
2004-10-14 14:25                                                         ` Richard B. Johnson
2004-10-14 15:40                                                           ` Richard B. Johnson
2004-10-14 15:50                                                             ` Dave Jones
     [not found]                                                               ` <Pine.LNX.4.61.0410141352590.8479@chaos.analogic.com>
2004-10-14 18:20                                                                 ` Dave Jones
2004-10-14 18:30                                                                   ` Richard B. Johnson
2004-10-14 18:46                                                                     ` Dave Jones
2004-10-14 19:03                                                                       ` Richard B. Johnson
2004-10-14 19:41                                                                         ` Geert Uytterhoeven
2004-10-14 21:13                                                                         ` Dave Jones
2004-10-18  1:56                                                       ` Jon Masters
2004-10-13 23:01                                             ` Rusty Russell [this message]
2004-10-14 11:02                                               ` David Howells
2004-10-15  0:47                                                 ` Rusty Russell
2004-10-14 18:09                                             ` David Howells
2004-10-15 11:12                                               ` Roman Zippel
2004-10-15 12:10                                                 ` Richard B. Johnson
2004-10-15 12:31                                                   ` Josh Boyer
2004-10-15 15:53                                                     ` Gene Heskett
2004-10-15 16:17                                                       ` Josh Boyer
2004-10-15 16:59                                                         ` Richard B. Johnson
2004-10-15 17:08                                                           ` David Woodhouse
2004-10-15 17:35                                                             ` Richard B. Johnson
2004-10-15 20:56                                                               ` Lee Revell
2004-10-15 21:18                                                                 ` Greg KH
2004-10-15 21:34                                                                   ` Chris Friesen
2004-10-15 22:08                                                                     ` Richard B. Johnson
2004-10-18 12:53                                                                       ` Richard B. Johnson
2004-10-18 13:53                                                                         ` Matthew Garrett
2004-10-18 14:09                                                                           ` Richard B. Johnson
2004-10-18 16:33                                                                         ` Greg KH
2004-10-18 17:14                                                                           ` Richard B. Johnson
2004-10-18 17:28                                                                             ` Richard B. Johnson
2004-10-15 17:46                                                           ` Josh Boyer
2004-10-15 20:11                                                             ` Tonnerre
2004-10-17 20:18                                                               ` Thomas Weber
2004-10-17 20:52                                                                 ` Geert Uytterhoeven
2004-10-17 21:25                                                                   ` Thomas Weber
2004-10-15 12:48                                                   ` Roman Zippel
2004-10-15 15:51                                                   ` Gene Heskett
2004-10-15 14:01                                                 ` David Woodhouse
2004-10-15 14:28                                                   ` Roman Zippel
2004-10-15 15:54                                                   ` Gene Heskett
2004-10-15 16:33                                                     ` Arjan van de Ven
2004-10-14 18:44                                   ` Thomas Weber
2004-10-15 15:37 Chuck Ebbert
2004-10-15 16:05 ` Olivier Galibert
     [not found] <fa.ghoqtmo.8nqeb0@ifi.uio.no>
     [not found] ` <fa.jtpibm5.1l4ki17@ifi.uio.no>
2004-10-17 15:13   ` Bodo Eggert
2004-10-18 11:27     ` Richard B. Johnson
2004-10-23 10:19       ` Bodo Eggert

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=1097707986.14303.36.camel@localhost.localdomain \
    --to=rusty@rustcorp.com.au \
    --cc=arjanv@redhat.com \
    --cc=dhowells@redhat.com \
    --cc=dwmw2@infradead.org \
    --cc=greg@kroah.com \
    --cc=latten@us.ibm.com \
    --cc=linux-kernel@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.