A huge amount of work has been done in this area in the capability
security world.  See for instance the reference to Mark Miller's
thesis in the footnotes of
http://en.wikipedia.org/wiki/Object-capability_model

A short summary of capability security is that checking permissions is
error prone.  Instead, only give out objects you want other pieces to
use.  In essence there is no global namespace, instead your
"supervisor" environment only hands out the capabilities that you've
decided the program that will be run needs.

The canonical example is

cp a.txt b.txt

vs.

cat <a.txt >b.txt

"cp" needs access to the global namespace to find a.txt and b.txt and
permissions are checked, etc.  That is giving cp the authority to
actually modify files other than a.txt and b.txt.

The "cat" example is simple to reason about.  The only objects "cat"
needs are the input and output file descriptors, and the shell in this
case is the supervisor which hands these capabilities to "cat".  It
doesn't need any access to the filesystem and so should not be granted
the ability to get directory listings or open other files that the
user running the program might have access to.

At a language level one of my favorite papers is
http://bracha.org/newspeak-modules.pdf because it addresses the issue
of the top level namespace of a language without making it globally
accessible.

Monty

On Wed, Aug 10, 2011 at 7:35 PM, BGB <cr88...@gmail.com> wrote:
> well, ok, this is currently mostly about my own language, but I figured it
> might be relevant/interesting.
>
> the basic idea is this:
> not all code may be from trusted sources.
> consider, say, code comes from the internet.
>
> what is a "good" way of enforcing security in such a case?
>
>
> first obvious thing seems to be to disallow any features which could
> directly circumvent security.
> say, the code is marked untrusted, and the first things likely to happen
> would be to disable access to things like raw pointers and to the C FFI.
>
> the second thing seems to be the option of moving the code to a local
> toplevel where its ability to see certain things is severely limited.
>
> both of these pose problems:
> simply disabling compiler features may not be sufficient, since there may be
> ways of "using" the language which may be insecure and which go beyond
> simply enabling/disabling certain features in the compiler.
>
> anything still visible may be tampered with, for example, suppose a global
> package is made visible in the new toplevel, and the untrusted code decides
> to define functions in a system package, essentially overwriting the
> existing functions. this is useful, say, for writing program mods, but may
> be a bad things from a security perspective.
>
> a partial option is to give untrusted code its own "shadowed" packages, but
> this poses other problems.
>
> similarly, an exposed API function may indirectly give untrusted code
> "unexpected levels of power" if it, by default, has unhindered access to the
> system, placing additional burden on library code not to perform operations
> which may be exploitable.
>
> consider something trivial like:
>
> function getTopVar(name) { return top[name]; }
>
> which, if exposed under a visibility-based security scheme, and the function
> was part of a library package (with full system access), now suddenly the
> whole security model is dead. essentially it would amount to trying to
> create "water tight" code to avoid potential "security leaks".
>
>
> another security worry is created by, among other things, the semantics of
> object delegation (at least in my language), where assigning through a
> delegated object may in-turn move up and assign the variable in a
> delegated-to object (at the VM level there are multiple assignment operators
> to address these different cases, namely which object will have a variable
> set in...).
>
> this in-turn compromises the ability to simply use delegation to give each
> module its own local toplevel (effectively, the toplevel, and any referenced
> scopes, would need to be cloned, so as to avoid them being modified), ...
>
>
> so, I am left idly wondering:
> could a variation of, say, the Unix security model, be applied at the VM
> level?
>
> in this case, any running code would have, say, a UID (UserID, more refers
> to the origin of the code than to the actual user) and GID (GroupID). VM
> objects, variables, and methods, would themselves (often implicitly) have
> access rights assigned to them (for example: Read/Write/Execute/Special).
>
> possible advantages:
> could be reasonably secure without going through contortions;
> lessens the problem of unintended levels of power;
> reasonably transparent at the language level (for the most part);
> ...
>
> disadvantages:
> have to implement VM level security checking in many places;
> there are many cases where static validation will not work, and where
> runtime checks would be needed (possible performance issue);
> may add additional memory costs (now, several types of memory objects will
> have to remember their owner and access rights, ...);
> it could in some cases require funky attributes "$[mode(0xF51),setuid]
> public function foo() ...";
> ...
>
> uncertain:
> a means could be provided for a program to request "trust" from the user,
> probably in a manner vaguely similar to UAC ("User Access Control") in
> Windows, or the digital-signing requests;
> if one allows for a system similar to digital signing, there is a potential
> risk of forged/stolen keys (effectively requiring user-vigilence), the main
> alternative being that the user authorize modules individually if they
> require certain features (more similar to installing apps on Android);
> ...
>
>
> probable semantics:
> declaration permissions (variable/function/class) are likely to be applied
> in a manner similar to lexical scoping, where a declaration will retain the
> UID in effect at the time of its creation. this will also likely be the case
> for functions and methods. this is also likely to be the model employed for
> static security checks.
>
> run-time security is likely to follow a model similar to dynamic scoping,
> and will likely be applied on a per-thread basis (the current UID and GID
> then being a part of the current VM context).
>
> will likely be applied to:
> functions/methods, which will mostly themselves care about execute
> permissions;
> objects, which will care both about access to themselves, and to individual
> members.
>
> say, object:
> Read, needed to read from any field;
> Write, needed to assign to any field;
> Execute, needed to call any ordinary method (special cases may require RX).
>
> field/method:
> Read, get value from field, get function/method handle;
> Write, assign to field, replace/override method;
> Execute: call method (N/A for fields);
>
> block/lambda:
> Read/Write: N/A
> Execute: call lambda.
>
> probably, for now, I will pack all of this into a 32-bit value, say:
> 12-bits, access flags; 10 bits, owner UID; 10 bits, owner GID.
> setuid/setgid would probably be stored with the modifier flags (currently a
> 64-bit value present in fields/methods/blocks, yes I really do have this
> many modifier flags... sadly...).
>
>
> any thoughts?...
>
>
> _______________________________________________
> fonc mailing list
> fonc@vpri.org
> http://vpri.org/mailman/listinfo/fonc
>

_______________________________________________
fonc mailing list
fonc@vpri.org
http://vpri.org/mailman/listinfo/fonc

Reply via email to