Re: [PATCH v7 4/7] fs: Introduce O_MAYEXEC flag for openat2(2)

2020-08-13 Thread Mickaël Salaün


On 11/08/2020 21:51, Eric W. Biederman wrote:
> Mickaël Salaün  writes:
> 
>> 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) because of their unspecified flags handling.  When used with
>> openat2(2), the default behavior is only to forbid to open a directory.
>>
>> 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.
>>
>> Even without enforced security policy, userland interpreters can set it
>> to enforce the system policy at their level, knowing that it will not
>> break anything on running systems which do not care about this feature.
>> However, on systems which want this feature enforced, there will be
>> knowledgeable people (i.e. sysadmins who enforced O_MAYEXEC
>> deliberately) to manage it.  A simple security policy implementation,
>> configured through a dedicated sysctl, is available in a following
>> patch.
>>
>> O_MAYEXEC should not be confused with the O_EXEC flag which is intended
>> for execute-only, which obviously doesn't work for scripts.  However, a
>> similar behavior could be implemented in userland with O_PATH:
>> https://lore.kernel.org/lkml/1e2f6913-42f2-3578-28ed-567f6a4bd...@digikod.net/
>>
>> The implementation of O_MAYEXEC almost duplicates what execve(2) and
>> uselib(2) are already doing: setting MAY_OPENEXEC in acc_mode (which can
>> then be checked as MAY_EXEC, if enforced).
> 
> You are allowing S_IFBLK, S_IFCHR, S_IFIFO, S_IFSOCK as targets for
> O_MAYEXEC?

There is a switch case for each file type (in this patch and the next one).

> 
> You are not requiring the opened script be executable?

The (conditional) enforcement is in the next patch, with the rational.

> 
> You are not requring path_noexec?  Despite the original patch that
> inspired this was checking path_noexec?

This patch just introduces the new flag and its default behavior. See
the next patch for a security policy configuration.

> 
> I honestly think this patch is buggy.  If you could reuse MAY_EXEC in
> the kernel and mean what exec means when it says MAY_EXEC that would be
> useful.

Yeah, but unfortunately this is not possible in practice because of
general Linux distro, as explained in the next patch.


> 
> As it is this patch appears wrong and dangerously confusing as it implies
> execness but does not implement execness.

Please see next patch.

> 
> If you were simply defining O_EXEC and reusing MAY_EXEC as it exists
> or exists with cleanups in the kernel this would be a small change that
> would seem to make reasonable sense.  But as you are not reusing
> anything from MAY_EXEC this code does not make any sense as I am reading
> it.

As explained in this commit message, O_EXEC doesn't have the same
semantic. Also, see next patch.

> 
> Eric
> 
> 
>> This is an updated subset of the patch initially written by Vincent
>> Strubel for CLIP OS 4:
>> https://github.com/clipos-archive/src_platform_clip-patches/blob/f5cb330d6b684752e403b4e41b39f7004d88e561/1901_open_mayexec.patch
>> This patch has been used for more than 12 years with customized script
>> interpreters.  Some examples (with the original O_MAYEXEC) can be found
>> here:
>> https://github.com/clipos-archive/clipos4_portage-overlay/search?q=O_MAYEXEC
>>
>> Co-developed-by: Vincent Strubel 
>> Signed-off-by: Vincent Strubel 
>> Co-developed-by: Thibaut Sautereau 
>> Signed-off-by: Thibaut Sautereau 
>> Signed-off-by: Mickaël Salaün 
>> Cc: Aleksa Sarai 
>> Cc: Al Viro 
>> Cc: Deven Bowers 
>> Cc: Kees Cook 
>> ---
>>
>> Changes since v6:
>> * Do not set __FMODE_EXEC for now because of inconsistent behavior:
>>   https://lore.kernel.org/lkml/202007160822.CCDB5478@keescook/
>> * Returns EISDIR when opening a directory with O_MAYEXEC.
>> * Removed Deven Bowers and Kees Cook Reviewed-by tags because of the
>>   current update.
>>
>> Changes since v5:
>> * Update commit message.
>>
>> Changes since v3:
>> * Switch back to O_MAYEXEC, but only handle it with openat2(2) which
>>   checks unknown flags (suggested by Aleksa Sarai). Cf.
>>   
>> 

Re: [PATCH v7 4/7] fs: Introduce O_MAYEXEC flag for openat2(2)

2020-08-11 Thread Eric W. Biederman
Mickaël Salaün  writes:

