Re: [PATCH v7 4/7] fs: Introduce O_MAYEXEC flag for openat2(2)
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)
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)
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)
* 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)
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)
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)
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. */ -