Re: [PATCH v36 22/24] selftests/x86: Add a selftest for SGX

2020-08-28 Thread Jarkko Sakkinen
On Thu, Aug 27, 2020 at 08:20:51AM -0700, Sean Christopherson wrote:
> On Thu, Aug 27, 2020 at 12:47:04AM -0400, Nathaniel McCallum wrote:
> > > +int main(int argc, char *argv[], char *envp[])
> > > +{
> > > +   struct sgx_enclave_exception exception;
> > > +   struct vdso_symtab symtab;
> > > +   Elf64_Sym *eenter_sym;
> > > +   uint64_t result = 0;
> > > +   struct encl encl;
> > > +   unsigned int i;
> > > +   void *addr;
> > > +
> > > +   if (!encl_load("test_encl.elf", ))
> > > +   goto err;
> > > +
> > > +   if (!encl_measure())
> > > +   goto err;
> > > +
> > > +   if (!encl_build())
> > > +   goto err;
> > > +
> > > +   /*
> > > +* An enclave consumer only must do this.
> > > +*/
> > > +   for (i = 0; i < encl.nr_segments; i++) {
> > > +   struct encl_segment *seg = _tbl[i];
> > > +
> > > +   addr = mmap((void *)encl.encl_base + seg->offset, 
> > > seg->size,
> > > +   seg->prot, MAP_SHARED | MAP_FIXED, encl.fd, 
> > > 0);
> > 
> > My patch version is a bit behind (v32), but I suspect this still
> > applies. I discovered the following by accident.
> > 
> > In the Enarx code base, this invocation succeeds:
> > mmap(0x2000, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED |
> > MAP_FIXED, sgxfd, 0)
> > 
> > However, this one fails with -EINVAL:
> > mmap(0x2000, 0x1000, PROT_READ | PROT_WRITE,
> > MAP_SHARED_VALIDATE | MAP_FIXED, sgxfd, 0)
> > 
> > From man mmap:
> > 
> >MAP_SHARED_VALIDATE (since Linux 4.15)
> >   This flag provides the same behavior as MAP_SHARED
> > except that MAP_SHARED mappings ignore unknown
> >   flags in flags.  By contrast, when creating a mapping
> > using MAP_SHARED_VALIDATE, the kernel veri‐
> >   fies  all  passed  flags  are  known  and fails the
> > mapping with the error EOPNOTSUPP for unknown
> >   flags.  This mapping type is also required to be able to
> > use some mapping flags (e.g., MAP_SYNC).
> > 
> > I can try again on a newer patch set tomorrow if need be. But the
> > documentation of mmap() doesn't match the behavior I'm seeing. A brief
> > look through the patch set didn't turn up anything obvious that could
> > be causing this.
> 
> This is a bug in sgx_get_unmapped_area().  EPC must be mapped SHARED, and
> so MAP_PRIVATE is disallowed.  The current check is:
> 
>   if (flags & MAP_PRIVATE)
>   return -EINVAL;
> 
> and the base "flags" are:
> 
>   #define MAP_SHARED  0x01/* Share changes */
>   #define MAP_PRIVATE 0x02/* Changes are private */
>   #define MAP_SHARED_VALIDATE 0x03/* share + validate extension flags 
> */
> 
> which causes the SGX check to interpret MAP_SHARED_VALIDATE as MAP_PRIVATE.
> The types are just that, types, not flag modifiers.  So the SGX code needs
> to be:
> 
>   if ((flags & MAP_TYPE) == MAP_PRIVATE)
>   return -EINVAL;

Updated, thanks.

/Jarkko


Re: [PATCH v36 22/24] selftests/x86: Add a selftest for SGX

2020-08-27 Thread Sean Christopherson
On Thu, Aug 27, 2020 at 12:47:04AM -0400, Nathaniel McCallum wrote:
> > +int main(int argc, char *argv[], char *envp[])
> > +{
> > +   struct sgx_enclave_exception exception;
> > +   struct vdso_symtab symtab;
> > +   Elf64_Sym *eenter_sym;
> > +   uint64_t result = 0;
> > +   struct encl encl;
> > +   unsigned int i;
> > +   void *addr;
> > +
> > +   if (!encl_load("test_encl.elf", ))
> > +   goto err;
> > +
> > +   if (!encl_measure())
> > +   goto err;
> > +
> > +   if (!encl_build())
> > +   goto err;
> > +
> > +   /*
> > +* An enclave consumer only must do this.
> > +*/
> > +   for (i = 0; i < encl.nr_segments; i++) {
> > +   struct encl_segment *seg = _tbl[i];
> > +
> > +   addr = mmap((void *)encl.encl_base + seg->offset, seg->size,
> > +   seg->prot, MAP_SHARED | MAP_FIXED, encl.fd, 0);
> 
> My patch version is a bit behind (v32), but I suspect this still
> applies. I discovered the following by accident.
> 
> In the Enarx code base, this invocation succeeds:
> mmap(0x2000, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED |
> MAP_FIXED, sgxfd, 0)
> 
> However, this one fails with -EINVAL:
> mmap(0x2000, 0x1000, PROT_READ | PROT_WRITE,
> MAP_SHARED_VALIDATE | MAP_FIXED, sgxfd, 0)
> 
> From man mmap:
> 
>MAP_SHARED_VALIDATE (since Linux 4.15)
>   This flag provides the same behavior as MAP_SHARED
> except that MAP_SHARED mappings ignore unknown
>   flags in flags.  By contrast, when creating a mapping
> using MAP_SHARED_VALIDATE, the kernel veri‐
>   fies  all  passed  flags  are  known  and fails the
> mapping with the error EOPNOTSUPP for unknown
>   flags.  This mapping type is also required to be able to
> use some mapping flags (e.g., MAP_SYNC).
> 
> I can try again on a newer patch set tomorrow if need be. But the
> documentation of mmap() doesn't match the behavior I'm seeing. A brief
> look through the patch set didn't turn up anything obvious that could
> be causing this.

This is a bug in sgx_get_unmapped_area().  EPC must be mapped SHARED, and
so MAP_PRIVATE is disallowed.  The current check is:

  if (flags & MAP_PRIVATE)
  return -EINVAL;

and the base "flags" are:

  #define MAP_SHARED  0x01/* Share changes */
  #define MAP_PRIVATE 0x02/* Changes are private */
  #define MAP_SHARED_VALIDATE 0x03/* share + validate extension flags */

which causes the SGX check to interpret MAP_SHARED_VALIDATE as MAP_PRIVATE.
The types are just that, types, not flag modifiers.  So the SGX code needs
to be:

  if ((flags & MAP_TYPE) == MAP_PRIVATE)
  return -EINVAL;

or

  unsigned long map_type = (flags & MAP_TYPE);

  if (map_type != MAP_SHARED && map_type != MAP_SHARED_VALIDATE)
  return -EINVAL;


Side topic, there is at least one existing bug of this nature, in mm/nommu.c.
I'll send a patch for that and look for any other instances of the bad
pattern.


Re: [PATCH v36 22/24] selftests/x86: Add a selftest for SGX

2020-08-26 Thread Nathaniel McCallum
On Thu, Jul 16, 2020 at 9:58 AM Jarkko Sakkinen
 wrote:
>
> Add a selftest for SGX. It is a trivial test where a simple enclave
> copies one 64-bit word of memory between two memory locations.
>
> Cc: linux-kselft...@vger.kernel.org
> Signed-off-by: Jarkko Sakkinen 
> ---
>  tools/testing/selftests/Makefile  |   1 +
>  tools/testing/selftests/sgx/.gitignore|   2 +
>  tools/testing/selftests/sgx/Makefile  |  53 +++
>  tools/testing/selftests/sgx/call.S|  54 +++
>  tools/testing/selftests/sgx/defines.h |  21 +
>  tools/testing/selftests/sgx/load.c| 282 +
>  tools/testing/selftests/sgx/main.c| 199 +
>  tools/testing/selftests/sgx/main.h|  38 ++
>  tools/testing/selftests/sgx/sigstruct.c   | 395 ++
>  tools/testing/selftests/sgx/test_encl.c   |  20 +
>  tools/testing/selftests/sgx/test_encl.lds |  40 ++
>  .../selftests/sgx/test_encl_bootstrap.S   |  89 
>  12 files changed, 1194 insertions(+)
>  create mode 100644 tools/testing/selftests/sgx/.gitignore
>  create mode 100644 tools/testing/selftests/sgx/Makefile
>  create mode 100644 tools/testing/selftests/sgx/call.S
>  create mode 100644 tools/testing/selftests/sgx/defines.h
>  create mode 100644 tools/testing/selftests/sgx/load.c
>  create mode 100644 tools/testing/selftests/sgx/main.c
>  create mode 100644 tools/testing/selftests/sgx/main.h
>  create mode 100644 tools/testing/selftests/sgx/sigstruct.c
>  create mode 100644 tools/testing/selftests/sgx/test_encl.c
>  create mode 100644 tools/testing/selftests/sgx/test_encl.lds
>  create mode 100644 tools/testing/selftests/sgx/test_encl_bootstrap.S
>
> diff --git a/tools/testing/selftests/Makefile 
> b/tools/testing/selftests/Makefile
> index 1195bd85af38..ec7be6d5a10d 100644
> --- a/tools/testing/selftests/Makefile
> +++ b/tools/testing/selftests/Makefile
> @@ -64,6 +64,7 @@ TARGETS += user
>  TARGETS += vm
>  TARGETS += x86
>  TARGETS += zram
> +TARGETS += sgx
>  #Please keep the TARGETS list alphabetically sorted
>  # Run "make quicktest=1 run_tests" or
>  # "make quicktest=1 kselftest" from top level Makefile
> diff --git a/tools/testing/selftests/sgx/.gitignore 
> b/tools/testing/selftests/sgx/.gitignore
> new file mode 100644
> index ..fbaf0bda9a92
> --- /dev/null
> +++ b/tools/testing/selftests/sgx/.gitignore
> @@ -0,0 +1,2 @@
> +test_sgx
> +test_encl.elf
> diff --git a/tools/testing/selftests/sgx/Makefile 
> b/tools/testing/selftests/sgx/Makefile
> new file mode 100644
> index ..95e5c4df8014
> --- /dev/null
> +++ b/tools/testing/selftests/sgx/Makefile
> @@ -0,0 +1,53 @@
> +top_srcdir = ../../../..
> +
> +include ../lib.mk
> +
> +.PHONY: all clean
> +
> +CAN_BUILD_X86_64 := $(shell ../x86/check_cc.sh $(CC) \
> +   ../x86/trivial_64bit_program.c)
> +
> +ifndef OBJCOPY
> +OBJCOPY := $(CROSS_COMPILE)objcopy
> +endif
> +
> +INCLUDES := -I$(top_srcdir)/tools/include
> +HOST_CFLAGS := -Wall -Werror -g $(INCLUDES) -fPIC -z noexecstack
> +ENCL_CFLAGS := -Wall -Werror -static -nostdlib -nostartfiles -fPIC \
> +  -fno-stack-protector -mrdrnd $(INCLUDES)
> +
> +TEST_CUSTOM_PROGS := $(OUTPUT)/test_sgx $(OUTPUT)/test_encl.elf
> +
> +ifeq ($(CAN_BUILD_X86_64), 1)
> +all: $(TEST_CUSTOM_PROGS)
> +endif
> +
> +$(OUTPUT)/test_sgx: $(OUTPUT)/main.o \
> +   $(OUTPUT)/load.o \
> +   $(OUTPUT)/sigstruct.o \
> +   $(OUTPUT)/call.o
> +   $(CC) $(HOST_CFLAGS) -o $@ $^ -lcrypto
> +
> +$(OUTPUT)/main.o: main.c
> +   $(CC) $(HOST_CFLAGS) -c $< -o $@
> +
> +$(OUTPUT)/load.o: load.c
> +   $(CC) $(HOST_CFLAGS) -c $< -o $@
> +
> +$(OUTPUT)/sigstruct.o: sigstruct.c
> +   $(CC) $(HOST_CFLAGS) -c $< -o $@
> +
> +$(OUTPUT)/call.o: call.S
> +   $(CC) $(HOST_CFLAGS) -c $< -o $@
> +
> +$(OUTPUT)/test_encl.elf: test_encl.lds test_encl.c test_encl_bootstrap.S
> +   $(CC) $(ENCL_CFLAGS) -T $^ -o $@
> +
> +EXTRA_CLEAN := \
> +   $(OUTPUT)/test_encl.elf \
> +   $(OUTPUT)/load.o \
> +   $(OUTPUT)/call.o \
> +   $(OUTPUT)/main.o \
> +   $(OUTPUT)/sigstruct.o \
> +   $(OUTPUT)/test_sgx \
> +   $(OUTPUT)/test_sgx.o \
> diff --git a/tools/testing/selftests/sgx/call.S 
> b/tools/testing/selftests/sgx/call.S
> new file mode 100644
> index ..77131e83db42
> --- /dev/null
> +++ b/tools/testing/selftests/sgx/call.S
> @@ -0,0 +1,54 @@
> +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
> +/**
> +* Copyright(c) 2016-18 Intel Corporation.
> +*/
> +
> +   .text
> +
> +   .macro ENCLU
> +   .byte 0x0f, 0x01, 0xd7
> +   .endm
> +
> +   .text
> +
> +   .global sgx_call_vdso
> +sgx_call_vdso:
> +   .cfi_startproc
> +   push%r15
> +   .cfi_adjust_cfa_offset  8
> +   .cfi_rel_offset %r15, 0
> +   push%r14
> +   .cfi_adjust_cfa_offset  8
> +   .cfi_rel_offset %r14, 0
> +   

[PATCH v36 22/24] selftests/x86: Add a selftest for SGX

2020-07-16 Thread Jarkko Sakkinen
Add a selftest for SGX. It is a trivial test where a simple enclave
copies one 64-bit word of memory between two memory locations.

Cc: linux-kselft...@vger.kernel.org
Signed-off-by: Jarkko Sakkinen 
---
 tools/testing/selftests/Makefile  |   1 +
 tools/testing/selftests/sgx/.gitignore|   2 +
 tools/testing/selftests/sgx/Makefile  |  53 +++
 tools/testing/selftests/sgx/call.S|  54 +++
 tools/testing/selftests/sgx/defines.h |  21 +
 tools/testing/selftests/sgx/load.c| 282 +
 tools/testing/selftests/sgx/main.c| 199 +
 tools/testing/selftests/sgx/main.h|  38 ++
 tools/testing/selftests/sgx/sigstruct.c   | 395 ++
 tools/testing/selftests/sgx/test_encl.c   |  20 +
 tools/testing/selftests/sgx/test_encl.lds |  40 ++
 .../selftests/sgx/test_encl_bootstrap.S   |  89 
 12 files changed, 1194 insertions(+)
 create mode 100644 tools/testing/selftests/sgx/.gitignore
 create mode 100644 tools/testing/selftests/sgx/Makefile
 create mode 100644 tools/testing/selftests/sgx/call.S
 create mode 100644 tools/testing/selftests/sgx/defines.h
 create mode 100644 tools/testing/selftests/sgx/load.c
 create mode 100644 tools/testing/selftests/sgx/main.c
 create mode 100644 tools/testing/selftests/sgx/main.h
 create mode 100644 tools/testing/selftests/sgx/sigstruct.c
 create mode 100644 tools/testing/selftests/sgx/test_encl.c
 create mode 100644 tools/testing/selftests/sgx/test_encl.lds
 create mode 100644 tools/testing/selftests/sgx/test_encl_bootstrap.S

diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index 1195bd85af38..ec7be6d5a10d 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -64,6 +64,7 @@ TARGETS += user
 TARGETS += vm
 TARGETS += x86
 TARGETS += zram
+TARGETS += sgx
 #Please keep the TARGETS list alphabetically sorted
 # Run "make quicktest=1 run_tests" or
 # "make quicktest=1 kselftest" from top level Makefile
diff --git a/tools/testing/selftests/sgx/.gitignore 
b/tools/testing/selftests/sgx/.gitignore
new file mode 100644
index ..fbaf0bda9a92
--- /dev/null
+++ b/tools/testing/selftests/sgx/.gitignore
@@ -0,0 +1,2 @@
+test_sgx
+test_encl.elf
diff --git a/tools/testing/selftests/sgx/Makefile 
b/tools/testing/selftests/sgx/Makefile
new file mode 100644
index ..95e5c4df8014
--- /dev/null
+++ b/tools/testing/selftests/sgx/Makefile
@@ -0,0 +1,53 @@
+top_srcdir = ../../../..
+
+include ../lib.mk
+
+.PHONY: all clean
+
+CAN_BUILD_X86_64 := $(shell ../x86/check_cc.sh $(CC) \
+   ../x86/trivial_64bit_program.c)
+
+ifndef OBJCOPY
+OBJCOPY := $(CROSS_COMPILE)objcopy
+endif
+
+INCLUDES := -I$(top_srcdir)/tools/include
+HOST_CFLAGS := -Wall -Werror -g $(INCLUDES) -fPIC -z noexecstack
+ENCL_CFLAGS := -Wall -Werror -static -nostdlib -nostartfiles -fPIC \
+  -fno-stack-protector -mrdrnd $(INCLUDES)
+
+TEST_CUSTOM_PROGS := $(OUTPUT)/test_sgx $(OUTPUT)/test_encl.elf
+
+ifeq ($(CAN_BUILD_X86_64), 1)
+all: $(TEST_CUSTOM_PROGS)
+endif
+
+$(OUTPUT)/test_sgx: $(OUTPUT)/main.o \
+   $(OUTPUT)/load.o \
+   $(OUTPUT)/sigstruct.o \
+   $(OUTPUT)/call.o
+   $(CC) $(HOST_CFLAGS) -o $@ $^ -lcrypto
+
+$(OUTPUT)/main.o: main.c
+   $(CC) $(HOST_CFLAGS) -c $< -o $@
+
+$(OUTPUT)/load.o: load.c
+   $(CC) $(HOST_CFLAGS) -c $< -o $@
+
+$(OUTPUT)/sigstruct.o: sigstruct.c
+   $(CC) $(HOST_CFLAGS) -c $< -o $@
+
+$(OUTPUT)/call.o: call.S
+   $(CC) $(HOST_CFLAGS) -c $< -o $@
+
+$(OUTPUT)/test_encl.elf: test_encl.lds test_encl.c test_encl_bootstrap.S
+   $(CC) $(ENCL_CFLAGS) -T $^ -o $@
+
+EXTRA_CLEAN := \
+   $(OUTPUT)/test_encl.elf \
+   $(OUTPUT)/load.o \
+   $(OUTPUT)/call.o \
+   $(OUTPUT)/main.o \
+   $(OUTPUT)/sigstruct.o \
+   $(OUTPUT)/test_sgx \
+   $(OUTPUT)/test_sgx.o \
diff --git a/tools/testing/selftests/sgx/call.S 
b/tools/testing/selftests/sgx/call.S
new file mode 100644
index ..77131e83db42
--- /dev/null
+++ b/tools/testing/selftests/sgx/call.S
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/**
+* Copyright(c) 2016-18 Intel Corporation.
+*/
+
+   .text
+
+   .macro ENCLU
+   .byte 0x0f, 0x01, 0xd7
+   .endm
+
+   .text
+
+   .global sgx_call_vdso
+sgx_call_vdso:
+   .cfi_startproc
+   push%r15
+   .cfi_adjust_cfa_offset  8
+   .cfi_rel_offset %r15, 0
+   push%r14
+   .cfi_adjust_cfa_offset  8
+   .cfi_rel_offset %r14, 0
+   push%r13
+   .cfi_adjust_cfa_offset  8
+   .cfi_rel_offset %r13, 0
+   push%r12
+   .cfi_adjust_cfa_offset  8
+   .cfi_rel_offset %r12, 0
+   push%rbx
+   .cfi_adjust_cfa_offset  8
+   .cfi_rel_offset %rbx, 0
+   push$0
+   .cfi_adjust_cfa_offset  8
+   push