> 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) because of their unspecified flags handling.  When used with
> openat2(2), the default behavior is only to forbid to open a directory.
>
> 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.
>
> Even without enforced security policy, userland interpreters can set it
> to enforce the system policy at their level, knowing that it will not
> break anything on running systems which do not care about this feature.
> However, on systems which want this feature enforced, there will be
> knowledgeable people (i.e. sysadmins who enforced O_MAYEXEC
> deliberately) to manage it.  A simple security policy implementation,
> configured through a dedicated sysctl, is available in a following
> patch.
>
> O_MAYEXEC should not be confused with the O_EXEC flag which is intended
> for execute-only, which obviously doesn't work for scripts.  However, a
> similar behavior could be implemented in userland with O_PATH:
> https://lore.kernel.org/lkml/1e2f6913-42f2-3578-28ed-567f6a4bd...@digikod.net/
>
> The implementation of O_MAYEXEC almost duplicates what execve(2) and
> uselib(2) are already doing: setting MAY_OPENEXEC in acc_mode (which can
> then be checked as MAY_EXEC, if enforced).

You are allowing S_IFBLK, S_IFCHR, S_IFIFO, S_IFSOCK as targets for
O_MAYEXEC?

You are not requiring the opened script be executable?

You are not requring path_noexec?  Despite the original patch that
inspired this was checking path_noexec?

I honestly think this patch is buggy.  If you could reuse MAY_EXEC in
the kernel and mean what exec means when it says MAY_EXEC that would be
useful.

As it is this patch appears wrong and dangerously confusing as it implies
execness but does not implement execness.

If you were simply defining O_EXEC and reusing MAY_EXEC as it exists
or exists with cleanups in the kernel this would be a small change that
would seem to make reasonable sense.  But as you are not reusing
anything from MAY_EXEC this code does not make any sense as I am reading
it.

Eric


> This is an updated subset of the patch initially written by Vincent
> Strubel for CLIP OS 4:
> https://github.com/clipos-archive/src_platform_clip-patches/blob/f5cb330d6b684752e403b4e41b39f7004d88e561/1901_open_mayexec.patch
> This patch has been used for more than 12 years with customized script
> interpreters.  Some examples (with the original O_MAYEXEC) can be found
> here:
> https://github.com/clipos-archive/clipos4_portage-overlay/search?q=O_MAYEXEC
>
> Co-developed-by: Vincent Strubel 
> Signed-off-by: Vincent Strubel 
> Co-developed-by: Thibaut Sautereau 
> Signed-off-by: Thibaut Sautereau 
> Signed-off-by: Mickaël Salaün 
> Cc: Aleksa Sarai 
> Cc: Al Viro 
> Cc: Deven Bowers 
> Cc: Kees Cook 
> ---
>
> Changes since v6:
> * Do not set __FMODE_EXEC for now because of inconsistent behavior:
>   https://lore.kernel.org/lkml/202007160822.CCDB5478@keescook/
> * Returns EISDIR when opening a directory with O_MAYEXEC.
> * Removed Deven Bowers and Kees Cook Reviewed-by tags because of the
>   current update.
>
> Changes since v5:
> * Update commit message.
>
> Changes since v3:
> * Switch back to O_MAYEXEC, but only handle it with openat2(2) which
>   checks unknown flags (suggested by Aleksa Sarai). Cf.
>   
> https://lore.kernel.org/lkml/20200430015429.wuob7m5ofdewu...@yavin.dot.cyphar.com/
>
> Changes since v2:
> * Replace O_MAYEXEC with RESOLVE_MAYEXEC from openat2(2).  This change
>   enables to not break existing application using bogus O_* flags that
>   may be ignored by current kernels by using a new dedicated flag, only
>   usable through openat2(2) (suggested by Jeff Layton).  Using this flag
>   will results in an error if the running kernel does not support it.
>   User space needs to manage this case, as with other RESOLVE_* flags.
>   The best effort approach to security (for most common distros) will
>   simply consists of ignoring such an error and retry without
>   RESOLVE_MAYEXEC.  However, a fully controlled system may 

Re: [PATCH v7 4/7] fs: Introduce O_MAYEXEC flag for openat2(2)

2020-07-27 Thread Mickaël Salaün


On 27/07/2020 07:27, Florian Weimer wrote:
> * Al Viro:
> 
>> On Thu, Jul 23, 2020 at 07:12:24PM +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) because of their unspecified flags handling.  When used with
>>> openat2(2), the default behavior is only to forbid to open a directory.
>>
>> Correct me if I'm wrong, but it looks like you are introducing a magical
>> flag that would mean "let the Linux S take an extra special whip
>> for this open()".

There is nothing magic, it doesn't only work with the LSM framework, and
there is nothing painful nor humiliating here (except maybe this language).

