3 ms·
I think there is an opportunity here for language design. I should be able to import a library and mark it as nothing but computation, or as network only no fil
by lanstin 4y ago
I think there is an opportunity here for language design. I should be able to import a library and mark it as nothing but computation, or as network only no file system, or file system only but no network, and have the language itself enforce that guarantee. I believe it has to be at the language/compilation level as executable segments can always just trap into the OS.
If there were some syntax, then you could even specify the particular network endpoints or file system paths allowed.
It is sort of old fashioned, a sort of dynamic scoping of access context, but would be better than you call a shared library which starts up some threads with network connections all invisible to you.
There would be some idea of the main function and spawning threads or green threads would also need to specify what that thread can do, a subset of what the creating thread can do.
- PaulDavisThe1st 4y ago> I should be able to import a library and mark it as nothing but computation, or as network only no file system, or file system only but no network, and have the language itself enforce that guarantee. There is no sheriff to enforce this guarantee. There's nobody come to save you (us) from ourselves. You can try to build walls around things, but meanwhile other people are building ladders (or digging tunnels). It gets worse though. Virtuality, whether via literal VMs or COWbuilder-style containers, means that defining what is means to access certain resources is hard to do. For the most part, this resolves nicely (i.e. you almost always have less significant access to "the real world" than you might believe), but it's not trivial to determine.
- marcosdumay 4y agoIt's funny to read those threads of people saying how nice would it be to have, or that things are impossible, and yet those same things are there in Haskell since forever.
- PaulDavisThe1st 4y agoSo tell me, I run a Haskell program inside a VM and it accesses the root of the filesystem. What happens? It accesses the network interface, what happens? The point is that the code, at runtime, cannot determine what context it is running in, and it may be entirely appropriate for it to do certain things, or highly inappropriate, depending on that context. It has nothing to do with language.
- JonChesterfield 4y agoPut the library in a different process and seccomp it
- tremon 4y agoYes, this, exactly. In our current operating systems models, the process is the most granular resource that we can confine. The OS model doesn't allow for more fine-grained resource control than that, so code with different authorization scopes should run in different processes. Maybe we need a different OS/process model?
- bhawks 4y agoThe fuchsia os has a very interesting security model in this respect : https://fuchsia.dev/fuchsia-src/concepts/principles/secure https://fuchsia.dev/fuchsia-src/concepts/principles/secure The tldr being a very powerful and lightweight sandboxing mechanism complemented with a OS mediated ipc layer wrapped by language idiomatic libraries. Unfortunately fuchsia is taking it's own sweet time to play out.
- gavinhoward 4y agoAuthor here. My language will have some sort of what you are talking about.
- lanstin 4y agoYeah, the replies all sort of show ways of wedging this in, but why not add it to the language/compiler? It would be very useful, and also interesting to see attacks against it. It would also be interesting to see how this sort of dynamic scoped feature would be implemented these days. (In old LISP stuff, you used to be able to do like: (with-stdout-redirected-to-printer (whatever-func etc)) and all the stuff whatever-func called would print but it would be redirected to printer.
- gavinhoward 4y agoThat sort of redirection will absolutely be possible, but that won't be the language-level thing my language will support. In my language, there are packages. You might have a left-pad package, for example. (Okay, it's a bad example, but whatever.) The programmer/user gives permissions to packages at the package level, so you might give the left-pad no permissions at all except for allocating memory (for generating a formatted string), which means something else will need to do the output. These permissions can include anything, like being able to use other packages, network access, filesystem access, etc. Static dependencies will be the first line of defense, but if something need dynamic access, say access to specific files such as `/dev/urandom` or `$HOME/.config/<program>/config.txt`, there will be a dynamic way to give permission. This dynamic way will probably serve a lot of the use case you suggest. This will be at the compiler IR level, by the way. The build system of dependencies might otherwise be able to get around it. But with IR, you can tell the dependency's build system to generate the LLVM-like IR for its code, and its build is done and can have no more influence. Then without using any of the dependency's code, you can then specialize the IR while inserting permission checks. You can even use this to generate cross-platform "binaries". The "binaries" would just be a tarball of IR. Most IR would be used for any platform, but some would be platform-specific. If you include all of the platform-specific IR with the platform-independent stuff, you can then ship that tarball to any machine, which, on trying to run it for the first time, will realize it needs to be specialized for that machine. This includes inserting permission checks based on the policy for that machine. Yes, it will be that powerful. My main concern is that it will be too powerful and thus have bad user experience or a steep learning curve. UX matters. I don't have it solved yet, but I'm trying.