November 04, 2009
Leandro Lucarella wrote:
> Andrei Alexandrescu, el  3 de noviembre a las 17:54 me escribiste:
>> Leandro Lucarella wrote:
>>> Andrei Alexandrescu, el  3 de noviembre a las 16:33 me escribiste:
>>>> SafeD is, unfortunately, not finished at the moment. I want to leave
>>>> in place a stub that won't lock our options. Here's what we
>>>> currently have:
>>>>
>>>> module(system) calvin;
>>>>
>>>> This means calvin can do unsafe things.
>>>>
>>>> module(safe) susie;
>>>>
>>>> This means susie commits to extra checks and therefore only a subset of D.
>>>>
>>>> module hobbes;
>>>>
>>>> This means hobbes abides to whatever the default safety setting is.
>>>>
>>>> The default safety setting is up to the compiler. In dmd by default
>>>> it is "system", and can be overridden with "-safe".
>>> What's the rationale for letting the compiler decide? I can't see nothing
>>> but trouble about this. A module will tipically be writen to be safe or
>>> system, I think the default should be defined (I'm not sure what the
>>> default should be though).
>> The parenthesis pretty much destroys your point :o).
> 
> I guess this is a joke, but I have to ask: why? I'm not sure about plenty
> of stuff, that doesn't mean they are pointless.

Oh, I see what you mean. The problem is that many are as unsure as you are about what the default should be. If too many are unsure, maybe the decision should be left as a choice.

>> I don't think letting the implementation decide is a faulty model.
>> If you know what you want, you say it. Otherwise it means you don't
>> care.
> 
> I can't understand how you can't care. Maybe I'm misunderstanding the
> proposal, since nobody else seems to see a problem here.

It's not a proposal as much as a discussion opener, but my suggestion is
that if you just say module without any qualification, you leave it to
the person compiling to choose the safety level.


Andrei
November 04, 2009
Leandro Lucarella wrote:
> Walter Bright, el  3 de noviembre a las 16:21 me escribiste:
>> Andrei Alexandrescu wrote:
>>> Sketch of the safe rules:
>>>
>>> \begin{itemize*}
>>> \item No @cast@ from a pointer type to an integral type and vice versa
>> replace integral type with non-pointer type.
>>
>>> \item No @cast@ between unrelated pointer types
>>> \item Bounds checks on all array accesses
>>> \item  No  unions  that  include  a reference  type  (array,  @class@,
>>>  pointer, or @struct@ including such a type)
>> pointers are not a reference type. Replace "reference type" with
>> "pointers or reference types".
> 
> Strictly speaking, arrays are not reference types either, right?
> 
> 

Ok, in order to not create confusion, I changed that. Here's the new list with one added item:

\begin{itemize*}
\item No @cast@ from a pointer type to a non-pointer type (e.g.~@int@)
  and vice versa
\item No @cast@ between unrelated pointer types
\item Bounds checks on all array accesses
\item No  unions that include pointer  type, a @class@  type, an array
  type, or a @struct@ embedding such a type
\item No pointer arithmetic
\item Taking the  address of a local is forbidden  (in fact the needed
  restriction is to  not allow such an address to  escape, but that is
  more difficult to track)
\item Cross-module function calls must only go to other @safe@ modules
\item No inline assembler
\item No casting away of @const@, @immutable@, or @shared@
\item No calls to unsafe functions
\end{itemize*}


