Skip to content
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

Port to linux #7

Closed
rain-1 opened this issue Jan 26, 2019 · 12 comments
Closed

Port to linux #7

rain-1 opened this issue Jan 26, 2019 · 12 comments

Comments

@rain-1
Copy link

rain-1 commented Jan 26, 2019

These are the changes needed to make the program build and run on linux

rain-1@0b2ef0a

@kristapsdz
Copy link
Owner

Hi, please read the Portability section on the main README. This is not a viable port, as it does not have any security mitigations.

@CameronNemo
Copy link

You could try to use aa_change_hat(2) to mimic the unveil and pledge calls. Of course, that involves defining AppArmor policy based on the pledge/unveil calls in the C code...

Perhaps @kristapsdz may want to draft up some pointers to where that policy is in the project, considering he knows what the "specific running modes for the super-user" are as well as how and when they should be used.

@kristapsdz
Copy link
Owner

Show Me The Code! Show Me The Code! (Or is it, "Show Me The Policy"!)

@CameronNemo
Copy link

Yeah I went ahead and looked at the pledge and unveil calls as well as the documentation for them. Some of the bits may be hard to replicate with AppArmor and might be better suited to a mount namespace. The gist is instead of unveiling a path you would bind mount that file into the namespace root prior to unshare()'ing. Or perhaps one could just grab all of the fds then drop into the namespace.

@shawnanastasio
Copy link

I think a better approach is using a custom seccomp-bpf filter that traps on open(2) calls and sends them over an AF_UNIX socket to a non-sandboxed process which can verify that the path is allowed, complete the open(2) call, and pass an fd back over using ancillary data messages. This is also the approach taken by chromium.

I may try my hand at an implementation of this in the upcoming days.

@shawnanastasio
Copy link

@kristapsdz, what is the project's policy on LGPL-2.1 dependencies? libseccomp would be useful for implementing the sandboxing mechanism I discussed in my previous comment, but it's not BSD licensed.

If the project is against LGPL dependencies, it is possible to write a seccomp filter by hand and avoid the need for a dependency at all.

@shawnanastasio
Copy link

shawnanastasio commented Feb 25, 2019

I've started work on a port that doesn't add any dependencies, available here.

So far, only minimal pledge(2) emulation for the stdio and unix promises are implemented, but the groundwork required to implement the rest is there.

You may notice that it's already comically large (~1K LoC!). Unfortunately this is just a result of the complexity of seccomp-bpf. If anybody has any suggestions for simplifying things, I'm all ears.

@CameronNemo
Copy link

I don't think most Linux users will care about the lgpl dependency. The port will live out of tree regardless from what I understand.

@rain-1
Copy link
Author

rain-1 commented Feb 25, 2019

I will relay some comments I got about the seccomp approach:

This works fine for pledge.
This isn't a replacement for unveil though, it's just a guarded open. unveil applies to everything that takes a path (e.g. stat). Doing unveil in userspace means you need to worry about symlinks and deleted files and more. You need to reimplement the whole filesystem layer.
You should look into mount namespaces instead.

@rain-1
Copy link
Author

rain-1 commented Feb 25, 2019

I think this is some good feedback, the seccomp tool seems appropriate to implement the pledge part but not the unveil part. We are very limited with the tools we have for this on linux since since patching the kernel isn't an option but hopefully the suggestion of using mount namespaces will be valuable.

@shawnanastasio
Copy link

I will relay some comments I got about the seccomp approach:

I would agree that a raw seccomp-bpf filter alone is not very useful for implementing unveil, but I'd argue that my approach of using seccomp + a broker process can cover all of those cases. I'll address each point individually.

it's just a guarded open. unveil applies to everything that takes a path (e.g. stat)

This is not true. As it stands, the filter denies every syscall except those that are explicitly allowed or trapped. Right now, only open(2) is trapped and emulated, but the same approach will work for stat(2) and the rest of them. There is no possibility for bypassing the filter by using a syscall that I haven't implemented path sanitization for, since the default filter behavior for unimplemented calls is to simply deny them.

Doing unveil in userspace means you need to worry about symlinks and deleted files and more.

I'll have to look into this, but since the actual path handling is still being done by the kernel with the
native system calls in the broker process, I don't think this is much of an issue. The broker process may have to be modified to deny paths that symlink outside of an unveil'd region, though (I'm not sure how oBSD does this, I'll have to look into that).

You need to reimplement the whole filesystem layer.

See above. I don't think this is necessarily true.

That being said, I'm certainly not against the idea of a mount namespace. I'll look into both approaches. If anybody familiar with mount namespaces would like to chime in or contribute some code, that'd be great.

@kristapsdz
Copy link
Owner

I give up on the security fight and just put in a compatibility shim.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants