[PATCH v4 2/4] KEYS: Add ELF class-independent certificate insertion support
Use ELF class-independent GElf API for processing the kernel binary. This patch adds support for compiling the script for 64-bit and the kernel for 32-bit (e.g. make ARCH=i386 on x86-64). Signed-off-by: Mehmet Kayaalp--- scripts/Makefile | 1 + scripts/insert-sys-cert.c | 215 +++--- 2 files changed, 109 insertions(+), 107 deletions(-) diff --git a/scripts/Makefile b/scripts/Makefile index 1d80897..5633f2c 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -25,6 +25,7 @@ HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include HOSTLOADLIBES_sign-file = -lcrypto HOSTLOADLIBES_extract-cert = -lcrypto +HOSTLOADLIBES_insert-sys-cert = -lelf always := $(hostprogs-y) $(hostprogs-m) diff --git a/scripts/insert-sys-cert.c b/scripts/insert-sys-cert.c index 8902836..86a3d41 100644 --- a/scripts/insert-sys-cert.c +++ b/scripts/insert-sys-cert.c @@ -24,7 +24,8 @@ #include #include #include -#include +#include +#include #define CERT_SYM "system_extra_cert" #define USED_SYM "system_extra_cert_used" @@ -34,18 +35,6 @@ #define warn(format, args...) fprintf(stdout, "WARNING: " format, ## args) #define err(format, args...) fprintf(stderr, "ERROR: " format, ## args) -#if UINTPTR_MAX == 0x -#define CURRENT_ELFCLASS ELFCLASS32 -#define Elf_Ehdr Elf32_Ehdr -#define Elf_Shdr Elf32_Shdr -#define Elf_SymElf32_Sym -#else -#define CURRENT_ELFCLASS ELFCLASS64 -#define Elf_Ehdr Elf64_Ehdr -#define Elf_Shdr Elf64_Shdr -#define Elf_SymElf64_Sym -#endif - static unsigned char endianness(void) { uint16_t two_byte = 0x00FF; @@ -65,22 +54,17 @@ struct sym { int size; }; -static unsigned long get_offset_from_address(Elf_Ehdr *hdr, unsigned long addr) +static unsigned long get_offset_from_address(Elf *elf, unsigned long addr) { - Elf_Shdr *x; - unsigned int i, num_sections; - - x = (void *)hdr + hdr->e_shoff; - if (hdr->e_shnum == SHN_UNDEF) - num_sections = x[0].sh_size; - else - num_sections = hdr->e_shnum; - - for (i = 1; i < num_sections; i++) { - unsigned long start = x[i].sh_addr; - unsigned long end = start + x[i].sh_size; - unsigned long offset = x[i].sh_offset; - + Elf_Scn *scn = NULL; + GElf_Shdr shdr; + unsigned long start, end, offset; + + while ((scn = elf_nextscn(elf, scn)) != NULL) { + gelf_getshdr(scn, ); + start = shdr.sh_addr; + end = start + shdr.sh_size; + offset = shdr.sh_offset; if (addr >= start && addr <= end) return addr - start + offset; } @@ -90,7 +74,7 @@ static unsigned long get_offset_from_address(Elf_Ehdr *hdr, unsigned long addr) #define LINE_SIZE 100 -static void get_symbol_from_map(Elf_Ehdr *hdr, FILE *f, char *name, +static void get_symbol_from_map(Elf *elf, void *base, FILE *f, char *name, struct sym *s) { char l[LINE_SIZE]; @@ -125,76 +109,65 @@ static void get_symbol_from_map(Elf_Ehdr *hdr, FILE *f, char *name, s->address = strtoul(l, NULL, 16); if (s->address == 0) return; - s->offset = get_offset_from_address(hdr, s->address); + s->offset = get_offset_from_address(elf, s->address); s->name = name; - s->content = (void *)hdr + s->offset; -} - -static Elf_Sym *find_elf_symbol(Elf_Ehdr *hdr, Elf_Shdr *symtab, char *name) -{ - Elf_Sym *sym, *symtab_start; - char *strtab, *symname; - unsigned int link; - Elf_Shdr *x; - int i, n; - - x = (void *)hdr + hdr->e_shoff; - link = symtab->sh_link; - symtab_start = (void *)hdr + symtab->sh_offset; - n = symtab->sh_size / symtab->sh_entsize; - strtab = (void *)hdr + x[link].sh_offset; - - for (i = 0; i < n; i++) { - sym = _start[i]; - symname = strtab + sym->st_name; - if (strcmp(symname, name) == 0) - return sym; - } - err("Unable to find symbol: %s\n", name); - return NULL; + s->content = (void *)base + s->offset; } -static void get_symbol_from_table(Elf_Ehdr *hdr, Elf_Shdr *symtab, +static void get_symbol_from_table(Elf *elf, Elf_Scn *symtab, void *base, char *name, struct sym *s) { - Elf_Shdr *sec; - int secndx; - Elf_Sym *elf_sym; - Elf_Shdr *x; + GElf_Shdr shdr; + Elf_Data *data; + int count; + int i; + GElf_Sym sym; + char *symname; + int found = 0; + size_t secndx; + Elf_Scn *sec; + + gelf_getshdr(symtab, ); + data = elf_getdata(symtab, NULL); + count = shdr.sh_size / shdr.sh_entsize; +
[PATCH v4 2/4] KEYS: Add ELF class-independent certificate insertion support
Use ELF class-independent GElf API for processing the kernel binary. This patch adds support for compiling the script for 64-bit and the kernel for 32-bit (e.g. make ARCH=i386 on x86-64). Signed-off-by: Mehmet Kayaalp --- scripts/Makefile | 1 + scripts/insert-sys-cert.c | 215 +++--- 2 files changed, 109 insertions(+), 107 deletions(-) diff --git a/scripts/Makefile b/scripts/Makefile index 1d80897..5633f2c 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -25,6 +25,7 @@ HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include HOSTLOADLIBES_sign-file = -lcrypto HOSTLOADLIBES_extract-cert = -lcrypto +HOSTLOADLIBES_insert-sys-cert = -lelf always := $(hostprogs-y) $(hostprogs-m) diff --git a/scripts/insert-sys-cert.c b/scripts/insert-sys-cert.c index 8902836..86a3d41 100644 --- a/scripts/insert-sys-cert.c +++ b/scripts/insert-sys-cert.c @@ -24,7 +24,8 @@ #include #include #include -#include +#include +#include #define CERT_SYM "system_extra_cert" #define USED_SYM "system_extra_cert_used" @@ -34,18 +35,6 @@ #define warn(format, args...) fprintf(stdout, "WARNING: " format, ## args) #define err(format, args...) fprintf(stderr, "ERROR: " format, ## args) -#if UINTPTR_MAX == 0x -#define CURRENT_ELFCLASS ELFCLASS32 -#define Elf_Ehdr Elf32_Ehdr -#define Elf_Shdr Elf32_Shdr -#define Elf_SymElf32_Sym -#else -#define CURRENT_ELFCLASS ELFCLASS64 -#define Elf_Ehdr Elf64_Ehdr -#define Elf_Shdr Elf64_Shdr -#define Elf_SymElf64_Sym -#endif - static unsigned char endianness(void) { uint16_t two_byte = 0x00FF; @@ -65,22 +54,17 @@ struct sym { int size; }; -static unsigned long get_offset_from_address(Elf_Ehdr *hdr, unsigned long addr) +static unsigned long get_offset_from_address(Elf *elf, unsigned long addr) { - Elf_Shdr *x; - unsigned int i, num_sections; - - x = (void *)hdr + hdr->e_shoff; - if (hdr->e_shnum == SHN_UNDEF) - num_sections = x[0].sh_size; - else - num_sections = hdr->e_shnum; - - for (i = 1; i < num_sections; i++) { - unsigned long start = x[i].sh_addr; - unsigned long end = start + x[i].sh_size; - unsigned long offset = x[i].sh_offset; - + Elf_Scn *scn = NULL; + GElf_Shdr shdr; + unsigned long start, end, offset; + + while ((scn = elf_nextscn(elf, scn)) != NULL) { + gelf_getshdr(scn, ); + start = shdr.sh_addr; + end = start + shdr.sh_size; + offset = shdr.sh_offset; if (addr >= start && addr <= end) return addr - start + offset; } @@ -90,7 +74,7 @@ static unsigned long get_offset_from_address(Elf_Ehdr *hdr, unsigned long addr) #define LINE_SIZE 100 -static void get_symbol_from_map(Elf_Ehdr *hdr, FILE *f, char *name, +static void get_symbol_from_map(Elf *elf, void *base, FILE *f, char *name, struct sym *s) { char l[LINE_SIZE]; @@ -125,76 +109,65 @@ static void get_symbol_from_map(Elf_Ehdr *hdr, FILE *f, char *name, s->address = strtoul(l, NULL, 16); if (s->address == 0) return; - s->offset = get_offset_from_address(hdr, s->address); + s->offset = get_offset_from_address(elf, s->address); s->name = name; - s->content = (void *)hdr + s->offset; -} - -static Elf_Sym *find_elf_symbol(Elf_Ehdr *hdr, Elf_Shdr *symtab, char *name) -{ - Elf_Sym *sym, *symtab_start; - char *strtab, *symname; - unsigned int link; - Elf_Shdr *x; - int i, n; - - x = (void *)hdr + hdr->e_shoff; - link = symtab->sh_link; - symtab_start = (void *)hdr + symtab->sh_offset; - n = symtab->sh_size / symtab->sh_entsize; - strtab = (void *)hdr + x[link].sh_offset; - - for (i = 0; i < n; i++) { - sym = _start[i]; - symname = strtab + sym->st_name; - if (strcmp(symname, name) == 0) - return sym; - } - err("Unable to find symbol: %s\n", name); - return NULL; + s->content = (void *)base + s->offset; } -static void get_symbol_from_table(Elf_Ehdr *hdr, Elf_Shdr *symtab, +static void get_symbol_from_table(Elf *elf, Elf_Scn *symtab, void *base, char *name, struct sym *s) { - Elf_Shdr *sec; - int secndx; - Elf_Sym *elf_sym; - Elf_Shdr *x; + GElf_Shdr shdr; + Elf_Data *data; + int count; + int i; + GElf_Sym sym; + char *symname; + int found = 0; + size_t secndx; + Elf_Scn *sec; + + gelf_getshdr(symtab, ); + data = elf_getdata(symtab, NULL); + count = shdr.sh_size / shdr.sh_entsize; + + for (i = 0; i <