www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Question and proposal: Can D be used to compile and run untrusted

reply Moamen Abdelsattar <moemen0101 gmail.com> writes:
I've recently known that D functions can be marked as ` safe`, 
which makes all unsafe operations unallowed inside the function, 
my question is: Can this feature be used to compile and run 
untrusted D code safely?
I mean: Let's say We have a program written in D or C, and we 
want to allow the user to extend the program by writing plug-ins 
and compiling them into dynamic libraries (like notepadd++ 
plug-ins).
Now the plug-in can access all system calls and can do something 
malicious, but what if the plug-in is written in D and we have 
something like `-forceSafe` compiler flag (which is the proposal) 
that will force every function written by the user to be ` safe`. 
Now, the user can only import the application's API and use it to 
perform functions and can't access the system directly. Is that 
true?
Dec 04 2021
next sibling parent reply Dukc <ajieskola gmail.com> writes:
On Saturday, 4 December 2021 at 11:33:21 UTC, Moamen Abdelsattar 
wrote:
 I've recently known that D functions can be marked as ` safe`, 
 which makes all unsafe operations unallowed inside the 
 function, my question is: Can this feature be used to compile 
 and run untrusted D code safely?
 I mean: Let's say We have a program written in D or C, and we 
 want to allow the user to extend the program by writing 
 plug-ins and compiling them into dynamic libraries (like 
 notepadd++ plug-ins).
 Now the plug-in can access all system calls and can do 
 something malicious, but what if the plug-in is written in D 
 and we have something like `-forceSafe` compiler flag (which is 
 the proposal) that will force every function written by the 
 user to be ` safe`. Now, the user can only import the 
 application's API and use it to perform functions and can't 
 access the system directly. Is that true?
No, ` safe` isn't suitable for that. For two reasons: 1: It only guards against memory integrity violations, not against otherwise malicious system calls. You can ` safe`ly delete everything in the home or "my documents" directory, or trigger a fork bomb. To prevent this, you have to not link any system calls to the untrusted module - which is perfectly doable, though. 2: The more difficult problem. It is not bug-free enough. ` safe` aims to be foolproof enough to prevent corrupting memory accidently, and it has enough challenge in that. It is more difficult to be so reliable that the memory could not be corrupted even by determined attempts. Perhaps in the far future it can do that, but not now nor anytime soon. The same can be accomplished by sandboxing the compiled binary somehow though. For example, D program compiled to WebAssembly cannot corrupt the web browser running it, just like no WebAssembly program can (modulo browser vulnerabilities).
Dec 04 2021
parent Moamen Abdelsattar <moemen0101 gmail.com> writes:
On Saturday, 4 December 2021 at 12:18:23 UTC, Dukc wrote:
 The same can be accomplished by sandboxing the compiled binary 
 somehow though. For example, D program compiled to WebAssembly 
 cannot corrupt the web browser running it, just like no 
 WebAssembly program can (modulo browser vulnerabilities).
I'm aware of that way of sandboxing, but it's not as efficient. I mean you can't call the functions inside the plug-in directly with C calling convention. If you need to call it thousands of times, the application will be markedly slower. Also I think that passing structures or objects with overriden virtual functions to the application will be a difficult problem due to ABI incompitability.
 1: It only guards against memory integrity violations, not 
 against otherwise
 malicious system calls.
Yes but I think memory-safe code can't do anything outside the API. Malicious C code (that is not linked to system calls) can still use pointer arthmetric to make system calls by address, use inline assembly to make them, or write to data segment to change the application's behaviour in a certain way. Making the untrusted code memory-safe will also make it safe to execute if it's only linked to a secure API.
 2: The more difficult problem. It is not bug-free enough.
That's disappointing, but at least it can make malicious code more difficult to write; it's better that nothing, and vulnerabilities can be fixed by time.
Dec 04 2021
prev sibling next sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Saturday, 4 December 2021 at 11:33:21 UTC, Moamen Abdelsattar 
wrote:
 I've recently known that D functions can be marked as ` safe`, 
 which makes all unsafe operations unallowed inside the function
