New "scallhook" feature. Is is OK to create a proposal?

Robert N. M. Watson rwatson at freebsd.org
Fri Apr 9 13:06:13 UTC 2010


On 8 Apr 2010, at 16:42, Alexander Churanov wrote:

> 2) There are NO plans to create a wrapper for system calls. The feature should be an integral part of the kernel.

To my mind, "wrapper" describes any piece of code that wraps the system call, regardless of whether it's compiled into the kernel, a loadable module, or a process reached via upcalls. If it happens before/after the remainder of the syscall runs, it's a wrapper. Wrappers are not, fundamentally, an evil technology: we use them in countless ways (although only for wrapping syscalls in the cases of things like LD_PRELOADS on libc, Linux ABI emulation, etc) -- what concerns me is using wrappers to enforce security properties that they are unable to enforce correctly.

> 3) There are plans to avoid races by design. The feature is to be implemented into several steps:
> 
>   * Deal with direct arguments only. This is not hard and easy to get right.
>   * Deal with indirect arguments of some calls by copying values. When passing control to the actual syscall, substitute original indirect arguments with copies.
>   * Optimize indirect arguments handling by eliminating extra copies and processing. This is actually hard. It's necessary to mention that this is not an all-or-nothing project. The goal is to provide actually useful and safe features. It's expected that some calls may be left unhookable.

It's worth observing that, although I didn't illustrate exploits for them in the paper, direct arguments, even if they can't be rewritten, are subject to race conditions in wrapper environments. Likewise even if the kernel moves effectively to message-passing, semantic vulnerabilities (mentioned) in the paper may occur. A few examples:

- If an indirect argument includes a path and the wrapper interprets the path with respect to the file system (i.e., looks it up to query whether the target is a symlink), then the interpretation of the same path (mapping to file system objects) can change between wrapper execution and lookup by the kernel.
- If the direct argument is for a file descriptor number, likewise any attempt to look up the file descriptor in the wrapper may be non-atomic with respect to "the kernel's" lookup of the same file descriptor number: the kernel might use a different file than the wrapper.

Hence the design of our pluggable access control framework, the MAC Framework, which provides atomic access to the objects being mediated by a policy. For example, the MLS policy can hook into the file open implementation at a point where it's guaranteed to be performing tests on the same vnode that I/O will be performed on. Likewise, the ability to catch a socket write in the socket code, rather than before the system call runs, so that it's working with socket structures rather than file descriptor numbers. This sort of safety in the presence of concurrency was one of the  motivating factors in choosing to go with a system like the MAC Framework rather than the more popular system call wrapping techniques of the late 1990's. However, there are certain types of security operations that the MAC Framework doesn't support implementing -- for example, privilege escalation of certain types, and substituting object references.

Given the above, could you say a bit more about how these sorts of vulnerabilities are avoided in your system? Argument transformation has value, but only when the underlying policies being implemented are safe. For example, substituting a uid argument to setuid() is "safe", but substituting paths may not be due to features like symlinks, concurrency attacks on the file system layout from another thread, etc.

Robert


More information about the freebsd-arch mailing list