Some questions about the ɴaᴄl-glibc libc (This is for Linux on ᴀᴍᴅ64)

55 views
Skip to first unread message

lael.c...@gmail.com

unread,
Sep 7, 2016, 3:19:45 PM9/7/16
to Native-Client-Discuss
Hello,

Since systems calls are disabled in ɴaᴄl, what libc functions are wrapped ?
Does mprotect() or mmap() with PROT_EXEC is availaible ?

Also what is the exact allowed whitelist of ᴄᴘᴜ instructions ? It seems to be really obfuscated in the code.

Please note no web browser is involved in my case (chrome or chromium isn’t even installed). The program is python.nexe version 2.7.1.

regards, 

Derek Schuff

unread,
Sep 7, 2016, 4:52:54 PM9/7/16
to Native-Client-Discuss
In NaCl you can't just map any executable code into the untrusted address space, because everything has to be validated before it can be executed. NaCl has a syscall (mostly for JIT-style use cases) nacl_dyncode_create ( see for example https://chromium.googlesource.com/native_client/src/native_client/+/master/src/untrusted/nacl/nacl_dyncode.h and its tests in https://chromium.googlesource.com/native_client/src/native_client/+/master/tests/dynamic_code_loading/ ). In that case you generate valid code in memory and load it. 


There's no definitive list of whitelisted instructions other than the validator implementation, but it's not too hard to read once you find it and figure out how; see for example https://chromium.googlesource.com/native_client/src/native_client/+/master/src/trusted/validator_ragel/instruction_definitions/general_purpose_instructions.def and the other definitions in that directory.

--
You received this message because you are subscribed to the Google Groups "Native-Client-Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to native-client-di...@googlegroups.com.
To post to this group, send email to native-cli...@googlegroups.com.
Visit this group at https://groups.google.com/group/native-client-discuss.
For more options, visit https://groups.google.com/d/optout.

lael.c...@gmail.com

unread,
Sep 7, 2016, 6:35:06 PM9/7/16
to Native-Client-Discuss
Le mercredi 7 septembre 2016 22:52:54 UTC+2, Derek Schuff a écrit :
In NaCl you can't just map any executable code into the untrusted address space, because everything has to be validated before it can be executed. NaCl has a syscall (mostly for JIT-style use cases) nacl_dyncode_create ( see for example https://chromium.googlesource.com/native_client/src/native_client/+/master/src/untrusted/nacl/nacl_dyncode.h and its tests in https://chromium.googlesource.com/native_client/src/native_client/+/master/tests/dynamic_code_loading/ ). In that case you generate valid code in memory and load it. 


There's no definitive list of whitelisted instructions other than the validator implementation, but it's not too hard to read once you find it and figure out how; see for example https://chromium.googlesource.com/native_client/src/native_client/+/master/src/trusted/validator_ragel/instruction_definitions/general_purpose_instructions.def and the other definitions in that directory.

Thank you, since forking process isn’t availaible, does exec of other nexe programs is disallowed too ?

Also is it possible to create user namespace ?

Victor Khimenko

unread,
Sep 9, 2016, 6:54:53 PM9/9/16
to Native Client Discuss
Yes. VERY, VERY few syscalls are available. Basically the bare minimum needed to jumpstart the process and connect to browser. Networking, posix_spawn and so on are usually emulated on top of PPAPI.
 
Also is it possible to create user namespace ?

Good question. We are talking about system which has no concept of "users" thus I'm not even sure what kind of "namespaces" could we talk about.

Basically sitation is simple: cut out Browser and PPAPI - and what you have left is something useful for running tests, nothing more.

There were attempts to expand NaCl to make it more useful as standalone thing - but this was is veeery rudimentary.

lael.c...@gmail.com

unread,
Sep 9, 2016, 7:22:13 PM9/9/16
to Native-Client-Discuss


Le samedi 10 septembre 2016 00:54:53 UTC+2, khim a écrit :

Good question. We are talking about system which has no concept of "users" thus I'm not even sure what kind of "namespaces" could we talk about.
Hemmm, yes, the concept is Unix specific 

Basically sitation is simple: cut out Browser and PPAPI - and what you have left is something useful for running tests, nothing more.

