Add file-descriptor as a primitive type?

335 views
Skip to first unread message

chalse...@gmail.com

unread,
Feb 25, 2015, 2:07:23 AM2/25/15
to capn...@googlegroups.com
I'm investigating using capnproto as a machine-local RPC replacing our current protobuf usage (specifically, for Mir - https://launchpad.net/mir).

One of our current annoyances is file-descriptor passing; since it's not a primitive type of protobuf it requires a certain amount of futzing around to make work.

Obviously, file descriptor passing is not broadly portable, cannot be serialised to disc, and can't be sent over the network, which speaks against them being primitive types in the capnproto schema. On the other hand, it seems like sandstorm.io services would in many cases be located on the same machine and could plausibly benefit from being able to exchange file descriptors, and it would obviously be helpful for us.

Would patches adding a fd primitive type be potentially acceptable, and if so what would be the broad outlines - non-Unix behaviour, behaviour over non-AF_UNIX sockets, etc - of something you'd accept?

Farz Hemmati

unread,
Feb 25, 2015, 2:33:25 AM2/25/15
to chalse...@gmail.com, capnproto
You could shove it into a Int32 field if you're not sending it out of the process. If you're using something like sendfd to send it to other processes, I don't know if capnp can do that for you.

If you go the Int32 route, you can use an alias to make it clearer: "using FD = Int32;"

--
You received this message because you are subscribed to the Google Groups "Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email to capnproto+...@googlegroups.com.
Visit this group at http://groups.google.com/group/capnproto.

Christopher James Halse Rogers

unread,
Feb 25, 2015, 4:17:29 AM2/25/15
to Farz Hemmati, chalse...@gmail.com, capnproto
Yeah, we need to send them out of process, so need the full SCM_RIGHTS dance.

Which is why it'd be convenient to have it as primitive type. Sending fds is not terribly difficult, but it's made more awkward by having to do it on a side-channel.

From: Farz Hemmati
Sent: ‎25/‎02/‎2015 18:33
To: chalse...@gmail.com
Cc: capnproto
Subject: Re: [capnproto] Add file-descriptor as a primitive type?

Kenton Varda

unread,
Feb 25, 2015, 6:40:42 AM2/25/15
to chalse...@gmail.com, capnproto
Hi Christopher,

To make this work, you'd need to add a lot of hooks to the serialization layer to keep track of what file descriptors have been added to the message. Whereas with Protobufs it would be a simple matter of implementing special parsing and serialization methods for the new type which do the necessary SCM_RIGHTS tricks, Cap'n Proto doesn't actually have a "parse" or "serialize" step. The only place where you can give your type special treatment is in the getter/setter methods, at which point you don't have a stream to use.

Luckily, something like the hooks you need are already there, to support capabilities. The RPC system needs to know what capabilities are embedded in a message so that it can make them available in the export table for the recipient to call. So, they are stored in a side table -- see `MessageBuilder::getCapTable()` and `MessageReader::initCapTable()`.

If you were willing to roll your own RPC system (rather than using Cap'n Proto's existing one), I think you could actually use these hooks as a way to embed file descriptors today, without any changes to the library.

If you want to use the official RPC system, then it would need to be extended to support a special kind of capability that represents a file descriptor and is passed via SCM_RIGHTS rather than as an entry in the capability export table. While I think this would be neat, and it's something I've actually considered adding before, it's a non-trivial change and needs to be carefully designed. Unfortunately I just don't have time to work on this at the moment, so I'm going to have to say "no" for now, but it's a possibility in the future, perhaps in conjunction with our plans to implement a shared memory transport.

-Kenton

On Tue, Feb 24, 2015 at 10:43 PM, <chalse...@gmail.com> wrote:

--

Christopher James Halse Rogers