>>
>> Why is it done during open?  If the caller is passing it deliberately,
>> why not have an explicit request to apply given torture device to an
>> already opened file?  Why not sys_masochism(int fd, char *hurt_flavour),
>> for that matter?
> 
> While I do not think this is appropriate language for a workplace, Al
> has a point: If the auditing event can be generated on an already-open
> descriptor, it would also cover scenarios like this one:
> 
>   perl < /path/to/script
> 
> Where the process that opens the file does not (and cannot) know that it
> will be used for execution purposes.

The check is done during open because the goal of this patch series is
to address the problem of script execution when opening a script in well
controlled systems (e.g. to enforce a "write xor execute" policy, to do
an atomic integrity check [1], to check specific execute/read
permissions, etc.). As discussed multiple times, controlling other means
to interpret commands (stdin, environment variables, etc.) is out of
scope and should be handled by interpreters (in userspace). Someone
could still extend fcntl(2) to enable to check file descriptors, but it
is an independent change not required for now.
Specific audit features are also out of scope for now [2].

[1] https://lore.kernel.org/lkml/1544699060.6703.11.ca...@linux.ibm.com/
[2] https://lore.kernel.org/lkml/202007160822.CCDB5478@keescook/


Re: [PATCH v7 4/7] fs: Introduce O_MAYEXEC flag for openat2(2)

2020-07-26 Thread Florian Weimer
* Al Viro:

> On Thu, Jul 23, 2020 at 07:12:24PM +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) because of their unspecified flags handling.  When used with
>> openat2(2), the default behavior is only to forbid to open a directory.
>
> Correct me if I'm wrong, but it looks like you are introducing a magical
> flag that would mean "let the Linux S take an extra special whip
> for this open()".
>
> Why is it done during open?  If the caller is passing it deliberately,
> why not have an explicit request to apply given torture device to an
> already opened file?  Why not sys_masochism(int fd, char *hurt_flavour),
> for that matter?

While I do not think this is appropriate language for a workplace, Al
has a point: If the auditing event can be generated on an already-open
descriptor, it would also cover scenarios like this one:

  perl < /path/to/script

Where the process that opens the file does not (and cannot) know that it
will be used for execution purposes.

Thanks,
Florian



Re: [PATCH v7 4/7] fs: Introduce O_MAYEXEC flag for openat2(2)

2020-07-26 Thread Al Viro
On Thu, Jul 23, 2020 at 07:12:24PM +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) because of their unspecified flags handling.  When used with
> openat2(2), the default behavior is only to forbid to open a directory.

Correct me if I'm wrong, but it looks like you are introducing a magical
flag that would mean "let the Linux S take an extra special whip
for this open()".

Why is it done during open?  If the caller is passing it deliberately,
why not have an explicit request to apply given torture device to an
already opened file?  Why not sys_masochism(int fd, char *hurt_flavour),
for that matter?


Re: [PATCH v7 4/7] fs: Introduce O_MAYEXEC flag for openat2(2)

2020-07-24 Thread Kees Cook
On Thu, Jul 23, 2020 at 07:12:24PM +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) because of their unspecified flags handling.  When used with
> openat2(2), the default behavior is only to forbid to open a directory.
> 
> 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.
> 
> Even without enforced security policy, userland interpreters can set it
> to enforce the system policy at their level, knowing that it will not
> break anything on running systems which do not care about this feature.
> However, on systems which want this feature enforced, there will be
> knowledgeable people (i.e. sysadmins who enforced O_MAYEXEC
> deliberately) to manage it.  A simple security policy implementation,
> configured through a dedicated sysctl, is available in a following
> patch.
> 
> O_MAYEXEC should not be confused with the O_EXEC flag which is intended
> for execute-only, which obviously doesn't work for scripts.  However, a
> similar behavior could be implemented in userland with O_PATH:
> https://lore.kernel.org/lkml/1e2f6913-42f2-3578-28ed-567f6a4bd...@digikod.net/
> 
> The implementation of O_MAYEXEC almost duplicates what execve(2) and
> uselib(2) are already doing: setting MAY_OPENEXEC in acc_mode (which can
> then be checked as MAY_EXEC, if enforced).
> 
> This is an updated subset of the patch initially written by Vincent
> Strubel for CLIP OS 4:
> https://github.com/clipos-archive/src_platform_clip-patches/blob/f5cb330d6b684752e403b4e41b39f7004d88e561/1901_open_mayexec.patch
> This patch has been used for more than 12 years with customized script
> interpreters.  Some examples (with the original O_MAYEXEC) can be found
> here:
> https://github.com/clipos-archive/clipos4_portage-overlay/search?q=O_MAYEXEC
> 
> Co-developed-by: Vincent Strubel 
> Signed-off-by: Vincent Strubel 

