News for hackers. Stuff that matters.
Re:Open-sourcing gVisor, a sandboxed container runtime by zbentley on Wednesday May 02, 2018 @08:09AM (#16976140)
This seems neat, but every time I read about something of this sort, I am left wondering: what's wrong with the pledge/seccomp model? According to TFA:

> Kernel features like seccomp filters can provide better isolation between the application and host kernel, but they require the user to create a predefined whitelist of system calls.

Isn't that something you'd effectively have to do anyway if you want a sandbox? Like, a sandbox isn't worth that much if you don't define what it can and can't do, no?

I'm far from an expert in this area. It's an honest question, not a veiled criticism.

Re:Open-sourcing gVisor, a sandboxed container runtime by geofft on Wednesday May 02, 2018 @09:43AM (#16976756)
The short version is that pledge and seccomp are implemented in the kernel, so any mistakes there let the attacker win immediately. As a result, they are implemented to be as simple as possible and don't let you express rules like "You can open /etc/ld.so.conf but nothing else in /etc". (Namespaces, which are also in the kernel but are more complex, let you do this sort of thing but definitely have had game-over bugs recently.)

The ideal way to deploy something like this is to stick seccomp/pledge on the userspace sandboxing process, and implement all your complicated policy decisions in that process.

Re:Open-sourcing gVisor, a sandboxed container runtime by notaplumber on Thursday May 03, 2018 @10:26AM (#16986308)
> As a result, they are implemented to be as simple as possible and don't let you express rules like "You can open /etc/ld.so.conf but nothing else in /etc".

OpenBSD's pledgepaths (..soon to be renamed?) will address this, but in general "hoisting" the opening of files before pledge or "sandboxing" is often correct.

The proposed semantics for pledgepath are explicit paths/files are allowed, and must be done before any pledge including "rpath/wpath" or "cpath".

    pledgepath("/etc/aaa", perms)
    pledgepath("/etc/bbb", perms)
Where future open*(2) calls to "/etc/aaa" and "/etc/bbb" succeed, but anything else returns -1/ENOENT.

I suspect Bob Beck's talk at BSDCan 2018 in June will be interesting, to say the least..

http://www.bsdcan.org/2018/schedule/events/968.en.html

Re:Open-sourcing gVisor, a sandboxed container runtime by geofft on Thursday May 03, 2018 @02:00PM (#16988203)
That seems cool, but I hope you don't end up in the place where namespaces ended up where there are too many security-sensitive codepaths in the kernel before you hit the sandbox. :) Unprivileged user namespaces exist but are disabled by default on many distros. It would be a shame for pledge to stay in the use case of "hardening programs that were previously running as root and that was okay" and not in the use case of "sandboxing actually untrusted programs".
Re:Open-sourcing gVisor, a sandboxed container runtime by notaplumber on Thursday May 03, 2018 @02:40PM (#16988583)
OpenBSD has practically pioneered privsep and privdrop designs, including techniques like file descriptor passing. pledge() already works for privileged/unprivileged users/processes and most of the base system is pledged.
Re:Open-sourcing gVisor, a sandboxed container runtime by prattmic on Wednesday May 02, 2018 @08:54AM (#16976392)
There are two primary strengths that gVisor provides over the seccomp model, the second of which you've actually alluded to above.

1. Layered security

While seccomp allows users to limit the attack surface on the kernel, the application is still directly interacting with it and any single bug in an allowed system call will allow compromise. One of the design principles of gVisor is that no single bug should allow compromise of the host system/user data.

By intercepting and handling all application system calls, the gVisor kernel is the first layer of defense against the application. The gVisor kernel itself puts itself inside a seccomp sandbox as a second layer of defense, so if the application gets privilege escalation into the gVisor kernel its attack surface to the host is still limited.

The gVisor kernel seccomp policy [1] is much more restrictive than the system calls we implement. For example, note that "open" and friends are not allowed at all. File system access is mediated by an external agent [2] which does not trust the gVisor kernel, so even a compromised gVisor kernel has no elevated file system access.

2. Ease of use

> > Kernel features like seccomp filters can provide better isolation between the application and host kernel, but they require the user to create a predefined whitelist of system calls.

> Isn't that something you'd effectively have to do anyway if you want a sandbox?

This is something we'd like to challenge with gVisor. gVisor intends to be "secure by default" and configuration-free to the largest extent possible.

gVisor runs and sandboxes arbitrary, unmodified Linux binaries. You don't need to specify a sandbox policy because gVisor safely implements the entire Linux API [3].

Building a sandbox policy can be a difficult and time consuming. It can also be a difficult maintenance burden to update as the application changes over time, especially if you've made modifications to the application to reduce its syscall surface. Additionally, some use-cases wish to sandbox arbitrary workloads, for which a sandbox policy cannot be defined.

With gVisor, we hope to remove this painful step in sandboxing and enable developers to easily sandbox their workloads.

(Note: I work on gVisor.)

[1] https://github.com/google/gvisor/blob/master/runsc/boot/filt...

[2] https://github.com/google/gvisor#file-system-access

[3] Note we don't technically fully implement Linux, as work is ongoing, but missing features are simply unimplemented, not left out for security reasons. See https://github.com/google/gvisor#will-my-container-work-with...

Re:Open-sourcing gVisor, a sandboxed container runtime by zbentley on Wednesday May 02, 2018 @09:00AM (#16976437)
Excellent info. Thanks for the trenchant answer!
Re:Open-sourcing gVisor, a sandboxed container runtime by cat199 on Wednesday May 02, 2018 @08:56AM (#16976411)
Any thoughts on similarity/difference with NetBSD's 'rump' kernel?
Re:Open-sourcing gVisor, a sandboxed container runtime by stphantom on Wednesday May 02, 2018 @09:38AM (#16976710)
Do you mean "rump kernels" or "Rumprun kernel"?

The former is a set of kernel libraries derived from NetBSD, and the latter is a Unikernel built based on the former. gVisor is different in a couple of ways: 1) gVisor is written from scratch using Go for its memory and type safety; 2) gVisor tends to be compatible with Linux which most people use. In theory, gVisor can be restructured as a Unikernel, but we still like to pertain the ring privilege boundary for additional isolation. We are working on an academic paper which will have more details.

I work on gVisor (TL/M and Co-Founder).

Re:Open-sourcing gVisor, a sandboxed container runtime by fpoling on Wednesday May 02, 2018 @01:02PM (#16978955)
Go is not memorysafe unless one restricts the application to single CPU thread. Is it done in gVisor?
Re:Open-sourcing gVisor, a sandboxed container runtime by staticassertion on Wednesday May 02, 2018 @01:11PM (#16979034)
This is true, Go is not memory safe in the presence of data races, and data races are possible in safe Go.

But they're also generally easy to code-review out. There's definitely a huge difference between C and Go, regardless of this one caveat to Go's memory safety guarantees.

They aren't using single threaded Go from what I can see.

Re:Open-sourcing gVisor, a sandboxed container runtime by pcwalton on Wednesday May 02, 2018 @02:18PM (#16979732)
Data races are not easy to "code review out". That is contrary to decades of experience. All you have to do in Go to get a race is to close over a for loop induction variable in a goroutine.

There is not a large difference between C and Go here. In fact, races might be easier in Go than in C, because it's easier for goroutines to close over mutable variables.

Re:Open-sourcing gVisor, a sandboxed container runtime by staticassertion on Wednesday May 02, 2018 @02:41PM (#16979939)
> That is contrary to decades of experience.

In languages like C and C++.

I haven't really seen this as a big problem in Go. I know of one vulnerability involving this, personally. I haven't gone looking though.

Regardless, I think there's a world of difference between C and Go when it comes to memory safety.

Re:Open-sourcing gVisor, a sandboxed container runtime by pcwalton on Wednesday May 02, 2018 @03:03PM (#16980145)
> I haven't really seen this as a big problem in Go.

Go certainly does have problems with data races all the time. Just Google for "golang data race": you'll find many blog posts explaining common data race gotchas in Go.

> Regardless, I think there's a world of difference between C and Go when it comes to memory safety.

Agreed.

Re:Open-sourcing gVisor, a sandboxed container runtime by cyphar on Wednesday May 02, 2018 @08:13AM (#16976172)
It also ignores that seccomp-bpf allows for far more fine-grained rules for syscalls (like specifying that certain bits be cleared or certain arguments be equal to a value). And they're adding more and more features over time to it. I don't get why you would use ptrace (and if you don't use ptrace then you don't need another layer -- just play with the exising OCI support for seccomp and use runc directly).
Re:Open-sourcing gVisor, a sandboxed container runtime by geofft on Wednesday May 02, 2018 @09:21AM (#16976573)
seccomp-bpf doesn't let you follow pointers, so you can't even implement most pledge() restrictions in it. For instance, pledge() always permits open("/etc/localtime"), but at the point seccomp is run, all you know is open(some pointer to userspace).

You could imagine combining seccomp-bpf with some other system that reads the arguments after they've been copied to kernelspace, which is basically Landlock's approach https://lwn.net/Articles/698226/. But I've been personally waiting for something like this since 2011 or so when people were saying seccomp mode 2 should use ftrace, and Landlock itself has been in review (slash argument) for two years. An approach like gVisor works today.

Re:Open-sourcing gVisor, a sandboxed container runtime by cyphar on Wednesday May 02, 2018 @11:24AM (#16977793)
> seccomp-bpf doesn't let you follow pointers, so you can't even implement most pledge() restrictions in it. For instance, pledge() always permits open("/etc/localtime"), but at the point seccomp is run, all you know is open(some pointer to userspace).

This is something that is being worked on (separately but similar to Landlock) in the form of seccomp syscall emulation (I don't remember the actual name of the patchset at the moment but it was proposed a month ago I think). However after talking to some seccomp folks I was told that in theory eBPF maps could be used for this purpose (though I'm not really convinced to be honest).

The real downside of ptrace is that you cannot filter which syscalls you're interested in -- so you pay the price of tracing for every syscall. seccomp doesn't have this problem.

Re:Open-sourcing gVisor, a sandboxed container runtime by geofft on Wednesday May 02, 2018 @11:40AM (#16977986)
You can use SECCOMP_RET_TRACE to kick complicated cases back to the ptracer but handle the easy cases without the slowdown. So you can write a seccomp policy that does something like this pseudocode:

    if syscall == SYS_open:
        if flags == O_RDONLY:
            return (SECCOMP_RET_TRACE, 0)
        else:
            return (SECCOMP_RET_ERRNO, EPERM)
    else if syscall in (SYS_read, SYS_write, ...):
        return (SECCOMP_RET_ALLOW, 0)
    else:
        return (SECCOMP_RET_ERRNO, ENOSYS)
and it would be much much faster than tracing every system call, since most programs call open() rarely and read() and write() very often.

That said, the ptracer's job here is kind of hard, because the kernel still gets an untrusted userspace pointer, and another thread, another process, etc. can modify that memory in between the ptracer okaying it and the kernel getting to it. (See "Argument races" in Tal Garfinkel's 2003 "Traps and Pitfalls" paper.) So you either want the filtering to happen in the kernel after it's been copied to kernelspace (which is Landlock's approach), or do the open from a trusted process and send the fd over (which is I think gVisor's approach).

Re:Open-sourcing gVisor, a sandboxed container runtime by brynet on Thursday May 03, 2018 @05:53PM (#16990325)
> seccomp-bpf doesn't let you follow pointers, so you can't even implement most pledge() restrictions in it.

That's not even the least of it, it's impossible to implement the ratcheting down semantics of pledge() using seccomp-bpf. For example, an initial pledge("stdio rpath") may be later reduced to pledge("stdio").

    "Subsequent calls to pledge can reduce the abilities further, but abilities can never be regained."
Re:Open-sourcing gVisor, a sandboxed container runtime by cyphar on Thursday May 03, 2018 @09:05PM (#16991410)
Personally I don't think pledge()'s semantics are the best idea in the world, especially since all of the restrictions are cleared on exec() if it is permitted IIRC -- so it's useless for sandboxing.
Re:Open-sourcing gVisor, a sandboxed container runtime by brynet on Friday May 04, 2018 @12:21PM (#16995778)
Of course. If you promise "exec", then you're allowed exec. This allows pledge to be in software that otherwise would be impossible, for example text editors, and other shells. It still reduces attack surface, as the shell itself can no longer open sockets, or random device ioctls. The alternative is no protection at all.

https://man.openbsd.org/pledge

See also execpromises, which addresses your issue.

Re:Open-sourcing gVisor, a sandboxed container runtime by dward on Thursday May 03, 2018 @12:40PM (#16987514)
> Package ptrace provides a ptrace-based implementation of the platform interface. This is useful for development and testing purposes primarily, and runs on stock kernels without special permissions.

From:

https://godoc.org/github.com/google/gvisor/pkg/sentry/platfo...

Re:Open-sourcing gVisor, a sandboxed container runtime by cpuguy83 on Wednesday May 02, 2018 @08:51AM (#16976372)
Also potentially have to deal with differences in how the syscalls are implemented from the Linux kernel.