unread,
Feb 25, 2015, 8:26:08 PM2/25/15
to Kenton Varda, chalse...@gmail.com, capnproto
On Wed, Feb 25, 2015 at 10:40 PM, Kenton Varda <ken...@sandstorm.io>
wrote:
> Hi Christopher,
>
> To make this work, you'd need to add a lot of hooks to the
> serialization layer to keep track of what file descriptors have been
> added to the message. Whereas with Protobufs it would be a simple
> matter of implementing special parsing and serialization methods for
> the new type which do the necessary SCM_RIGHTS tricks, Cap'n Proto
> doesn't actually have a "parse" or "serialize" step. The only place
> where you can give your type special treatment is in the
> getter/setter methods, at which point you don't have a stream to use.
>
> Luckily, something like the hooks you need are already there, to
> support capabilities. The RPC system needs to know what capabilities
> are embedded in a message so that it can make them available in the
> export table for the recipient to call. So, they are stored in a side
> table -- see `MessageBuilder::getCapTable()` and
> `MessageReader::initCapTable()`.

Ah, ok. I think I see what's happening there.

>
> If you were willing to roll your own RPC system (rather than using
> Cap'n Proto's existing one), I think you could actually use these
> hooks as a way to embed file descriptors today, without any changes
> to the library.

While writing RPC systems is super fun, I was hoping I wouldn't have to
write another one :).

>
> If you want to use the official RPC system, then it would need to be
> extended to support a special kind of capability that represents a
> file descriptor and is passed via SCM_RIGHTS rather than as an entry
> in the capability export table. While I think this would be neat, and
> it's something I've actually considered adding before, it's a
> non-trivial change and needs to be carefully designed. Unfortunately
> I just don't have time to work on this at the moment, so I'm going to
> have to say "no" for now, but it's a possibility in the future,
> perhaps in conjunction with our plans to implement a shared memory
> transport.

It would seem that kj I/O bits could be cleanly extended to support
this? DatagramReceiver already supports receiving AncillaryMessages;
adding write and read support to an AsyncUnix{Input,Output,Io}Stream
wouldn't touch anything else.

If I'm going to do another RPC system it'd be nice if bits of it I
could potentially reuse once you've had the time to do the design
thinking required to fold it into the official RPC.

Failing that I guess I'll get to play around with SOCK_SEQPACKET.

Kenton Varda

unread,
Mar 1, 2015, 8:27:44 PM3/1/15
to Christopher James Halse Rogers, Christopher Halse Rogers, capnproto
On Wed, Feb 25, 2015 at 5:26 PM, Christopher James Halse Rogers <ch...@cooperteam.net> wrote:
It would seem that kj I/O bits could be cleanly extended to support this? DatagramReceiver already supports receiving AncillaryMessages; adding write and read support to an AsyncUnix{Input,Output,Io}Stream wouldn't touch anything else.

On one hand, I would like async-io.h to have this functionality. On the other hand, I'm honestly not sure what the interface should look like.

Defining `AsyncUnix*Stream` seems sad because it's so specific to one kind of transport. It would be nice to have an interface that can be implemented on Win32, and that can also have a simple implementation for inter-thread communications without involving an actual socket.

But defining something abstract seems tricky, too.

Another problem is that defining new "Input", "Output", and "Io" streams means we end up with crazy diamond inheritance (since these presumably subclass the existing Async*Stream), and moreso when we consider the implementation (which would presumably want to share read/write code with the existing AsyncIoStream implementation). Perhaps this argues for adding methods directly to the existing interfaces, similar to how getsockopt/setsockopt/getsockname/getpeername are on there already even though they are specific to sockets.

Another issue is, what is the parameter type to write() to specify fds? Just ints? What if I have an AsyncIoStream that wraps an fd, and that's what I want to send? What if I'm on Windows and I actually want to send a HANDLE? Should we try for that level of abstraction, or is that impractical?

So I'm kind of stuck here and unsure how to proceed. If I saw a good proposal I might agree to it.

-Kenton