You can also mark functions trusted, which allows all operations inside but pretends to be safe from the outside. So even if safe worked for what you want, it is too easy to bypass to actually rely on it. Malicious users will just make all their naughty code as trusted.
Dec 04 2021
parent reply Moamen Abdelsattar <moemen0101 gmail.com> writes:
On Saturday, 4 December 2021 at 13:53:43 UTC, Adam D Ruppe wrote:
 You can also mark functions  trusted, which allows all 
 operations inside but pretends to be safe from the outside.
Yeah but I'm assuming the compiler will force every function written by the user to be ` safe`, so the user can't mark any code ` trusted`, only the API can.
Dec 04 2021
parent Paul Backus <snarwin gmail.com> writes:
On Saturday, 4 December 2021 at 14:08:16 UTC, Moamen Abdelsattar 
wrote:
 On Saturday, 4 December 2021 at 13:53:43 UTC, Adam D Ruppe 
 wrote:
 You can also mark functions  trusted, which allows all 
 operations inside but pretends to be safe from the outside.
Yeah but I'm assuming the compiler will force every function written by the user to be ` safe`, so the user can't mark any code ` trusted`, only the API can.
Even if the compiler could do this, it would not protect you from malicious code in a DLL, because an attacker could simply provide their own malicious DLL that was created using a different compiler. To really protect against this threat, you would have to do something like embed the compiler in the host application, load the plugin as source code, compile it with the embedded compiler, and then load the resulting DLL. Of course, if you're going to all that trouble, you may be better off embedding an interpreter for a scripting language like Lua, which is designed for this kind of use-case.
Dec 04 2021
prev sibling next sibling parent Kagamin <spam here.lot> writes:
If memory serves well, long ago there was an idea of a `-safe` 
compiler switch that would restrict the language to only safe 
subset, but it was abandoned.
Dec 06 2021
prev sibling next sibling parent ManKey <mensikovk817 gmail.com> writes:
On Saturday, 4 December 2021 at 11:33:21 UTC, Moamen Abdelsattar 
wrote:
 Now the plug-in can access all system calls and can do 
 something malicious, but what if the plug-in is written in D 
 and we have something like `-forceSafe` compiler flag (which is 
 the proposal) that will force every function written by the 
 user to be ` safe`. Now, the user can only import the 
 application's API and use it to perform functions and can't 
 access the system directly. Is that true?
You can use pure attribute. But it will still be by `cast` to break it
Dec 07 2021
prev sibling parent reply Brian Callahan <bcallah openbsd.org> writes:
On Saturday, 4 December 2021 at 11:33:21 UTC, Moamen Abdelsattar 
wrote:
 I've recently known that D functions can be marked as ` safe`, 
 which makes all unsafe operations unallowed inside the 
 function, my question is: Can this feature be used to compile 
 and run untrusted D code safely?
 I mean: Let's say We have a program written in D or C, and we 
 want to allow the user to extend the program by writing 
 plug-ins and compiling them into dynamic libraries (like 
 notepadd++ plug-ins).
 Now the plug-in can access all system calls and can do 
 something malicious, but what if the plug-in is written in D 
 and we have something like `-forceSafe` compiler flag (which is 
 the proposal) that will force every function written by the 
 user to be ` safe`. Now, the user can only import the 
 application's API and use it to perform functions and can't 
 access the system directly. Is that true?
What you want appears to be similar to the pledge(2) system call from OpenBSD: https://man.openbsd.org/pledge.2 It is available on all D compilers, but only when running your code on OpenBSD. ~Brian
Dec 07 2021
parent max haughton <maxhaton gmail.com> writes:
On Tuesday, 7 December 2021 at 19:31:46 UTC, Brian Callahan wrote:
 On Saturday, 4 December 2021 at 11:33:21 UTC, Moamen 
 Abdelsattar wrote:
 [...]
What you want appears to be similar to the pledge(2) system call from OpenBSD: https://man.openbsd.org/pledge.2 It is available on all D compilers, but only when running your code on OpenBSD. ~Brian
Interesting. I must get round to trying OpenBSD soon. What tracing infrastructure exists on OpenBSD?
Dec 07 2021