Andrei
November 04, 2009
Andrei Alexandrescu wrote:
> How can we address that? Again, I'm looking for a simple, robust, extensible design that doesn't lock our options.
> 
> 
> Thanks,
> 
> Andrei
You may want to have a look at the CoreCLR security model (that's used by silverlight / moonlight). It's quite similar to what you've proposed. http://www.mono-project.com/Moonlight2CoreCLR#Security_levels

Btw, is there a reason why safety should be specified at the module level? As we have attributes now that would be a perfect usecase for them: example:

@Safety(Safe)
void doSomething()...

or:
@Safety.Critical
void doSomething()...

where that attribute could be applied to functions, classes, modules, ...

Another related question: Will there be a way to provide different implementations for different safety levels?

version(Safety.Critical)
{
   //Some unsafe yet highly optimized asm stuff here
}
else
{
   //Same thing in safe
}
November 04, 2009
Andrei Alexandrescu wrote:
> Don wrote:
>> Andrei Alexandrescu wrote:
>>> Don wrote:
>>>> Andrei Alexandrescu wrote:
>>
>>> module(safe) is not a comment. We need three types of modules because of the interaction between what the module declares and what the command line wants.
>>>
>>> Let's assume the default, no-flag build allows unsafe code, like right now. Then, module(safe) means that the module volunteers itself for tighter checking, and module(system) is same as module unadorned.
>>>
>>> But then if the user compiles with -safe, module(safe) is the same as module unadorned, and module(system) allows for unchecked operations in that particular module. I was uncomfortable with this, but Walter convinced me that D's charter is not to allow sandbox compilation and execution of malicious code. If you have the sources, you may as well take a look at their module declarations if you have some worry.
>>>
>>> Regardless on the result of the debate regarding the default compilation mode, if the change of that default mode is allowed in the command line, then we need both module(safe) and module(system).
>>
>> When would it be MANDATORY for a module to be compiled in safe mode?
> 
> module(safe) entails safe mode, come hell or high water.
> 
>> If module(safe) implies bound-checking *cannot* be turned off for that module, would any standard library modules be module(safe)?
> 
> I think most or all of the standard library is trusted. But don't forget that std is a bad example of a typical library or program because std interfaces programs with the OS.

I think it's not so atypical. Database, graphics, anything which calls a C library will be the same.
For an app, I'd imagine you'd have a policy of either always compiling with -safe, or ignoring it.
If you've got a general-purpose library, you have to assume some of your users will be compiling with -safe. So you have to make all your library modules safe, regardless of how they are marked. (Similarly, -w is NOT optional for library developers).

That doesn't leave very much.
I'm not seeing the use case for module(safe).
November 04, 2009
Andrei Alexandrescu Wrote:

> Jesse Phillips wrote:
> > On Tue, 03 Nov 2009 23:13:14 -0600, Andrei Alexandrescu wrote:
> > 
> >>> I think the only real option is to have the importer decide if it is trusted.
> >> That can't work. I can't say that stdc.stdlib is trusted no matter how hard I try. I mean free is there!
> > 
> > I would like to disagree here.
> > 
> > void free(void *ptr);
> > 
> > free() takes a pointer. There is no way for the coder to get a pointer in SafeD, compiler won't let them, so the function is unusable by a "safe" module even if the function is imported.
> 
> Pointers should be available to SafeD, just not certain operations with them.
> 
> Andrei

I must have been confused by the statement:

"As long as these pointers are not exposed to the client, such an implementation might be certified to be SafeD compatible1 ."

Found on the article for SafeD. I realize things may change, just sounded like pointers were not ever an option.
November 04, 2009
Andrei Alexandrescu, el  4 de noviembre a las 08:16 me escribiste:
> Michal Minich wrote:
> >Hello Michel,
> >
> >>module (system) name;         // interface: unsafe   impl.: unsafe
> >>module (safe) name;           // interface: safe     impl.: safe
> >
> >I thought that first (unsafe-unsafe) case is currently available just by:
> >
> >module name; // interface: unsafe   impl.: unsafe
> >
> >separating modules to unsafe-unsafe and safe-safe  has no usefulness - as those modules could not interact, specifically you need modules that are implemented by unsafe means, but provides only safe interface, so I see it as:
> >
> >module name;                  // interface: unsafe   impl.: unsafe
> >module (system) name;         // interface: safe     impl.: unsafe
> >module (safe) name;           // interface: safe     impl.: safe
> >
> >so you can call system modules (io, network...) from safe code.

I think safe should be the default, as it should be the most used flavor in user code, right? What about:

module s;             // interface: safe     impl.: safe
module (trusted) t;   // interface: safe     impl.: unsafe
module (unsafe) u;    // interface: unsafe   impl.: unsafe

* s can import other safe or trusted modules (no unsafe for s).
* t can import any kind of module, but he guarantee not to corrupt your
  memory if you use it (that's why s can import it).
* u can import any kind of modules and makes no guarantees (C bindings
  use this).

> That's a pretty clean design. How would it interact with a -safe command-line flag?

I'll use safe by default. If you want to use broken stuff (everything
should be correctly marked as safe (default), trusted or unsafe) and let
it compile anyway, add a compiler flag -no-safe (or whatever).

But people should never use it, unless you are using some broken library or you are to lazy to mark your modules correctly.


Is this too crazy?

-- 
Leandro Lucarella (AKA luca)                     http://llucax.com.ar/
----------------------------------------------------------------------
GPG Key: 5F5A8D05 (F8CD F9A7 BF00 5431 4145  104C 949E BFB6 5F5A 8D05)
----------------------------------------------------------------------
El discman vuelve locos a los controles, te lleva a cualquier lugar.
Ajústense pronto los cinturones, nos vamos a estrellar.
Evidentemente, no escuchaste el speech,
que dio la azafata, antes de despegar.
November 04, 2009
jpf wrote:
> Andrei Alexandrescu wrote:
>> How can we address that? Again, I'm looking for a simple, robust,
>> extensible design that doesn't lock our options.
>>
>>
>> Thanks,
>>
>> Andrei
> You may want to have a look at the CoreCLR security model (that's used
> by silverlight / moonlight). It's quite similar to what you've proposed.
> http://www.mono-project.com/Moonlight2CoreCLR#Security_levels

I don't have much time right now, but here's what a cursory look reveals:

====================
 Security levels

The CoreCLR security model divide all code into three distinct levels: transparent, safe-critical and critical. This model is much simpler to understand (and implement) than CAS (e.g. no stack-walk). Only a few rules can describe much of it.
====================

The keywords "security" and "stack-walk" give it away that this is a matter of software security, not language safety. These are quite different.

> Btw, is there a reason why safety should be specified at the module
> level? As we have attributes now that would be a perfect usecase for
> them: example:
> 
> @Safety(Safe)
> void doSomething()...
> 
> or:
> @Safety.Critical
> void doSomething()...
> 
> where that attribute could be applied to functions, classes, modules, ...
> 
> Another related question: Will there be a way to provide different
> implementations for different safety levels?
> 
> version(Safety.Critical)
> {
>    //Some unsafe yet highly optimized asm stuff here
> }
> else
> {
>    //Same thing in safe
> }

I think it muddies things too much to allow people to make safety decisions at any point (e.g., I'm not a fan of C#'s unsafe).

Andrei
November 04, 2009
Don wrote:
> Andrei Alexandrescu wrote:
>> Don wrote:
>>> Andrei Alexandrescu wrote:
>>>> Don wrote:
>>>>> Andrei Alexandrescu wrote:
>>>
>>>> module(safe) is not a comment. We need three types of modules because of the interaction between what the module declares and what the command line wants.
>>>>
>>>> Let's assume the default, no-flag build allows unsafe code, like right now. Then, module(safe) means that the module volunteers itself for tighter checking, and module(system) is same as module unadorned.
>>>>
>>>> But then if the user compiles with -safe, module(safe) is the same as module unadorned, and module(system) allows for unchecked operations in that particular module. I was uncomfortable with this, but Walter convinced me that D's charter is not to allow sandbox compilation and execution of malicious code. If you have the sources, you may as well take a look at their module declarations if you have some worry.
>>>>
>>>> Regardless on the result of the debate regarding the default compilation mode, if the change of that default mode is allowed in the command line, then we need both module(safe) and module(system).
>>>
>>> When would it be MANDATORY for a module to be compiled in safe mode?
>>
>> module(safe) entails safe mode, come hell or high water.
>>
>>> If module(safe) implies bound-checking *cannot* be turned off for that module, would any standard library modules be module(safe)?
>>
>> I think most or all of the standard library is trusted. But don't forget that std is a bad example of a typical library or program because std interfaces programs with the OS.
> 
> I think it's not so atypical. Database, graphics, anything which calls a C library will be the same.

I still think the standard library is different because it's part of the computing base offered by the language. A clearer example is Java, which has things in its standard library that cannot be done in Java. But I agree there will be other libraries that need to interface with C.

> For an app, I'd imagine you'd have a policy of either always compiling with -safe, or ignoring it.

I'd say for an app you'd have a policy of marking most modules as safe. That makes it irrelevant what compiler switch is used and puts the onus in the right place: the module.

> If you've got a general-purpose library, you have to assume some of your users will be compiling with -safe. So you have to make all your library modules safe, regardless of how they are marked. (Similarly, -w is NOT optional for library developers).

If you've got a general-purpose library, you try what any D codebase should try: make most of your modules safe and as few as possible system.

> That doesn't leave very much.
> I'm not seeing the use case for module(safe).

I think you ascribe to -safe what module(safe) should do. My point is that -safe is inferior, just some low-level means of choosing a default absent other declaration. The "good" way to go about it is to think your design in terms of safe vs. system modules.


Andrei
November 04, 2009
Jesse Phillips wrote:
> Andrei Alexandrescu Wrote:
> 
>> Jesse Phillips wrote:
>>> On Tue, 03 Nov 2009 23:13:14 -0600, Andrei Alexandrescu wrote:
>>>
>>>>> I think the only real option is to have the importer decide if it is
>>>>> trusted.
>>>> That can't work. I can't say that stdc.stdlib is trusted no matter how
>>>> hard I try. I mean free is there!
>>> I would like to disagree here.
>>>
>>> void free(void *ptr);
>>>
>>> free() takes a pointer. There is no way for the coder to get a pointer in SafeD, compiler won't let them, so the function is unusable by a "safe" module even if the function is imported.
>> Pointers should be available to SafeD, just not certain operations with them.
>>
>> Andrei
> 
> I must have been confused by the statement:
> 
> "As long as these pointers are not exposed to the client, such an implementation might be certified to be SafeD compatible1 ."
> 
> Found on the article for SafeD. I realize things may change, just sounded like pointers were not ever an option.

Yes, sorry for not mentioning that. It was Walter's idea to allow restricted use of pointers in SafeD. Initially we were thinking of banning pointers altogether.

Andrei
November 04, 2009
Andrei Alexandrescu wrote:
> jpf wrote:
>> You may want to have a look at the CoreCLR security model (that's used by silverlight / moonlight). It's quite similar to what you've proposed. http://www.mono-project.com/Moonlight2CoreCLR#Security_levels
> 
> I don't have much time right now, but here's what a cursory look reveals:
> 
> ====================
>  Security levels
> 
> The CoreCLR security model divide all code into three distinct levels:
> transparent, safe-critical and critical. This model is much simpler to
> understand (and implement) than CAS (e.g. no stack-walk). Only a few
> rules can describe much of it.
> ====================
> 
> The keywords "security" and "stack-walk" give it away that this is a matter of software security, not language safety. These are quite different.

What i wanted to refer to are the levels "Transparent", "Critical" and "Safe Critical", which work exactly as "safe", "system" and "Yeah, I do unsafe stuff inside, but safe modules can call me no problem". The implementation and use case might be different, but the meaning is the same. There's nothing unique in the .net implementation, I just though you may want to have a look at how others solved a similiar problem.