Christopher James Halse Rogers

unread,
Mar 1, 2015, 8:44:28 PM3/1/15
to Kenton Varda, Christopher Halse Rogers, capnproto
On Mon, Mar 2, 2015 at 12:27 PM, Kenton Varda <ken...@sandstorm.io>
wrote:
Hm. I would have thought “impractical”, but then a little bit of
googling uncovers that it's perfectly possible to send HANDLEs across
processes, although with a significantly different procedure. I guess
that should have been an obviously enough useful thing to be able to do
to expect it to be supported :).

As long as we can identify process on the remote end of a (local)
connection - and that seems like a reasonable assumption - it looks
like this could be abstracted out.

I guess it'd be compile-time parametrised on native handle type - int
for POSIX, HANDLE for win32? AsyncIoStream could grow a nativeHandle()
accessor...

>
> So I'm kind of stuck here and unsure how to proceed. If I saw a good
> proposal I might agree to it.

I'll continue to give it some thought in the background. No guarantees
I'll come up with a good proposal :)

Tony Arcieri

unread,
Mar 1, 2015, 8:47:33 PM3/1/15
to Kenton Varda, Christopher James Halse Rogers, Christopher Halse Rogers, capnproto
On Sun, Mar 1, 2015 at 5:27 PM, Kenton Varda <ken...@sandstorm.io> wrote:
So I'm kind of stuck here and unsure how to proceed. If I saw a good proposal I might agree to it.

Have services that provide SturdyRefs that abstract away the implementation-specific details? This may require an "I/O server" abstraction, but I feel like adding OS-specific exotica is muddying up capnproto's existing conceptual purity

--
Tony Arcieri

Christopher James Halse Rogers

unread,
Mar 1, 2015, 11:04:28 PM3/1/15
to Kenton Varda, capnproto


On Mon, Mar 2, 2015 at 12:44 PM, Christopher James Halse Rogers
On further thought this might very nearly be ClientHooks; on Windows
you need to modify the message before it goes over the wire (with
information only the IO layer is likely to have) but not do any
additional writing, on POSIX you need to write your message differently
and then modify the message that comes off the wire (with information
only the IO layer has).

On Mon, Mar 2, 2015 at 12:47 PM, Tony Arcieri <bas...@gmail.com> wrote:
> Have services that provide SturdyRefs that abstract away the
> implementation-specific details? This may require an "I/O server"
> abstraction, but I feel like adding OS-specific exotica is muddying
> up capnproto's existing conceptual purity

Yeah. What I want is deeply non-portable. What I (eventually) want is
to write the message:

struct Buffer {
width @0 :UInt32;
height @1 : UInt32;
format @2 : PixelFormat;
handle @3 : Fd; # A linux-specific kernel handle to some GPU memory
that probably isn't CPU-accessible

}

and have the C++ RPC system do all the relevant bits needed to ferry
that file descriptor around.

It's not unreasonable to say “no, we don't want to support that, it's
too different from connecting services across the Internet”.

Kenton Varda

unread,
Mar 6, 2015, 5:04:37 PM3/6/15
to Christopher James Halse Rogers, capnproto
OK, I'm coming around on this.

I do suspect you're not the only one who is going to want to ferry around GPU contexts in this way. Anyone wanting to build a Sandstorm-like sandbox for desktop or mobile apps -- with a Cap'n Proto connection being the only way the app talks to the world -- is likely to need something like this.

I guess that trying to abstract over Win32 is not going to work so well, because the model for transferring handles is totally different there -- it requires that at least one of the two processes involved has complete power over the other, it seems. Not capability-like at all.

I guess what we want is:
- A new variant of AsyncInputStream::read() which also fills in an ArrayPtr<AutoCloseFd>.
- A new variant of AsyncOutputStream::write() which also accepts an ArrayPtr<const int>.

