Message ID | 20200915112842.897265-19-jarkko.sakkinen@linux.intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Intel SGX foundations | expand |
On Tue, Sep 15, 2020 at 02:28:36PM +0300, Jarkko Sakkinen wrote: > From: Sean Christopherson <sean.j.christopherson@intel.com> > > The basic concept and implementation is very similar to the kernel's > exception fixup mechanism. The key differences are that the kernel > handler is hardcoded and the fixup entry addresses are relative to > the overall table as opposed to individual entries. ... This gist of this commit message should be also in Documentation/x86/sgx.rst And I already said the same thing during v33 review: "That is a very good explanation and I would prefer if it would be in a sgx-specific README or so instead of it getting lost in git..." ... > diff --git a/arch/x86/entry/vdso/extable.h b/arch/x86/entry/vdso/extable.h > new file mode 100644 > index 000000000000..aafdac396948 > --- /dev/null > +++ b/arch/x86/entry/vdso/extable.h > @@ -0,0 +1,29 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +#ifndef __VDSO_EXTABLE_H > +#define __VDSO_EXTABLE_H > + > +/* > + * Inject exception fixup for vDSO code. Unlike normal exception fixup, > + * vDSO uses a dedicated handler the addresses are relative to the overall > + * exception table, not each individual entry. > + */ > +#ifdef __ASSEMBLY__ > +#define _ASM_VDSO_EXTABLE_HANDLE(from, to) \ > + ASM_VDSO_EXTABLE_HANDLE from to > + > +.macro ASM_VDSO_EXTABLE_HANDLE from:req to:req > + .pushsection __ex_table, "a" > + .long (\from) - __ex_table > + .long (\to) - __ex_table > + .popsection > +.endm > +#else > +#define _ASM_VDSO_EXTABLE_HANDLE(from, to) \ > + ".pushsection __ex_table, \"a\"\n" \ > + ".long (" #from ") - __ex_table\n" \ > + ".long (" #to ") - __ex_table\n" \ > + ".popsection\n" > +#endif > + > +#endif /* __VDSO_EXTABLE_H */ > + Also from last time: .git/rebase-apply/patch:122: new blank line at EOF. +
On Thu, Sep 24, 2020 at 12:07:12AM +0200, Borislav Petkov wrote: > On Tue, Sep 15, 2020 at 02:28:36PM +0300, Jarkko Sakkinen wrote: > > From: Sean Christopherson <sean.j.christopherson@intel.com> > > > > The basic concept and implementation is very similar to the kernel's > > exception fixup mechanism. The key differences are that the kernel > > handler is hardcoded and the fixup entry addresses are relative to > > the overall table as opposed to individual entries. > > ... > > This gist of this commit message should be also in > Documentation/x86/sgx.rst > > And I already said the same thing during v33 review: > > "That is a very good explanation and I would prefer if it would be in a > sgx-specific README or so instead of it getting lost in git..." > > ... This is not technically SGX specific patch. Is SGX documentation the correct place for this? > > diff --git a/arch/x86/entry/vdso/extable.h b/arch/x86/entry/vdso/extable.h > > new file mode 100644 > > index 000000000000..aafdac396948 > > --- /dev/null > > +++ b/arch/x86/entry/vdso/extable.h > > @@ -0,0 +1,29 @@ > > +/* SPDX-License-Identifier: GPL-2.0 */ > > +#ifndef __VDSO_EXTABLE_H > > +#define __VDSO_EXTABLE_H > > + > > +/* > > + * Inject exception fixup for vDSO code. Unlike normal exception fixup, > > + * vDSO uses a dedicated handler the addresses are relative to the overall > > + * exception table, not each individual entry. > > + */ > > +#ifdef __ASSEMBLY__ > > +#define _ASM_VDSO_EXTABLE_HANDLE(from, to) \ > > + ASM_VDSO_EXTABLE_HANDLE from to > > + > > +.macro ASM_VDSO_EXTABLE_HANDLE from:req to:req > > + .pushsection __ex_table, "a" > > + .long (\from) - __ex_table > > + .long (\to) - __ex_table > > + .popsection > > +.endm > > +#else > > +#define _ASM_VDSO_EXTABLE_HANDLE(from, to) \ > > + ".pushsection __ex_table, \"a\"\n" \ > > + ".long (" #from ") - __ex_table\n" \ > > + ".long (" #to ") - __ex_table\n" \ > > + ".popsection\n" > > +#endif > > + > > +#endif /* __VDSO_EXTABLE_H */ > > + > > Also from last time: > > .git/rebase-apply/patch:122: new blank line at EOF. > + From checkpatch I only get: ERROR: Macros with complex values should be enclosed in parentheses #193: FILE: arch/x86/entry/vdso/extable.h:11: +#define _ASM_VDSO_EXTABLE_HANDLE(from, to) \ + ASM_VDSO_EXTABLE_HANDLE from to ERROR: need consistent spacing around '*' (ctx:WxV) #244: FILE: arch/x86/entry/vdso/vdso2c.h:8: +static void BITSFUNC(copy)(FILE *outfile, const unsigned char *data, size_t len) ^ ERROR: need consistent spacing around '*' (ctx:WxV) #263: FILE: arch/x86/entry/vdso/vdso2c.h:27: + FILE *outfile, ELF(Shdr) *sec, const char *name) I did fix it now. Thanks. > -- > Regards/Gruss, > Boris. > > https://people.kernel.org/tglx/notes-about-netiquette /Jarkko
On Thu, Sep 24, 2020 at 03:09:01PM +0300, Jarkko Sakkinen wrote: > This is not technically SGX specific patch. Is SGX documentation the > correct place for this? So what is it then? It is SGX implementation-specific. Why would you not put it in the documentation?! > From checkpatch I only get: Please concentrate and start reading more carefully: ".git/rebase-apply/patch:122: new blank line at EOF." Would that error come from checkpatch?
On Thu, Sep 24, 2020 at 06:00:57PM +0200, Borislav Petkov wrote: > On Thu, Sep 24, 2020 at 03:09:01PM +0300, Jarkko Sakkinen wrote: > > This is not technically SGX specific patch. Is SGX documentation the > > correct place for this? > > So what is it then? It is SGX implementation-specific. Why would you not > put it in the documentation?! > > > From checkpatch I only get: > > Please concentrate and start reading more carefully: > > ".git/rebase-apply/patch:122: new blank line at EOF." > > Would that error come from checkpatch? Nope. And I did fully read what you wrote. I just mentioned that more in the tone that I should (and will) do also git am test from now on, at least for mainline tree (when applicable) and x86 tip. Right now the static tests that I do are checkpatch and sparse. Any other suggestions are welcome. I would also also coccicheck but have had some version issues with it in Ubuntu, which I use as my host OS. Cannot recall what was the exact issue, has been a while since I last tried it. > -- > Regards/Gruss, > Boris. > > https://people.kernel.org/tglx/notes-about-netiquette /Jarkko
diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile index 215376d975a2..3f183d0b8826 100644 --- a/arch/x86/entry/vdso/Makefile +++ b/arch/x86/entry/vdso/Makefile @@ -31,7 +31,7 @@ vobjs32-y := vdso32/note.o vdso32/system_call.o vdso32/sigreturn.o vobjs32-y += vdso32/vclock_gettime.o # files to link into kernel -obj-y += vma.o +obj-y += vma.o extable.o KASAN_SANITIZE_vma.o := y UBSAN_SANITIZE_vma.o := y KCSAN_SANITIZE_vma.o := y @@ -130,8 +130,8 @@ $(obj)/%-x32.o: $(obj)/%.o FORCE targets += vdsox32.lds $(vobjx32s-y) -$(obj)/%.so: OBJCOPYFLAGS := -S -$(obj)/%.so: $(obj)/%.so.dbg FORCE +$(obj)/%.so: OBJCOPYFLAGS := -S --remove-section __ex_table +$(obj)/%.so: $(obj)/%.so.dbg $(call if_changed,objcopy) $(obj)/vdsox32.so.dbg: $(obj)/vdsox32.lds $(vobjx32s) FORCE diff --git a/arch/x86/entry/vdso/extable.c b/arch/x86/entry/vdso/extable.c new file mode 100644 index 000000000000..afcf5b65beef --- /dev/null +++ b/arch/x86/entry/vdso/extable.c @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <linux/err.h> +#include <linux/mm.h> +#include <asm/current.h> +#include <asm/traps.h> +#include <asm/vdso.h> + +struct vdso_exception_table_entry { + int insn, fixup; +}; + +bool fixup_vdso_exception(struct pt_regs *regs, int trapnr, + unsigned long error_code, unsigned long fault_addr) +{ + const struct vdso_image *image = current->mm->context.vdso_image; + const struct vdso_exception_table_entry *extable; + unsigned int nr_entries, i; + unsigned long base; + + /* + * Do not attempt to fixup #DB or #BP. It's impossible to identify + * whether or not a #DB/#BP originated from within an SGX enclave and + * SGX enclaves are currently the only use case for vDSO fixup. + */ + if (trapnr == X86_TRAP_DB || trapnr == X86_TRAP_BP) + return false; + + if (!current->mm->context.vdso) + return false; + + base = (unsigned long)current->mm->context.vdso + image->extable_base; + nr_entries = image->extable_len / (sizeof(*extable)); + extable = image->extable; + + for (i = 0; i < nr_entries; i++) { + if (regs->ip == base + extable[i].insn) { + regs->ip = base + extable[i].fixup; + regs->di = trapnr; + regs->si = error_code; + regs->dx = fault_addr; + return true; + } + } + + return false; +} diff --git a/arch/x86/entry/vdso/extable.h b/arch/x86/entry/vdso/extable.h new file mode 100644 index 000000000000..aafdac396948 --- /dev/null +++ b/arch/x86/entry/vdso/extable.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __VDSO_EXTABLE_H +#define __VDSO_EXTABLE_H + +/* + * Inject exception fixup for vDSO code. Unlike normal exception fixup, + * vDSO uses a dedicated handler the addresses are relative to the overall + * exception table, not each individual entry. + */ +#ifdef __ASSEMBLY__ +#define _ASM_VDSO_EXTABLE_HANDLE(from, to) \ + ASM_VDSO_EXTABLE_HANDLE from to + +.macro ASM_VDSO_EXTABLE_HANDLE from:req to:req + .pushsection __ex_table, "a" + .long (\from) - __ex_table + .long (\to) - __ex_table + .popsection +.endm +#else +#define _ASM_VDSO_EXTABLE_HANDLE(from, to) \ + ".pushsection __ex_table, \"a\"\n" \ + ".long (" #from ") - __ex_table\n" \ + ".long (" #to ") - __ex_table\n" \ + ".popsection\n" +#endif + +#endif /* __VDSO_EXTABLE_H */ + diff --git a/arch/x86/entry/vdso/vdso-layout.lds.S b/arch/x86/entry/vdso/vdso-layout.lds.S index 4d152933547d..dc8da7695859 100644 --- a/arch/x86/entry/vdso/vdso-layout.lds.S +++ b/arch/x86/entry/vdso/vdso-layout.lds.S @@ -75,11 +75,18 @@ SECTIONS * stuff that isn't used at runtime in between. */ - .text : { *(.text*) } :text =0x90909090, + .text : { + *(.text*) + *(.fixup) + } :text =0x90909090, + + .altinstructions : { *(.altinstructions) } :text .altinstr_replacement : { *(.altinstr_replacement) } :text + __ex_table : { *(__ex_table) } :text + /DISCARD/ : { *(.discard) *(.discard.*) diff --git a/arch/x86/entry/vdso/vdso2c.h b/arch/x86/entry/vdso/vdso2c.h index 6f46e11ce539..1c7cfac7e64a 100644 --- a/arch/x86/entry/vdso/vdso2c.h +++ b/arch/x86/entry/vdso/vdso2c.h @@ -5,6 +5,41 @@ * are built for 32-bit userspace. */ +static void BITSFUNC(copy)(FILE *outfile, const unsigned char *data, size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) { + if (i % 10 == 0) + fprintf(outfile, "\n\t"); + fprintf(outfile, "0x%02X, ", (int)(data)[i]); + } +} + + +/* + * Extract a section from the input data into a standalone blob. Used to + * capture kernel-only data that needs to persist indefinitely, e.g. the + * exception fixup tables, but only in the kernel, i.e. the section can + * be stripped from the final vDSO image. + */ +static void BITSFUNC(extract)(const unsigned char *data, size_t data_len, + FILE *outfile, ELF(Shdr) *sec, const char *name) +{ + unsigned long offset; + size_t len; + + offset = (unsigned long)GET_LE(&sec->sh_offset); + len = (size_t)GET_LE(&sec->sh_size); + + if (offset + len > data_len) + fail("section to extract overruns input data"); + + fprintf(outfile, "static const unsigned char %s[%lu] = {", name, len); + BITSFUNC(copy)(outfile, data + offset, len); + fprintf(outfile, "\n};\n\n"); +} + static void BITSFUNC(go)(void *raw_addr, size_t raw_len, void *stripped_addr, size_t stripped_len, FILE *outfile, const char *image_name) @@ -15,7 +50,7 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len, ELF(Ehdr) *hdr = (ELF(Ehdr) *)raw_addr; unsigned long i, syms_nr; ELF(Shdr) *symtab_hdr = NULL, *strtab_hdr, *secstrings_hdr, - *alt_sec = NULL; + *alt_sec = NULL, *extable_sec = NULL; ELF(Dyn) *dyn = 0, *dyn_end = 0; const char *secstrings; INT_BITS syms[NSYMS] = {}; @@ -77,6 +112,8 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len, if (!strcmp(secstrings + GET_LE(&sh->sh_name), ".altinstructions")) alt_sec = sh; + if (!strcmp(secstrings + GET_LE(&sh->sh_name), "__ex_table")) + extable_sec = sh; } if (!symtab_hdr) @@ -155,6 +192,9 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len, (int)((unsigned char *)stripped_addr)[i]); } fprintf(outfile, "\n};\n\n"); + if (extable_sec) + BITSFUNC(extract)(raw_addr, raw_len, outfile, + extable_sec, "extable"); fprintf(outfile, "const struct vdso_image %s = {\n", image_name); fprintf(outfile, "\t.data = raw_data,\n"); @@ -165,6 +205,14 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len, fprintf(outfile, "\t.alt_len = %lu,\n", (unsigned long)GET_LE(&alt_sec->sh_size)); } + if (extable_sec) { + fprintf(outfile, "\t.extable_base = %lu,\n", + (unsigned long)GET_LE(&extable_sec->sh_offset)); + fprintf(outfile, "\t.extable_len = %lu,\n", + (unsigned long)GET_LE(&extable_sec->sh_size)); + fprintf(outfile, "\t.extable = extable,\n"); + } + for (i = 0; i < NSYMS; i++) { if (required_syms[i].export && syms[i]) fprintf(outfile, "\t.sym_%s = %" PRIi64 ",\n", diff --git a/arch/x86/include/asm/vdso.h b/arch/x86/include/asm/vdso.h index bbcdc7b8f963..b5d23470f56b 100644 --- a/arch/x86/include/asm/vdso.h +++ b/arch/x86/include/asm/vdso.h @@ -15,6 +15,8 @@ struct vdso_image { unsigned long size; /* Always a multiple of PAGE_SIZE */ unsigned long alt, alt_len; + unsigned long extable_base, extable_len; + const void *extable; long sym_vvar_start; /* Negative offset to the vvar area */ @@ -45,6 +47,9 @@ extern void __init init_vdso_image(const struct vdso_image *image); extern int map_vdso_once(const struct vdso_image *image, unsigned long addr); +extern bool fixup_vdso_exception(struct pt_regs *regs, int trapnr, + unsigned long error_code, + unsigned long fault_addr); #endif /* __ASSEMBLER__ */ #endif /* _ASM_X86_VDSO_H */