Re: [PATCH v5 1/6] fs: Add support for an O_MAYEXEC flag on openat2(2)

2020-05-12 Thread Christian Heimes
On 12/05/2020 23.05, Kees Cook wrote:
> On Tue, May 05, 2020 at 05:31:51PM +0200, Mickaël Salaün wrote:
>> When the O_MAYEXEC flag is passed, openat2(2) may be subject to
>> additional restrictions depending on a security policy managed by the
>> kernel through a sysctl or implemented by an LSM thanks to the
>> inode_permission hook.  This new flag is ignored by open(2) and
>> openat(2).
>>
>> The underlying idea is to be able to restrict scripts interpretation
>> according to a policy defined by the system administrator.  For this to
>> be possible, script interpreters must use the O_MAYEXEC flag
>> appropriately.  To be fully effective, these interpreters also need to
>> handle the other ways to execute code: command line parameters (e.g.,
>> option -e for Perl), module loading (e.g., option -m for Python), stdin,
>> file sourcing, environment variables, configuration files, etc.
>> According to the threat model, it may be acceptable to allow some script
>> interpreters (e.g. Bash) to interpret commands from stdin, may it be a
>> TTY or a pipe, because it may not be enough to (directly) perform
>> syscalls.  Further documentation can be found in a following patch.
> 
> You touch on this lightly in the cover letter, but it seems there are
> plans for Python to restrict stdin parsing? Are there patches pending
> anywhere for other interpreters? (e.g. does CLIP OS have such patches?)
> 
> There's always a push-back against adding features that have external
> dependencies, and then those external dependencies can't happen without
> the kernel first adding a feature. :) I like getting these catch-22s
> broken, and I think the kernel is the right place to start, especially
> since the threat model (and implementation) is already proven out in
> CLIP OS, and now with IMA. So, while the interpreter side of this is
> still under development, this gives them the tool they need to get it
> done on the kernel side. So showing those pieces (as you've done) is
> great, and I think finding a little bit more detail here would be even
> better.

Hi,

Python core dev here.

Yes, there are plans to use feature for Python in combination with
additional restrictions. For backwards compatibility reasons we cannot
change the behavior of the default Python interpreter. I have plans to
provide a restricted Python binary that prohibits piping from stdin,
disables -c "some_code()", restricts import locations, and a couple of
other things. O_MAYEXEC flag makes it easier to block imports from
noexec filesystems.

My PoC [1] for a talk [2] last year is inspired by IMA appraisal and a
previous talk by Mickaël on O_MAYEXEC.

Christian

[1] https://github.com/zooba/spython/blob/master/linux_xattr/spython.c
[2]
https://speakerdeck.com/tiran/europython-2019-auditing-hooks-and-security-transparency-for-cpython


Re: [PATCH v3 0/5] Add support for RESOLVE_MAYEXEC

2020-05-01 Thread Christian Heimes
On 29/04/2020 00.01, Jann Horn wrote:
> On Tue, Apr 28, 2020 at 11:21 PM Florian Weimer  wrote:
>> * Jann Horn:
>>
>>> Just as a comment: You'd probably also have to use RESOLVE_MAYEXEC in
>>> the dynamic linker.
>>
>> Absolutely.  In typical configurations, the kernel does not enforce
>> that executable mappings must be backed by files which are executable.
>> It's most obvious with using an explicit loader invocation to run
>> executables on noexec mounts.  RESOLVE_MAYEXEC is much more useful
>> than trying to reimplement the kernel permission checks (or what some
>> believe they should be) in userspace.
> 
> Oh, good point.
> 
> That actually seems like something Mickaël could add to his series? If
> someone turns on that knob for "When an interpreter wants to execute
> something, enforce that we have execute access to it", they probably
> also don't want it to be possible to just map files as executable? So
> perhaps when that flag is on, the kernel should either refuse to map
> anything as executable if it wasn't opened with RESOLVE_MAYEXEC or
> (less strict) if RESOLVE_MAYEXEC wasn't used, print a warning, then
> check whether the file is executable and bail out if not?
> 
> A configuration where interpreters verify that scripts are executable,
> but other things can just mmap executable pages, seems kinda
> inconsistent...

+1

I worked with Steve Downer on Python PEP 578 [1] that added audit hooks
and PyFile_OpenCode() to CPython. A PyFile_OpenCode() implementation
with RESOLVE_MAYEXEC will hep to secure loading of Python code. But
Python also includes a wrapper of libffi. ctypes or cffi can load native
code from either shared libraries with dlopen() or execute native code
from mmap() regions. For example SnakeEater [2] is a clever attack that
abused memfd_create syscall and proc filesystem to execute code.

A consistent security policy must also ensure that mmap() PROT_EXEC
enforces the same restrictions as RESOLVE_MAYEXEC. The restriction
doesn't have be part of this patch, though.

Christian

[1] https://www.python.org/dev/peps/pep-0578/
[2] https://github.com/nullbites/SnakeEater/blob/master/SnakeEater2.py