All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Howells <dhowells@redhat.com>
To: "Rusty Russell (IBM)" <rusty@au1.ibm.com>
Cc: David Woodhouse <dwmw2@infradead.org>,
	rusty@ozlabs.au.ibm.com, 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: Wed, 13 Oct 2004 10:24:46 +0100	[thread overview]
Message-ID: <24261.1097659486@redhat.com> (raw)
In-Reply-To: <1097626296.4013.34.camel@localhost.localdomain>


> Let me make this clear: I refuse to include any solution which doesn't
> protect against accidental, as well as deliberate, corruption.  This
> means your "canonicalization" code has to be very, very paranoid about
> not trusting the data until the signature is verified.  The current code
> does very simple checks then completely trusts the module contents,
> especially the section headers: to make signatures worth anything, your
> code must not do this.

I agree that checks should be made on ELF before signature checking is
performed, but I was trying to develop it one step at a time. However, since
you asked so nicely, I've added the attached to my implementation.

David

---

struct module_verify_data {
	struct crypto_tfm	*sha1_tfm;
	const void		*buffer;
	const Elf_Ehdr		*hdr;
	const Elf_Shdr		*sections;
	const Elf_Sym		*symbols;
	const char		*secstrings;
	const char		*strings;
	size_t			*secsizes;
	size_t			size;
	size_t			nsects;
	size_t			nsyms;
	size_t			nstrings;
	size_t			signed_size;
	int			*canonlist;
	int			*canonmap;
	int			sig_index;
	uint8_t			csum;
};

/*****************************************************************************/
/*
 * 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);

	/* 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));

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

	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);

		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);
		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) < mvdata->nsyms);
			}

			break;

		case SHT_RELA:
			relas = mvdata->buffer + section->sh_offset;
			relastop = mvdata->buffer + section->sh_offset + section->sh_size;

			for (rela = relas; rela < relastop; rela++) {
				relacheck(rela->r_offset < section2->sh_size);
				relacheck(ELF_R_SYM(rela->r_info) < mvdata->nsyms);
			}

			break;

		default:
			break;
		}
	}


	_debug("ELF okay\n");
	return 0;

 elfcheck_error:
	printk("Verify ELF error (assertion %d)\n", line);
	goto format_error;

 seccheck_error:
	printk("Verify ELF error [sec %ld] (assertion %d)\n",
	       section - mvdata->sections, line);
	goto format_error;

 symcheck_error:
	printk("Verify ELF error [sym %ld] (assertion %d)\n",
	       symbol - mvdata->symbols, line);
	goto format_error;

 relcheck_error:
	printk("Verify ELF error [sec %ld rel %ld] (assertion %d)\n",
	       section - mvdata->sections, rel - rels, line);
	goto format_error;

 relacheck_error:
	printk("Verify ELF error [sec %ld rela %ld] (assertion %d)\n",
	       section - mvdata->sections, rela - relas, line);
	goto format_error;

 format_error:
	return -ELIBBAD;

} /* end module_verify_elf() */

  parent reply	other threads:[~2004-10-13  9:25 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 [this message]
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
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=24261.1097659486@redhat.com \
    --to=dhowells@redhat.com \
    --cc=arjanv@redhat.com \
    --cc=dwmw2@infradead.org \
    --cc=greg@kroah.com \
    --cc=latten@us.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=rusty@au1.ibm.com \
    --cc=rusty@ozlabs.au.ibm.com \
    /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.