These methods will have default implementations that throw UNIMPLEMENTED exceptions and even the `AsyncStreamFd` implementations of these methods should throw UNIMPLEMENTED when the underlying fd is not a unix socket (much like how getsockopt()/setsockopt()/getsockname()/getpeername() do -- actually, they rely on the fact that KJ_SYSCALL translates ENOTSOCK to UNIMPLEMENTED; I'm not sure what sendmsg()/recvmsg() will do if SCM_RIGHTS isn't supported). It might make sense to have a separate method `bool canExchangeFds()` which people can use to check upfront whether these methods will work.

Once that is in, the Cap'n Proto RPC system could be extended to support these:
- CapDescriptor's union should add a new field `unixFd @6 :UInt32`. The value is not actually the file descriptor, but rather an index into an array of file descriptors sent along with the message.
- We define a special interface type, UnixFd, which has no methods, but whose client type can be passed to `capnp::unwrapUnixFd()` to extract the underlying FD. Behind-the-scenes this is implemented using a special kind of ClientHook. If the capability passed over something other than a unix socket somewhere along the way, unwrapping will fail. (A `tryUnwrapUnixFd()` method should also be provided for people who want to detect this failure.)
- Similarly, `capnp::wrapUnixFd()` turns an FD into a `UnixFd::Client`.