Acked-by: Kees Cook 

-- 
Kees Cook


[PATCH v7 4/7] fs: Introduce O_MAYEXEC flag for openat2(2)

2020-07-23 Thread Mickaël Salaün
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) because of their unspecified flags handling.  When used with
openat2(2), the default behavior is only to forbid to open a directory.

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.

Even without enforced security policy, userland interpreters can set it
to enforce the system policy at their level, knowing that it will not
break anything on running systems which do not care about this feature.
However, on systems which want this feature enforced, there will be
knowledgeable people (i.e. sysadmins who enforced O_MAYEXEC
deliberately) to manage it.  A simple security policy implementation,
configured through a dedicated sysctl, is available in a following
patch.

O_MAYEXEC should not be confused with the O_EXEC flag which is intended
for execute-only, which obviously doesn't work for scripts.  However, a
similar behavior could be implemented in userland with O_PATH:
https://lore.kernel.org/lkml/1e2f6913-42f2-3578-28ed-567f6a4bd...@digikod.net/

The implementation of O_MAYEXEC almost duplicates what execve(2) and
uselib(2) are already doing: setting MAY_OPENEXEC in acc_mode (which can
then be checked as MAY_EXEC, if enforced).

This is an updated subset of the patch initially written by Vincent
Strubel for CLIP OS 4:
https://github.com/clipos-archive/src_platform_clip-patches/blob/f5cb330d6b684752e403b4e41b39f7004d88e561/1901_open_mayexec.patch
This patch has been used for more than 12 years with customized script
interpreters.  Some examples (with the original O_MAYEXEC) can be found
here:
https://github.com/clipos-archive/clipos4_portage-overlay/search?q=O_MAYEXEC

Co-developed-by: Vincent Strubel 
Signed-off-by: Vincent Strubel 
Co-developed-by: Thibaut Sautereau 
Signed-off-by: Thibaut Sautereau 
Signed-off-by: Mickaël Salaün 
Cc: Aleksa Sarai 
Cc: Al Viro 
Cc: Deven Bowers 
Cc: Kees Cook 
---

Changes since v6:
* Do not set __FMODE_EXEC for now because of inconsistent behavior:
  https://lore.kernel.org/lkml/202007160822.CCDB5478@keescook/
* Returns EISDIR when opening a directory with O_MAYEXEC.
* Removed Deven Bowers and Kees Cook Reviewed-by tags because of the
  current update.

Changes since v5:
* Update commit message.

Changes since v3:
* Switch back to O_MAYEXEC, but only handle it with openat2(2) which
  checks unknown flags (suggested by Aleksa Sarai). Cf.
  
https://lore.kernel.org/lkml/20200430015429.wuob7m5ofdewu...@yavin.dot.cyphar.com/

Changes since v2:
* Replace O_MAYEXEC with RESOLVE_MAYEXEC from openat2(2).  This change
  enables to not break existing application using bogus O_* flags that
  may be ignored by current kernels by using a new dedicated flag, only
  usable through openat2(2) (suggested by Jeff Layton).  Using this flag
  will results in an error if the running kernel does not support it.
  User space needs to manage this case, as with other RESOLVE_* flags.
  The best effort approach to security (for most common distros) will
  simply consists of ignoring such an error and retry without
  RESOLVE_MAYEXEC.  However, a fully controlled system may which to
  error out if such an inconsistency is detected.

Changes since v1:
* Set __FMODE_EXEC when using O_MAYEXEC to make this information
  available through the new fanotify/FAN_OPEN_EXEC event (suggested by
  Jan Kara and Matthew Bobrowski):
  https://lore.kernel.org/lkml/20181213094658.ga...@lithium.mbobrowski.org/
---
 fs/fcntl.c   | 2 +-
 fs/namei.c   | 4 ++--
 fs/open.c| 6 ++
 include/linux/fcntl.h| 2 +-
 include/linux/fs.h   | 2 ++
 include/uapi/asm-generic/fcntl.h | 7 +++
 6 files changed, 19 insertions(+), 4 deletions(-)

diff --git a/fs/fcntl.c b/fs/fcntl.c
index 2e4c0fa2074b..0357ad667563 100644
--- a/fs/fcntl.c
+++ b/fs/fcntl.c
@@ -1033,7 +1033,7 @@ static int __init fcntl_init(void)
 * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY
 * is defined as O_NONBLOCK on some platforms and not on others.
 */
-