There were attempts to expand NaCl to make it more useful as standalone thing - but this was is veeery rudimentary.
I’m afraid that there are no part wrapped to ppapi in my case. there’s nothing which look like a browser running on the system not even sel_ldr.

Victor Khimenko

unread,
Sep 9, 2016, 8:51:29 PM9/9/16
to Native Client Discuss
Right, but sel_ldr only implement very few syscalls:


Bascially enough to start up the program which then is expected to talk to browser via PPAPI to do high-level things (graphics, networking, etc).

lael.c...@gmail.com

unread,
Sep 9, 2016, 10:08:11 PM9/9/16
to Native-Client-Discuss
Le samedi 10 septembre 2016 02:51:29 UTC+2, khim a écrit :
Right, but sel_ldr only implement very few syscalls:


Bascially enough to start up the program which then is expected to talk to browser via PPAPI to do high-level things (graphics, networking, etc).
I’m using ɴaᴄl glibc… This doesn’t look to be the right list as mprotect() isn’t available in my case, whereas I can perform wrapped call to malloc() or free().

And again, there’s nothing that look like the ᴘᴘᴀᴘɪ in my case.

Victor Khimenko

unread,
Sep 10, 2016, 6:30:27 AM9/10/16
to Native Client Discuss
malloc() and free() don't need mprotect, just mmap() and munmap()
 
And again, there’s nothing that look like the ᴘᴘᴀᴘɪ in my case.

Exactly - and that would limit the things that you could do severely.

lael.c...@gmail.com

unread,
Sep 10, 2016, 8:16:44 AM9/10/16
to Native-Client-Discuss
Le samedi 10 septembre 2016 12:30:27 UTC+2, khim a écrit :
And again, there’s nothing that look like the ᴘᴘᴀᴘɪ in my case.

Exactly - and that would limit the things that you could do severely.
Not that much, since having an unpatched perl5 compiler is possible (though most features of the language don’t work)

Thank you for answering everything.

lael.c...@gmail.com

unread,
Sep 12, 2016, 8:15:10 AM9/12/16
to Native-Client-Discuss
Finally I have a doubt while reading the source code…

Can NaClSysMprotect be called with PROT_EXEC (this would be on valid ɴaᴄl instructions of course) ?
Or does it can only be used with PROT_NONE/PROT_WRITE/PROT_READ meaning mmap() is required for setting pages the executable permission ? (dealing with assembly, I would prefer having to set up less registers for parameters)

Victor Khimenko

unread,
Sep 12, 2016, 11:43:48 AM9/12/16
to Native Client Discuss
You are assuming that you could change NX attributes of a page. Under NaCl it's impossible. Full stop. End of discussion. There are some regions where code resides (RX) and there are other, different, regions where data resides (could be R or RW, never RX or RWX).

That's because of structure of NaCl sandbox on x86 (32-bit) but since this assumption is baked in quite a few places... it's true for x86-64 and arm, too.

