Upload
vancong
View
217
Download
0
Embed Size (px)
Citation preview
.init.whoami!● I'm not a Linux developer● I'm not a historian● But I know my way around code repositories and mailing
list archives
● And I am an ELF metadata wizard
Image: Tess27 on deviantart.com
Obligatory code signing slide
Images: Stick figures xkcd. Matrix Jamie Zawinski→ →
Without code signing With code signing
hash filedigitally sign hash
Code signing: it's not just an algorithm,
it's a lifestyle.
But I'm just focusing and a few tiny aspects of code signing...
A focus on ELF metadata
● How/where is signature stored● What is signed● What is not signed● How signature is interpreted● How signature may be misinterpreted
– Parser differentials*● Highlighting the evolution b/c other implementations probably made
similar mistakes
Image photoshopped by Kythera of Anevern
The remainder of this talk
● ELF metadata overview● The evolution of Linux module signing
– With commentary on implementations
● What different distributions use● Critique, etc
More than one way to skin an ELF
Image: Surueña CC BYSA 3.0
Static linking view
Load/runtime view
* Note: Linux module loader (in kernel) loads directly from the section headers
How module signing evolved
2011: v2
2007: v1
2004: v0
2012: v32012: Linux 3.7
Used in Fedora/Redhat variants
2012: Linux 3.72012: Linux 3.7
Back in 2004 (v0)
● Greg KroahHarman wrote a patch– Because other kernels sign their modules
● Linux 2.5– Module loading logic moved to kernel
● Edited by David Howells (Redhat)
Module signing v0● Signature stored in ELF section
● Contents of .text and .data are hashed
'Signed Kernel Modules' Linux Journal
for (i = 1; i < hdr->e_shnum; i++) if (strcmp(secstrings+sechdrs[i].sh_name, "module_sig") == 0) { sig_index = i; break;}
for (i = 1; i < hdr->e_shnum; i++) { name = secstrings+sechdrs[i].sh_name; // We only care about sections with "text" or "data" in their names if ((strstr(name, "text")==NULL) && (strstr(name, "data") == NULL)) continue; // avoid the ".rel.*" sections too. if (strstr(name, ".rel.") != NULL) continue;
// (add contents of section to signature)
...}
2007: v1● Patch by David Howells● Appears in Fedora/RedHat
// verify a module's integrity // - check the ELF is viable // - check the module's signature if it has oneint module_verify(const Elf_Ehdr *hdr, size_t size) {
struct module_verify_data mvdata;int ret;...ret = module_verify_elf(&mvdata);if (ret < 0) goto error;ret = module_verify_signature(&mvdata);
error:return ret;
}
Module signing v1● In module_verify_signature {}
● Signature still in ELF section
● More metadata is hashed! (headers and more sections)/* load data from each relevant section into the digest */for (i = 1; i < mvdata->nsects; i++) {
...if (i == mvdata->sig_index) // Do not sign signature
continue; /* it would be nice to include relocation sections, but the act of adding a signature to the module seems changes their contents, because the symtab gets changed when sections are added or removed */if (sh_type == SHT_REL || sh_type == SHT_RELA) {
// add relocation header information to hash// add individual relocation entries and symbols they use to hash...continue;
}// hash allocatable loadable sectionsif (sh_type != SHT_NOBITS && sh_flags & SHF_ALLOC)
goto include_section;continue;
include_section:// add section header and section data to signature...
}
2011: v2● 2011, David Howells● Appears in RHEL 6● Now with more indirection!● Signature stored in note section (SHT_NOTE)
Image from docs.oracle.com
module.sig
100
signature
2011: v2
● Slightly more metadata is hashed– BSS headers (loaded “empty” sections)
/* include the headers of BSS sections */if (sh_type == SHT_NOBITS && sh_flags & SHF_ALLOC) { // add header metadata to hash
… goto digested;
}
2012: Linux 3.7/v3
● Decided it was best to hash entire module– Signature should not be in ELF metadata
● 2 suggested implementations– Store signature in xattrs
● Integrity Measurement Architecture did this (generically) since 2010 (Dmitry Kasatkin)
– Append signature to end of ELF ● v3 implemented by David Howells● Redhat/Fedora had to rework build/distribution process to allow for this
● Linux 3.7 incorporated Howell's v3 implementation
Linux 3.7 module signing
● Check for signature at end of file#define MODULE_SIG_STRING "~Module signature appended~\n"const unsigned long markerlen = sizeof(MODULE_SIG_STRING) 1;const void *mod = info>hdr;
if (info>len > markerlen && memcmp(mod + info>len markerlen, MODULE_SIG_STRING, markerlen) == 0) {
/* We truncate the module to discard the signature */info>len = markerlen;err = mod_verify_sig(mod, &info>len);
}
Linux 3.7 module signing● Hash all the things! (but the signature)/* Verify the signature on a module. */int mod_verify_sig(const void *mod, unsigned long *_modlen) {
// sanity checks...// copy bytes at end of file into signature structurememcpy(&ms, mod + (modlen sizeof(ms)), sizeof(ms));// do work to calculate length of module (modlen)...sig = mod + modlen;// add all module contents (but signature) to signaturepks = mod_make_digest(ms.hash, mod, modlen);if (IS_ERR(pks)) {
ret = PTR_ERR(pks); goto error;}...ret = verify_signature(key, pks);
error:return ret;
}
Who uses what
● Redhat/Fedora/CentOS/Oracle use v12 and mainline implementation
● Gentoo/OpenSUSE use mainline version● (list is incomplete)
Critiques, etc
● Why aren't all the metadata signed?– See: ELF Eccentricities, CONFidence 2013
● When stored in ELF section, how do we know all parsers use same section?– Remember Android "Master Key" bug?
● How do we know our shotgun sanity checks will fully protect us?
● ...Appending signature to end seems to help