-
Notifications
You must be signed in to change notification settings - Fork 517
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add basic Intel SGX support #2219
base: master
Are you sure you want to change the base?
Conversation
d0ff414
to
f16266b
Compare
Tests are failing because conditional |
Here are some possible solutions to the problem:
|
Thanks, interesting stuff! I'll look into the changes as soon as I get a chance. I agree banning plain sprintf() would be nice. The reason sprintf() is currently used is that snprintf() has portability issues, e.g. it's not available on legacy platforms and sometimes interpretations before C99 differ, especially handling of truncation. So there are pros and cons in each case. I'd be OK with requiring snprintf(), it's probably the better compromise. Users running pre-C99 would then need to implement or borrow one but that's not a big deal. This could be made easier by making it easy to use the minimal replacements https://github.com/svaarala/duktape/tree/master/extras/minimal-printf via config. |
I decided to add a new option This PR is getting a little large, maybe once we agree on things I can break it up into smaller ones. |
src-input/duk_util_misc.c
Outdated
|
||
for (i = 0; i < sz; i++) { | ||
if (0 == buf[i]) { | ||
goto safe_sscanf; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Decided to add this safety check for sscanf
because previously there was none, and there could have been cases where, for eg. { "__ptr": " " }
was passed, and since sscanf
and %p
are generally available, but the %p
is not specified meaning bad implementations may start reading the JX buffer until the end. This way, that can't ever happen.
Re: forcing It would be best for the define not to have a But if it would be clearer, maybe forced platforms could be handled using a convention like |
I'll try to review the diff tomorrow night, assuming it is ready for comments. |
Yes, ready for comments @svaarala. I agree on the point for |
config/config-options/DUK_USE_STANDARDIZED_POINTER_ENCODING.yaml
Outdated
Show resolved
Hide resolved
@hf I finally got some time to do a review on the changes. Mostly just trivia but there's one probable snprintf() truncation issue and AUTHORS needs a fix. With these fixed and the commits squashed this is ready for merging. Thanks for the detailed work! 👍 |
@svaarala Thanks for reviewing. I tried to get all indent issues, but not sure how I missed these. Maybe think about setting up I'll investigate more about the snprintf, and adjust code so that it works good. I like the |
What's the ideal style for |
Still many broken indents. Something is wrong with my vim, it's confused by this codebase. |
In the current codebase it would simply be |
I've gone through uncrustify, astyle, and clang-format, and none of them have enough controls to get the results I would want (which is not surprising). But it's probably best to compromise on the result so that code style would be automatic, so I'll merge in something for 3.0.x release. This was one major issue: https://stackoverflow.com/questions/38620019/can-clang-format-align-a-block-of-defines-for-me. It's fixed in clang-format-9 but that may not be available on the host so the autoindenting step will need to be dockerized. |
Also a good idea is to add |
Adding a |
Hey @svaarala I finally managed to fix all outstanding issues. Would you mind checking the logic I used in the unresolved comments before merging? TODOs post PR: |
I'll take a look - after that commits should be squashed for merging (a single commit is fine). |
skip reliance on sscanf for platforms that don't support it. | ||
|
||
When turned off, pointer encoding to string is done via the %p format | ||
specifier in the printf and scanf family of functions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file should be removed from the squashed commit.
@@ -0,0 +1,9 @@ | |||
/** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trivia: no double star in comment style.
#undef DUK_USE_DATE_TZO_GMTIME_R | ||
#undef DUK_USE_DATE_TZO_GMTIME_S | ||
#undef DUK_USE_DATE_TZO_WINDOWS | ||
#undef DUK_USE_DATE_TZO_WINDOWS_NO_DST |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should be no need to undefine any of these. Only platform files are intended to define the Date provider defines.
* DUK_USE_DATE_GET_LOCAL_TZOFFSET for their enclave either manually | ||
* in duk_config.h or via other means (other config header, compiler | ||
* flags). If these are not defined compilation will fail with a | ||
* preprocessor error. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should just say "in duk_config.h", no other means are supported. So something like:
Enclave developers must provide DUK_USE_DATE_GET_NOW and DUK_USE_DATE_GET_LOCAL_TZOFFSET when configuring Duktape for build.
* Intel SGX enclaves don't have access to sscanf, so pointer parsing must | ||
* be without using sscanf. | ||
*/ | ||
#define DUK_USE_MEMBASED_POINTER_ENCODING |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This probably won't work as expected: if this define appears here, it will prevent the emission of the default value for all platforms when duk_config.h default/forced options section is emitted. The problem is that the default/forced options section only knows that the define is forced in the preceding header, but it doesn't know (or care) that it is conditional to a platform.
So IMO this header should just say in its comments that DUK_USE_MEMBASED_POINTER_ENCODING
is a required option for Intel SGX enclaves. There should be a better way to address this, but at present I don't think configure.py can do better.
One possible solution would be for platforms to optionally have a config check snippet at the end of duk_config.h
where they could check that required options are met, so that they could #error
out cleanly.
* snprintf does not always terminate with NUL, however if it does it will | ||
* write the NUL in the C position, which can be overwritten with 0xff | ||
* if desc is NULL. Nonetheless, snprintf when positive, returns the number | ||
* of bytes that the format would have taken without counting NUL. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indent is broken here.
* | ||
* A len B f f f f f f f f - f f f f f f f f C | ||
* -- --- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- | ||
* 00 len 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This layout seems a bit confusing, the offsets in the bottom row are not continuous (due to len).
/* make sure that we had enough room to format the symbol */ | ||
DUK_ASSERT(flen > 0 && flen <= 1 + 17 /* without + 1 for NUL */); | ||
|
||
p += flen; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This block has broken indent.
@@ -91,16 +91,40 @@ DUK_LOCAL void duk__bi_print(const char *name, duk__bigint *x) { | |||
char buf[DUK__BI_MAX_PARTS * 9 + 64]; | |||
char *p = buf; | |||
duk_small_int_t i; | |||
duk_int_t flen; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Broken indent.
p += 63; | ||
} else if (flen > 0) { | ||
p += flen; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had forgotten about the possible negative error return value :o
Negative returns are probably not addressed correctly elsewhere. But it doesn't need to be addressed in this pull.
(Easiest fix would be to have an internal duk_snprintf() helper which would post-process the snprintf() return value: just convert <0 to 0, and cap the return value to bufsize - 1. The return value could then safely be used as is to increment pointers.)
@hf Went through the changes and there's just some minor trivia left, see review comments. Once you address them, you can just squash the commits into one, and I'll then merge the changes. I'll fix up whatever trivia is left while working on the snprintf() handling generally. |
Duktape is great for embedded environments, and so I wanted to try and run it in Intel SGX. There is some special configuration needed and refactoring string formatting in a few places, but otherwise works just fine.
Summary of changes:
platform_intelsgx
.The order is important to be immediately above Linux and Windows. Intel SGX enclaves are compiled under Linux or Windows with a special C library (tlibc; trusted libc) but otherwise are indistinguishable from other object files. Therefore the Linux and Windows detection will trigger.
There is no official documentation that describes if there is a macro you can check to see if compiling against tlibc; I did manage to find
_TLIBC_CDECL_
and a few others fromsys/cdefs.h
which might be used for this purpose but I decided it's best to prefer manual versus automatic detection. In order to hint that this is the Intel SGX build either defineINTELSGX
manually or use--platform=intelsgx
in theconfigure.py
invocations.DUK_USE_DATE_GET_NOW
andDUK_USE_DATE_GET_LOCAL_TZOFFSET
. These are mandatory and well documented, and compilation fails with a preprocessor error if they are not added.DUK_SPRINTF
needed to be refactored intoDUK_SNPRINTF
, but that was an easy affair. In general it's my opinion that going forward the unsafe functions be completely "banned" from the Duktape code, and be replaced with safe ones.DUK_USE_STANDARDIZED_POINTER_ENCODING
option (default: false) that encodes all pointers in a "standardized" way i.e. in lowercase hexadecimal encoding as the value is laid out in memory. In order to implement this, the functionsduk_encode_pointer_cstr
andduk_decode_pointer_cstr
were added toduk_util_misc.c
. They have also been replaced wherever the%p
format specifier was used directly or indirectly (except for debug statements, of course). By enabling this option, Duktape no longer usesDUK_SSCANF
..gitignore
, most importantlyruntests/package-lock.json
which is added by npm when tests are run locally. It may be a good idea to remove this from.gitignore
if we want to pin down versions.python
withinruntests/runtests.js
topython2.7
since running theecmatest
with Python 3 failed with error. These days Python 3 is behindpython
, while 2.7 can be invoked withpython2.7
.This PR is not complete I'm still testing and changing things, but discussions can begin IMO.
Remaining things to complete:
apitest
fails whenDUK_USE_STANDARDIZED_POINTER_ENCODING
because of the hardcoded expectation for0xdeadbeef
.ecmatest
succeeds, tho. Possible solutions:jade
or some other preprocessor so they can be configured before being run.0xdeadbeef
occurrences in expectations withintests/api
are replaced with a configurable value.