Question: should the SCM_RIGHTS message actually be sent along with the Cap'n Proto message containing the CapDescriptor, or should a second one-byte message be sent immediately after with this payload?
- Problem with a single message: You don't know how many file descriptors may be delivered, so you don't know how large of an array to pass to read(). (The underlying recvmsg() call has this problem. In theory you could probe with MSG_PEEK but you'd have to do so for every message which would hurt performance.)
- Problem with multiple messages: The second message needs some dummy data attached, and peers running an older version of the protocol will be confused when they see this data. Perhaps we could introduce a new field to the rpc `Message` union to use just for this case. Old clients will respond with an `unimplemented` message, but that's OK. This means that the dummy data will be some 32 bytes total instead of 1 but I think we can live with that.

Note that FD passing should be opt-in on the TwoPartyVatNetwork. For Sandstorm, we wont want apps to be able to pass FDs to each other as I believe there are some sandbox breakouts possible if you have apps in independent sandboxes colluding and sharing FDs. (Andy knows more about this.)

Hmm I think we can do this. Chris, are you still interested in working on this?

-Kenton

--
You received this message because you are subscribed to the Google Groups "Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email to capnproto+unsubscribe@googlegroups.com.

David Drysdale

unread,
Mar 9, 2015, 9:04:13 AM3/9/15
to Kenton Varda, Christopher James Halse Rogers, capnproto
On Fri, Mar 6, 2015 at 10:04 PM, Kenton Varda <ken...@sandstorm.io> wrote:
> OK, I'm coming around on this.
>
> I do suspect you're not the only one who is going to want to ferry around
> GPU contexts in this way. Anyone wanting to build a Sandstorm-like sandbox
> for desktop or mobile apps -- with a Cap'n Proto connection being the only
> way the app talks to the world -- is likely to need something like this.

Just to chime in here: Capsicum is another context where FD transfer
over IPC is needed, and it would be nice to be able to do that with
Cap'n Proto.

Capsicum capabilities are file descriptors that reference kernel
objects as usual, but with restricted, fine-grained rights that the
kernel polices. Allowing FD transfer would mean that an individual
component of a compartmentalized application could have specific
objects (files, sockets, timerfds, ...) passed to it, without needing
access to the rest of of the system.

Capsicum is rather OS-specific though (it's only available on FreeBSD
and (currently) as a patchset for Linux), so it's another UNIX-only use case.

[snip]

> Note that FD passing should be opt-in on the TwoPartyVatNetwork. For
> Sandstorm, we wont want apps to be able to pass FDs to each other as I
> believe there are some sandbox breakouts possible if you have apps in
> independent sandboxes colluding and sharing FDs. (Andy knows more about
> this.)

This shouldn't theoretically be a problem for Capsicum capability FDs,
given that the kernel polices what operations are allowed on the FD
according to the rights associated with it.

But I'd be interested to know the details about the sandbox breakouts
you mention, to confirm that practice matches theory...

Kenton Varda

unread,
Mar 9, 2015, 2:55:09 PM3/9/15
to David Drysdale, Andrew Lutomirski, Christopher James Halse Rogers, capnproto
On Mon, Mar 9, 2015 at 6:03 AM, 'David Drysdale' via Cap'n Proto <capn...@googlegroups.com> wrote:
Just to chime in here: Capsicum is another context where FD transfer
over IPC is needed, and it would be nice to be able to do that with
Cap'n Proto.

Indeed! I'm excited about Capsicum.
 
> Note that FD passing should be opt-in on the TwoPartyVatNetwork. For
> Sandstorm, we wont want apps to be able to pass FDs to each other as I
> believe there are some sandbox breakouts possible if you have apps in
> independent sandboxes colluding and sharing FDs. (Andy knows more about
> this.)

This shouldn't theoretically be a problem for Capsicum capability FDs,
given that the kernel polices what operations are allowed on the FD
according to the rights associated with it.

But I'd be interested to know the details about the sandbox breakouts
you mention, to confirm that practice matches theory...

Andy (cc'd) knows more about this.

For one example, consider two processes in separate chroot environments. If they can pass file descriptors to each other, both processes can escape their chroots. The kernel implements chroot by storing, for each process, the root inode for that process, and comparing against it when performing filesystem ops. Unfortunately, an open file descriptor does not contain information about the chroot environment in which it was opened. When sent to another process, the receiving process now has a file descriptor for a file outside of its own chroot, and can freely walk the directory tree all the way up to the filesystem's real physical root.

IIRC, mount namespaces don't have this problem (file descriptors do remember the mount namespace in which they were opened, I think). But in general the kernel wasn't designed for this kind of thing, so there are likely other bugs out there.

-Kenton

Kenton Varda

unread,
Mar 9, 2015, 2:57:20 PM3/9/15
to David Drysdale, Andrew Lutomirski, Christopher James Halse Rogers, capnproto
On Mon, Mar 9, 2015 at 11:54 AM, Kenton Varda <ken...@sandstorm.io> wrote:
For one example, consider two processes in separate chroot environments. If they can pass file descriptors to each other, both processes can escape their chroots. The kernel implements chroot by storing, for each process, the root inode for that process, and comparing against it when performing filesystem ops. Unfortunately, an open file descriptor does not contain information about the chroot environment in which it was opened. When sent to another process, the receiving process now has a file descriptor for a file outside of its own chroot, and can freely walk the directory tree all the way up to the filesystem's real physical root.

To clarify, I'm talking about passing directory FDs. It seems like there are a lot of weird things that can happen when you pass around directory FDs.

-Kenton

Andrew Lutomirski

unread,
Mar 9, 2015, 4:29:43 PM3/9/15
to Kenton Varda, Christopher James Halse Rogers, capnproto
I think it's reasonable to just decide on some a priori max and pass a
big enough buffer. Stack space is sort of free.

> - Problem with multiple messages: The second message needs some dummy data
> attached, and peers running an older version of the protocol will be
> confused when they see this data. Perhaps we could introduce a new field to
> the rpc `Message` union to use just for this case. Old clients will respond
> with an `unimplemented` message, but that's OK. This means that the dummy
> data will be some 32 bytes total instead of 1 but I think we can live with
> that.

Hmm. This seems uglier.

--Andy

>
> Note that FD passing should be opt-in on the TwoPartyVatNetwork. For
> Sandstorm, we wont want apps to be able to pass FDs to each other as I
> believe there are some sandbox breakouts possible if you have apps in
> independent sandboxes colluding and sharing FDs. (Andy knows more about
> this.)

If nothing else, the supervisor can block this.

--Andy

Christopher James Halse Rogers

unread,
Mar 10, 2015, 12:29:21 AM3/10/15
to Kenton Varda, capnproto


On Sat, Mar 7, 2015 at 9:04 AM, Kenton Varda <ken...@sandstorm.io>
wrote:
If you're willing to treat the transport as a pseudo-packet transport
rather than a stream you can just pass a large CMSG buffer and you'll
only get the fds attached to the message as sent. (If I can remember my
experimentation correctly) SCM_RIGHTS messages make the stream act a
bit like a packet transport.

From a look at the serialisation code it looks like it's compatible
with this usage.

It may or may not be worth making this explicit by using a
SOCK_SEQPACKET transport.

>
> Note that FD passing should be opt-in on the TwoPartyVatNetwork. For
> Sandstorm, we wont want apps to be able to pass FDs to each other as
> I believe there are some sandbox breakouts possible if you have apps
> in independent sandboxes colluding and sharing FDs. (Andy knows more
> about this.)
>
> Hmm I think we can do this. Chris, are you still interested in
> working on this?

Yes, still interested. I'll start poking at it.
>> send an email to capnproto+...@googlegroups.com.

David Drysdale

unread,
Mar 10, 2015, 4:50:51 AM3/10/15
to Kenton Varda, Andrew Lutomirski, Christopher James Halse Rogers, capnproto
Thanks for explaining the scenario, that makes sense.

I think Capsicum capability directory FDs should be safe here -- Capsicum
imposes a "beneath-only" behaviour on openat(2) (and disables open(2)), so
paths with ".." or leading "/" are rejected.

[I've also made this behaviour accessible via a new O_BENEATH flag
to openat(2), as it's potentially useful for things other than Capsicum;
current patch suggestion at https://lkml.org/lkml/2015/3/9/407]

David

Kenton Varda

unread,
Mar 10, 2015, 2:20:22 PM3/10/15
to Andrew Lutomirski, Christopher James Halse Rogers, capnproto
On Mon, Mar 9, 2015 at 1:29 PM, Andrew Lutomirski <an...@luto.us> wrote:
I think it's reasonable to just decide on some a priori max and pass a
big enough buffer.  Stack space is sort of free.

What would you set as the a priori max? While, say, 4 would probably be enough for 95% of use cases, I can imagine there being a small number of cases that want hundreds...

-Kenton

Kenton Varda

unread,
Mar 10, 2015, 2:26:20 PM3/10/15
to Christopher James Halse Rogers, capnproto
On Mon, Mar 9, 2015 at 9:29 PM, Christopher James Halse Rogers <ch...@cooperteam.net> wrote:
If you're willing to treat the transport as a pseudo-packet transport rather than a stream you can just pass a large CMSG buffer and you'll only get the fds attached to the message as sent. (If I can remember my experimentation correctly) SCM_RIGHTS messages make the stream act a bit like a packet transport.

Right... but I'm worried that we'd have to make the buffer enormous to avoid breaking some use cases.
 
It may or may not be worth making this explicit by using a SOCK_SEQPACKET transport.

I think this would mean we also need to make the body buffer enormous because by default a message could be up to 64MiB.

Though I suppose we could alternatively use MSG_PEEK to probe the segment table in order to find the message size, which wouldn't increase the total number of syscalls (since currently we issue multiple read()s to read the segment table followed by the content).

I suppose if we were doing that, then we could also use the opportunity to probe the cmsg buffer size?

-Kenton

Kenton Varda

unread,
Mar 10, 2015, 2:31:07 PM3/10/15
to David Drysdale, Andrew Lutomirski, Christopher James Halse Rogers, capnproto
On Tue, Mar 10, 2015 at 1:50 AM, 'David Drysdale' via Cap'n Proto <capn...@googlegroups.com> wrote:
I think Capsicum capability directory FDs should be safe here -- Capsicum
imposes a "beneath-only" behaviour on openat(2) (and disables open(2)), so
paths with ".." or leading "/" are rejected.

[I've also made this behaviour accessible via a new O_BENEATH flag
to openat(2), as it's potentially useful for things other than Capsicum;
current patch suggestion at https://lkml.org/lkml/2015/3/9/407]

This is awesome. FWIW, O_BENEATH seems like it is generally useful for preventing path injection attacks. E.g. various web servers have at various points been vulnerable to using ".." to cause them to serve arbitrary files from the file system. This is something I've had to deal with many times myself, by painstakingly filtering paths for "..", etc. Might be worth mentioning in the man page.

-Kenton

Andrew Lutomirski

unread,
Mar 10, 2015, 2:46:10 PM3/10/15
to Kenton Varda, Christopher James Halse Rogers, capnproto
On Tue, Mar 10, 2015 at 11:25 AM, Kenton Varda <ken...@sandstorm.io> wrote:
> On Mon, Mar 9, 2015 at 9:29 PM, Christopher James Halse Rogers
> <ch...@cooperteam.net> wrote:
>>
>> If you're willing to treat the transport as a pseudo-packet transport
>> rather than a stream you can just pass a large CMSG buffer and you'll only
>> get the fds attached to the message as sent. (If I can remember my
>> experimentation correctly) SCM_RIGHTS messages make the stream act a bit
>> like a packet transport.
>
>
> Right... but I'm worried that we'd have to make the buffer enormous to avoid
> breaking some use cases.

This is silly, but:

#define SCM_MAX_FD 253

I'm not sure Cap'n Proto should rely on that.

>
>>
>> It may or may not be worth making this explicit by using a SOCK_SEQPACKET
>> transport.
>
>
> I think this would mean we also need to make the body buffer enormous
> because by default a message could be up to 64MiB.
>
> Though I suppose we could alternatively use MSG_PEEK to probe the segment
> table in order to find the message size, which wouldn't increase the total
> number of syscalls (since currently we issue multiple read()s to read the
> segment table followed by the content).
>
> I suppose if we were doing that, then we could also use the opportunity to
> probe the cmsg buffer size?

I don't know how well probing the cmsg buffer size works.

--Andy

David Drysdale

unread,
Mar 10, 2015, 4:01:06 PM3/10/15
to Kenton Varda, Andrew Lutomirski, Christopher James Halse Rogers, capnproto
On Tue, Mar 10, 2015 at 6:30 PM, Kenton Varda <ken...@sandstorm.io> wrote:
On Tue, Mar 10, 2015 at 1:50 AM, 'David Drysdale' via Cap'n Proto <capn...@googlegroups.com> wrote:
I think Capsicum capability directory FDs should be safe here -- Capsicum
imposes a "beneath-only" behaviour on openat(2) (and disables open(2)), so
paths with ".." or leading "/" are rejected.

[I've also made this behaviour accessible via a new O_BENEATH flag
to openat(2), as it's potentially useful for things other than Capsicum;
current patch suggestion at https://lkml.org/lkml/2015/3/9/407]

This is awesome. FWIW, O_BENEATH seems like it is generally useful for preventing path injection attacks.

Thanks; feel free to join in on the LKML and indicate support for the idea! 
 
E.g. various web servers have at various points been vulnerable to using ".." to cause them to serve arbitrary files from the file system. This is something I've had to deal with many times myself, by painstakingly filtering paths for "..", etc. Might be worth mentioning in the man page.

Good idea; I sent an update to the man page that obliquely hinted at that:
   "This feature allows applications to be sure that the opened file
    is  within  the  specified directory, regardless of the original
    source of the pathname argument."
but I should make it more explicit. 
  
-Kenton

--
You received this message because you are subscribed to the Google Groups "Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email to capnproto+...@googlegroups.com.

Kenton Varda

unread,
Mar 13, 2015, 4:02:53 PM3/13/15
to David Drysdale, Andrew Lutomirski, Christopher James Halse Rogers, capnproto
On Tue, Mar 10, 2015 at 1:00 PM, 'David Drysdale' via Cap'n Proto <capn...@googlegroups.com> wrote:

On Tue, Mar 10, 2015 at 6:30 PM, Kenton Varda <ken...@sandstorm.io> wrote:
On Tue, Mar 10, 2015 at 1:50 AM, 'David Drysdale' via Cap'n Proto <capn...@googlegroups.com> wrote:
I think Capsicum capability directory FDs should be safe here -- Capsicum
imposes a "beneath-only" behaviour on openat(2) (and disables open(2)), so
paths with ".." or leading "/" are rejected.

[I've also made this behaviour accessible via a new O_BENEATH flag
to openat(2), as it's potentially useful for things other than Capsicum;
current patch suggestion at https://lkml.org/lkml/2015/3/9/407]

This is awesome. FWIW, O_BENEATH seems like it is generally useful for preventing path injection attacks.

Thanks; feel free to join in on the LKML and indicate support for the idea! 

I'm too scared to participate on LKML but maybe Andy will chime in?

-Kenton

Andrew Lutomirski

unread,
Mar 13, 2015, 5:08:52 PM3/13/15
to Kenton Varda, David Drysdale, Christopher James Halse Rogers, capnproto
I chimed in last time. I like it, and I'll chime in again :)

--Andy

arichar...@gmail.com

unread,
Mar 17, 2015, 2:08:36 PM3/17/15
to capn...@googlegroups.com, ch...@cooperteam.net
On Friday, 6 March 2015 22:04:37 UTC, Kenton Varda wrote:
OK, I'm coming around on this.

I do suspect you're not the only one who is going to want to ferry around GPU contexts in this way. Anyone wanting to build a Sandstorm-like sandbox for desktop or mobile apps -- with a Cap'n Proto connection being the only way the app talks to the world -- is likely to need something like this.

I guess that trying to abstract over Win32 is not going to work so well, because the model for transferring handles is totally different there -- it requires that at least one of the two processes involved has complete power over the other, it seems. Not capability-like at all.
 
I'm also very interested in file descriptors being passed over Cap'nProto. I'm currently working on sandboxing applications using Capsicum and being able to pass file descriptors without another open socket would be extremely useful for me.
I need that for e.g. passing shared memory fds or passing a read-only file descriptor for the file that is supposed to be opened. I'm fine with this being UNIX-only since currently I am only sandboxing on Linux and FreeBSD.

Alex
 

Kenton Varda

unread,
Mar 20, 2015, 3:32:32 PM3/20/15
to arichar...@gmail.com, capnproto, Christopher Halse Rogers
Hi Alexander,

I'm excited to hear KDE is planning to use capability-based sandboxing!

How far along is this? Are there docs describing the design, especially how apps will go about obtaining permissions to talk to each other when the user wants them to? We've spent a lot of time thinking about this for Sandstorm and I'd love to compare notes. If you plan to use Cap'n Proto then it may even make sense to share code (not just Cap'n Proto itself, but components of Sandstorm).

-Kenton

--
You received this message because you are subscribed to the Google Groups "Cap'n Proto" group.
To unsubscribe from this group and stop receiving emails from it, send an email to capnproto+...@googlegroups.com.

Kenton Varda

unread,
Apr 21, 2019, 9:27:06 PM4/21/19
to arichar...@gmail.com, capnproto, Christopher Halse Rogers
So it's just over four years later and probably everyone's interests have changed, but I thought I'd mention:


This adds FD passing to Cap'n Proto RPC. You can attach an FD to any capability type, and it will be transmitted along with the capability.

-Kenton
Reply all
Reply to author
Forward
0 new messages