mmap would only work in certain limited circumstances - the environment then is supposed to validate code in a binary file first and mark is as "kosher" (maybe problem with that mechanism is how you've achieved your security breach?). Of course you could only mmap such pages in the region where code is expected.

And mprotect does not work at all. You are supposed to use nacl_dyncode_create mostly.

lael.c...@gmail.com

unread,
Sep 12, 2016, 3:38:55 PM9/12/16
to Native-Client-Discuss
Le lundi 12 septembre 2016 17:43:48 UTC+2, khim a écrit :

You are assuming that you could change NX attributes of a page. Under NaCl it's impossible. Full stop. End of discussion. There are some regions where code resides (RX) and there are other, different, regions where data resides (could be R or RW, never RX or RWX).
I didn’t known, it could have validated the code and refuse the permission change if the code fails validation if PROT_EXEC was gaven…

That's because of structure of NaCl sandbox on x86 (32-bit) but since this assumption is baked in quite a few places... it's true for x86-64 and arm, too.

mmap would only work in certain limited circumstances - the environment then is supposed to validate code in a binary file first and mark is as "kosher" (maybe problem with that mechanism is how you've achieved your security breach?). Of course you could only mmap such pages in the region where code is expected.
Do you mean I need to use MAP_FIXED if I use PROT_EXEC ?
Other wise my security breach isn’t that spectacular, I can read and write everywhere it’s allowed, and because of it I only control the 20 functions pointers along their parameter. The problem is I’m toped to to 4 arguments (I mean don’t have the control of functions and I couldn’t found to pass the arguments in registers)
And mprotect does not work at all. You are supposed to use nacl_dyncode_create mostly.
Yeah, with 3 parameters, I think this should be the best candidate… However. I’m unsure it’s included on the native clients build powering google servers that uses python. So maybe I’ll need mmap.
The doc says the *destination should be in a code region but how to I determine if a specific address is a code region (I recognize I don’t fully known what it is). Is it possible for *dest to overwrite existing but no longer used data ?

Can the result contains native validated cpu opcodes were I can jump to directly, or do I need handling each instructions (I don’t how jit works but if I understand correctly the initial purpose of nacl_dyncode_create is to an executable place that contains jit data not native cpu instructions)

Also, same thing as trampoline : at which address to I need to jump in order to perform the NaClSysDyncodeCreate call ? (since I can’t determine default address)

Victor Khimenko

unread,
Sep 20, 2016, 5:59:15 AM9/20/16
to Native Client Discuss
On Mon, Sep 12, 2016 at 9:38 PM, <lael.c...@gmail.com> wrote:
Le lundi 12 septembre 2016 17:43:48 UTC+2, khim a écrit :

You are assuming that you could change NX attributes of a page. Under NaCl it's impossible. Full stop. End of discussion. There are some regions where code resides (RX) and there are other, different, regions where data resides (could be R or RW, never RX or RWX).
I didn’t known, it could have validated the code and refuse the permission change if the code fails validation if PROT_EXEC was gaven…

How?
 

That's because of structure of NaCl sandbox on x86 (32-bit) but since this assumption is baked in quite a few places... it's true for x86-64 and arm, too.

mmap would only work in certain limited circumstances - the environment then is supposed to validate code in a binary file first and mark is as "kosher" (maybe problem with that mechanism is how you've achieved your security breach?). Of course you could only mmap such pages in the region where code is expected.
Do you mean I need to use MAP_FIXED if I use PROT_EXEC ?

Yes. And you need to use it with whitelisted libraries. They must come from "trusted storage" and there are some additional mechanism which ensures that they could be mmaped. I don't know details: it was implemented strictly as on optimization option after I left native client team thus I don't know details. I'm not even 100% sure this mechanism is used or supported outside of browser.
 
Other wise my security breach isn’t that spectacular, I can read and write everywhere it’s allowed, and because of it I only control the 20 functions pointers along their parameter. The problem is I’m toped to to 4 arguments (I mean don’t have the control of functions and I couldn’t found to pass the arguments in registers)

That part I don't understand at all, sorry.
 
And mprotect does not work at all. You are supposed to use nacl_dyncode_create mostly.
Yeah, with 3 parameters, I think this should be the best candidate… However. I’m unsure it’s included on the native clients build powering google servers that uses python.

I'm not 100% sure either. I know that in the past they used nacl-glibc and it could only work with nacl_dyncode_create. If mmap with PROT_EXEC works there at all then it works only for google-supplied prevalidated libraries.
 
So maybe I’ll need mmap.

See above. mmap would ONLY work for libraries which are NOT supplied by untrusted code.
 
The doc says the *destination should be in a code region but how to I determine if a specific address is a code region (I recognize I don’t fully known what it is). Is it possible for *dest to overwrite existing but no longer used data ?

No, that's impossible. There are another syscall nacl_dyncode_delete for that. But it has it's own complications. Your best bet is probably to pick something in first %r15 to %15+256MiB and try it with nacl_dyncode_create.
 
Can the result contains native validated cpu opcodes were I can jump to directly, or do I need handling each instructions (I don’t how jit works but if I understand correctly the initial purpose of nacl_dyncode_create is to an executable place that contains jit data not native cpu instructions)

It's the other way around. It's indended and used by JITs to create new chunks of natively executable code from bytecode. It's also used by glibc to load libraries (although trusted libraries could be loaded with mmap).
 
Also, same thing as trampoline : at which address to I need to jump in order to perform the NaClSysDyncodeCreate call ? (since I can’t determine default address)

You call the function provided by nacl_glibc usually. Or jump to %r15+something.

Reply all
Reply to author
Forward
0 new messages