-
Notifications
You must be signed in to change notification settings - Fork 567
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
An exec
directive
#5406
Comments
|
I can write the helpers that sit on either side of the socket. Implementing Regarding messages sent over the socket, each message is serialized using UTF-8 encoded and is preceded with an unsigned 32-bit value containing the message length in native byte order. The messages are the command, followed by arguments (all as strings). |
That format for sending the message didn't work, because it's impossible to distinguish arguments that have a space vs multiple args. I could use quotes, but then real quotes have to be escape, and at that point, I'm just re-inventing a serialisation mechanism. Trying msgpack instead. It's standard, efficient, and has all these issues solved. |
Die you used spaces to separate arguments? The usual way are null bytes. Also note that implementing stuff before discussing and agreeing on them might be waste of time. |
I guess null bytes could work, yes. I'm mostly implementing a proof of concept to validate the ideas so far. |
Also #3315 is doing something similar. |
@WhyNotHugo commented on Oct 10:
So there would be a client running inside the sandbox and a daemon/server Request@WhyNotHugo commented on Oct 10:
Considering the use case, I don't think that performance would be a big That is, maybe the request could be something like this (using
(Alternatively, use It uses a similar format to an HTTP 1.1 request:
That is, the first blank line signifies the end of the environment variables Misc: It is kind of analogous to a call to
FilesystemTo simplify the access control and talking to multiple sandboxes at once, the For example, when running
And when trying to start a new sandbox, the request could be sent by writing
Note: The base path (/run/firestarter/1000) could be owned by root:root and Then the server could read it and run something like ResponseThe response could be similar to an HTTP 1.1 response:
Example (not a real response; this is just for showing the format):
Alternatively, put the error code and message in their own lines to make it
The error codes/messages could be based on either errno.h or on HTTP response IPCOne consideration would be how to return stdout/stderr. Maybe create one pipe
IIRC Arcan does something kind of similar by using input/output Note that this should leave most the burden (such as of connecting the streams) Then when the program exits, the server could write the exit status code (such
No idea about propagating signals though. |
In order to make future use-cases for this socket easier I would split the protocol into two layers: Layer 1:
Layer 2: Depending on Message Type, Message Data is interpreted, parsed, ... For a
If we do responses we use
How do you know the PID? Do we
How much IPC do we want to support and where is the point where it becomes to complex? Not only signals, also open file-descriptors, PIDs, UIDs, filesystem layout, Network, ... IMHO we should exclude IPC from the first implementation as it is to complex. We should focus on a working way to spawn independent programs (i.e. browser, email-client, image viewer, video-player, ...) and only keep the format open for future IPC.
Do we want all this message passing and parsing in C? Or Rust? #4386 Since this is a very isolated feature in the code base, it would be a good feature to bring in rust without touching FFI topics. |
There would be a daemon/server outside the sandbox. Inside the sandbox the client doesn't need to run continuously. For my current experiment, I'm installing my client in The daemon merely listens to a socket that is placed inside the sandbox is a well-known location ( The location outside the sandbox is not important, it only needs to be unique.
Keep in mind that arguments can contain newlines. Regarding stdout/stdin: I'd rather leave it out-of-scope for now. The intended usecase is for Firefox to be able to execute an image viewer, or being able to click on links on any firejail'ed application and this gets passed onto Firefox in its own sandbox. Generally, these are "run and forget" style of execution, and don't care about pipes or exit code. If/when we want to connect stdout/stderr/stdin, the easiest thing would be to send three file descriptors over the socket (as a response to the I haven't kept signals in mind either, but an additional FD to which one can simply write an unsigned 32-bit value (the signal ID itself) might work. Using an FD prevents any PID reuse attacks or similar race conditions too. @rusty-snake Agree on pretty much everything. I'd prefer Rust mostly because I'm rather fluent in it and my C is terrible (as you may have seen). |
Minimal, ugly and unfinish PoC for my Layer 1 protocol using |
I've seen this. You want std::mem::transmute, to convert from one type to another without re-allocating. |
But for that, both data types must have the same length, which they should. |
You should read the first byte (e.g.: |
Sample reading from a socket like that: |
Semantically they are the same. If you speak about heap allocation, there is no. |
Sorry, I meant the first u32. |
There are other corner cases like this, hence the suggestion to read first that u32 first. |
I know them. It's a "Minimal, ugly and unfinish PoC". There are othere things I wanted to focus/check/test. It's a "Minimal, ugly and unfinish PoC". The hole message passing is a PoC. MessageData is 4096 bytes in size, if the arguments of a program are longer than that, buff, if you want to transfer one byte it add 4095 zeros. And that's all on a connection oriented socket, if it would be a Datagram socket, ok, but here. It's a "Minimal, ugly and unfinish PoC".
And how should I do it? From which type should I transmute to which? In rust you can do (from "safer" but still unsafe, to unsafer and more powerful):
You can not |
Actually, raw pointer cast is what I was looking for and couldn't remember 😅 That would be much simpler than the union since it's just a single (unsafe) call. |
And I Actually wanted to use the union in the |
Is your feature request related to a problem? Please describe.
I'd like to allow
firefox
to launchimv
, butimv
should run in its own sandbox (with its own profile).Describe the solution you'd like
An
exec
directive in profiles. So by specifyingexec imv
infirefox.local
firejail will allow launching$PATH/imv
, butimv
will run withimv.profile
and in its own sandbox.Because more
imv.profile
might have a wider set of permissions, this needs to be done outside of firefox's sandbox.For this, I'd propose having a pair of sockets (one inside the sandbox, one another), where a sandbox-external process waits for messages where another process inside the sandbox writes
imv $FILE
. The program inside file would be located in/usr/bin/imv
(shadowing the real one, if necessary), and would pass args without shelling out.Describe alternatives you've considered
D-Bus, but I think it'd be more work for little benefit.
Additional context
There's 485 issues matching results, and I haven't found any mention on an idea like this before. Opening this as a point of discussion, I'd love to hear other ideas.
The text was updated successfully, but these errors were encountered: