Message ID | 20181212081712.32347-1-mic@digikod.net (mailing list archive) |
---|---|
Headers | show |
Series | Add support for O_MAYEXEC | expand |
On Wednesday, December 12, 2018 9:17 AM, Mickaël Salaün <mic@digikod.net> wrote: > Hi, > > The goal of this patch series is to control script interpretation. A > new O_MAYEXEC flag used by sys_open() is added to enable userland script > interpreter to delegate to the kernel (and thus the system security > policy) the permission to interpret scripts or other files containing > what can be seen as commands. > > The security policy is the responsibility of an LSM. A basic > system-wide policy is implemented with Yama and configurable through a > sysctl. > > The initial idea come from CLIP OS and the original implementation has > been used for more than 10 years: > https://github.com/clipos-archive/clipos4_doc > > An introduction to O_MAYEXEC was given at the Linux Security Summit > Europe 2018 - Linux Kernel Security Contributions by ANSSI: > https://www.youtube.com/watch?v=chNjCRtPKQY&t=17m15s > The "write xor execute" principle was explained at Kernel Recipes 2018 - > CLIP OS: a defense-in-depth OS: > https://www.youtube.com/watch?v=PjRE0uBtkHU&t=11m14s > > This patch series can be applied on top of v4.20-rc6. This can be > tested with CONFIG_SECURITY_YAMA. I would really appreciate > constructive comments on this RFC. > > Regards, > Are various interpreters upstreams interested in adding support for O_MAYEXEC if it land in kernel? Did you contacted them about this? Jordan
Le 12/12/2018 à 17:29, Jordan Glover a écrit : > On Wednesday, December 12, 2018 9:17 AM, Mickaël Salaün <mic@digikod.net> wrote: > >> Hi, >> >> The goal of this patch series is to control script interpretation. A >> new O_MAYEXEC flag used by sys_open() is added to enable userland script >> interpreter to delegate to the kernel (and thus the system security >> policy) the permission to interpret scripts or other files containing >> what can be seen as commands. >> >> The security policy is the responsibility of an LSM. A basic >> system-wide policy is implemented with Yama and configurable through a >> sysctl. >> >> The initial idea come from CLIP OS and the original implementation has >> been used for more than 10 years: >> https://github.com/clipos-archive/clipos4_doc >> >> An introduction to O_MAYEXEC was given at the Linux Security Summit >> Europe 2018 - Linux Kernel Security Contributions by ANSSI: >> https://www.youtube.com/watch?v=chNjCRtPKQY&t=17m15s >> The "write xor execute" principle was explained at Kernel Recipes 2018 - >> CLIP OS: a defense-in-depth OS: >> https://www.youtube.com/watch?v=PjRE0uBtkHU&t=11m14s >> >> This patch series can be applied on top of v4.20-rc6. This can be >> tested with CONFIG_SECURITY_YAMA. I would really appreciate >> constructive comments on this RFC. >> >> Regards, >> > > Are various interpreters upstreams interested in adding support > for O_MAYEXEC if it land in kernel? Did you contacted them about this? I think the first step is to be OK on the kernel side. We will then be able to help upstream interpreters implement this feature. It should be OK because the behavior doesn't change by default, i.e. if the sysadmin doesn't configure (and test) the whole system. Some examples of modified interpreters can be found at https://github.com/clipos-archive/clipos4_portage-overlay/search?q=O_MAYEXEC . Mickaël
On Wed, 12 Dec 2018, Mickaël Salaün wrote: > Hi, > > The goal of this patch series is to control script interpretation. A > new O_MAYEXEC flag used by sys_open() is added to enable userland script > interpreter to delegate to the kernel (and thus the system security > policy) the permission to interpret scripts or other files containing > what can be seen as commands. > > The security policy is the responsibility of an LSM. A basic > system-wide policy is implemented with Yama and configurable through a > sysctl. If you're depending on the script interpreter to flag that the user may execute code, this seems to be equivalent in security terms to depending on the user. e.g. what if the user uses ptrace and clears O_MAYEXEC?
* James Morris: > If you're depending on the script interpreter to flag that the user may > execute code, this seems to be equivalent in security terms to depending > on the user. e.g. what if the user uses ptrace and clears O_MAYEXEC? The argument I've heard is this: Using ptrace (and adding the +x attribute) are auditable events. Florian
On Wed, 12 Dec 2018, Florian Weimer wrote: > * James Morris: > > > If you're depending on the script interpreter to flag that the user may > > execute code, this seems to be equivalent in security terms to depending > > on the user. e.g. what if the user uses ptrace and clears O_MAYEXEC? > > The argument I've heard is this: Using ptrace (and adding the +x > attribute) are auditable events. I guess you could also preload a modified libc which strips the flag.
On Wed, Dec 12, 2018 at 09:17:07AM +0100, Mickaël Salaün wrote: > The goal of this patch series is to control script interpretation. A > new O_MAYEXEC flag used by sys_open() is added to enable userland script > interpreter to delegate to the kernel (and thus the system security > policy) the permission to interpret scripts or other files containing > what can be seen as commands. I don't have a problem with the concept, but we're running low on O_ bits. Does this have to be done before the process gets a file descriptor, or could we have a new syscall? Since we're going to be changing the interpreters anyway, it doesn't seem like too much of an imposition to ask them to use: int verify_for_exec(int fd) instead of adding an O_MAYEXEC.
* James Morris: > On Wed, 12 Dec 2018, Florian Weimer wrote: > >> * James Morris: >> >> > If you're depending on the script interpreter to flag that the user may >> > execute code, this seems to be equivalent in security terms to depending >> > on the user. e.g. what if the user uses ptrace and clears O_MAYEXEC? >> >> The argument I've heard is this: Using ptrace (and adding the +x >> attribute) are auditable events. > > I guess you could also preload a modified libc which strips the flag. My understanding is that this new libc would have to come somewhere, and making it executable would be an auditable even as well. Thanks, Florian
* Matthew Wilcox: > On Wed, Dec 12, 2018 at 09:17:07AM +0100, Mickaël Salaün wrote: >> The goal of this patch series is to control script interpretation. A >> new O_MAYEXEC flag used by sys_open() is added to enable userland script >> interpreter to delegate to the kernel (and thus the system security >> policy) the permission to interpret scripts or other files containing >> what can be seen as commands. > > I don't have a problem with the concept, but we're running low on O_ bits. > Does this have to be done before the process gets a file descriptor, > or could we have a new syscall? Since we're going to be changing the > interpreters anyway, it doesn't seem like too much of an imposition to > ask them to use: > > int verify_for_exec(int fd) > > instead of adding an O_MAYEXEC. Will this work for auditing? Maybe add an interface which explicitly upgrades O_PATH descriptors, and give that a separate flag argument? I suppose that would be more friendly to auditing. Thanks, Florian
On Wed, 2018-12-12 at 19:02 -0800, Matthew Wilcox wrote: > On Wed, Dec 12, 2018 at 09:17:07AM +0100, Mickaël Salaün wrote: > > The goal of this patch series is to control script interpretation. A > > new O_MAYEXEC flag used by sys_open() is added to enable userland script > > interpreter to delegate to the kernel (and thus the system security > > policy) the permission to interpret scripts or other files containing > > what can be seen as commands. > > I don't have a problem with the concept, but we're running low on O_ bits. > Does this have to be done before the process gets a file descriptor, > or could we have a new syscall? Since we're going to be changing the > interpreters anyway, it doesn't seem like too much of an imposition to > ask them to use: > > int verify_for_exec(int fd) > > instead of adding an O_MAYEXEC. The indication needs to be set during file open, before the open returns to the caller. This is the point where ima_file_check() verifies the file's signature. On failure, access to the file is denied. Mimi
* Mimi Zohar: > The indication needs to be set during file open, before the open > returns to the caller. This is the point where ima_file_check() > verifies the file's signature. On failure, access to the file is > denied. Does this verification happen for open with O_PATH? Thanks, Florian
On Thu, Dec 13, 2018 at 06:04:20AM -0500, Mimi Zohar wrote: > > I don't have a problem with the concept, but we're running low on O_ bits. > > Does this have to be done before the process gets a file descriptor, > > or could we have a new syscall? Since we're going to be changing the > > interpreters anyway, it doesn't seem like too much of an imposition to > > ask them to use: > > > > int verify_for_exec(int fd) > > > > instead of adding an O_MAYEXEC. > > The indication needs to be set during file open, before the open > returns to the caller. This is the point where ima_file_check() > verifies the file's signature. On failure, access to the file is > denied. I understand that's what happens today, but do we need to do it that way? There's no harm in the interpreter having an fd to a file if it knows not to execute it. This is different from a program opening a file and having the LSM deny access to it because it violates the security model.
[Cc'ing linux-integrity] On Thu, 2018-12-13 at 12:26 +0100, Florian Weimer wrote: > * Mimi Zohar: > > > The indication needs to be set during file open, before the open > > returns to the caller. This is the point where ima_file_check() > > verifies the file's signature. On failure, access to the file is > > denied. > > Does this verification happen for open with O_PATH? Interesting! According to the manpage, userspace cannot read/write to the file. It looks like do_o_path() intentionally skips do_last(), with the call to ima_file_check(). If the file data isn't being accessed, does the file's integrity need to be verified? Mimi
On 13/12/2018 06:13, Florian Weimer wrote: > * James Morris: > >> On Wed, 12 Dec 2018, Florian Weimer wrote: >> >>> * James Morris: >>> >>>> If you're depending on the script interpreter to flag that the user may >>>> execute code, this seems to be equivalent in security terms to depending >>>> on the user. e.g. what if the user uses ptrace and clears O_MAYEXEC? This security mechanism makes sense in an hardened system where the user is not allowed to import and execute new file (write xor execute policy). This can be enforced with appropriate mount points a more advanced access control policy. >>> >>> The argument I've heard is this: Using ptrace (and adding the +x >>> attribute) are auditable events. >> >> I guess you could also preload a modified libc which strips the flag. > > My understanding is that this new libc would have to come somewhere, and > making it executable would be an auditable even as well. Auditing is a possible use case as well, but the W^X idea is to deny use of libraries which are not in an executable mount point, i.e. only execute trusted code.
On 13/12/2018 04:02, Matthew Wilcox wrote: > On Wed, Dec 12, 2018 at 09:17:07AM +0100, Mickaël Salaün wrote: >> The goal of this patch series is to control script interpretation. A >> new O_MAYEXEC flag used by sys_open() is added to enable userland script >> interpreter to delegate to the kernel (and thus the system security >> policy) the permission to interpret scripts or other files containing >> what can be seen as commands. > > I don't have a problem with the concept, but we're running low on O_ bits. > Does this have to be done before the process gets a file descriptor, > or could we have a new syscall? Since we're going to be changing the > interpreters anyway, it doesn't seem like too much of an imposition to > ask them to use: > > int verify_for_exec(int fd) > > instead of adding an O_MAYEXEC. > Adding a new syscall for this simple use case seems excessive. I think that the open/openat syscall familly are the right place to do an atomic open and permission check, the same way the kernel does for other file access. Moreover, it will be easier to patch upstream interpreters without the burden of handling a (new) syscall that may not exist on the running system, whereas unknown open flags are ignored.
On Thu, Dec 13, 2018 at 04:17:29PM +0100, Mickaël Salaün wrote: > On 13/12/2018 04:02, Matthew Wilcox wrote: > > On Wed, Dec 12, 2018 at 09:17:07AM +0100, Mickaël Salaün wrote: > >> The goal of this patch series is to control script interpretation. A > >> new O_MAYEXEC flag used by sys_open() is added to enable userland script > >> interpreter to delegate to the kernel (and thus the system security > >> policy) the permission to interpret scripts or other files containing > >> what can be seen as commands. > > > > I don't have a problem with the concept, but we're running low on O_ bits. > > Does this have to be done before the process gets a file descriptor, > > or could we have a new syscall? Since we're going to be changing the > > interpreters anyway, it doesn't seem like too much of an imposition to > > ask them to use: > > > > int verify_for_exec(int fd) > > > > instead of adding an O_MAYEXEC. > > Adding a new syscall for this simple use case seems excessive. I think We have somewhat less than 400 syscalls today. We have 20 O_ bits defined. Obviously there's a lower practical limit on syscalls, but in principle we could have up to 2^32 syscalls, and there are only 12 O_ bits remaining. > that the open/openat syscall familly are the right place to do an atomic > open and permission check, the same way the kernel does for other file > access. Moreover, it will be easier to patch upstream interpreters > without the burden of handling a (new) syscall that may not exist on the > running system, whereas unknown open flags are ignored. Ah, but that's the problem. The interpreter can see an -ENOSYS response and handle it appropriately. If the flag is silently ignored, the interpreter has no idea whether it can do a racy check or whether to skip even trying to do the check.
On 13/12/2018 18:13, Matthew Wilcox wrote: > On Thu, Dec 13, 2018 at 04:17:29PM +0100, Mickaël Salaün wrote: >> On 13/12/2018 04:02, Matthew Wilcox wrote: >>> On Wed, Dec 12, 2018 at 09:17:07AM +0100, Mickaël Salaün wrote: >>>> The goal of this patch series is to control script interpretation. A >>>> new O_MAYEXEC flag used by sys_open() is added to enable userland script >>>> interpreter to delegate to the kernel (and thus the system security >>>> policy) the permission to interpret scripts or other files containing >>>> what can be seen as commands. >>> >>> I don't have a problem with the concept, but we're running low on O_ bits. >>> Does this have to be done before the process gets a file descriptor, >>> or could we have a new syscall? Since we're going to be changing the >>> interpreters anyway, it doesn't seem like too much of an imposition to >>> ask them to use: >>> >>> int verify_for_exec(int fd) >>> >>> instead of adding an O_MAYEXEC. >> >> Adding a new syscall for this simple use case seems excessive. I think > > We have somewhat less than 400 syscalls today. We have 20 O_ bits defined. > Obviously there's a lower practical limit on syscalls, but in principle > we could have up to 2^32 syscalls, and there are only 12 O_ bits remaining. > >> that the open/openat syscall familly are the right place to do an atomic >> open and permission check, the same way the kernel does for other file >> access. Moreover, it will be easier to patch upstream interpreters >> without the burden of handling a (new) syscall that may not exist on the >> running system, whereas unknown open flags are ignored. > > Ah, but that's the problem. The interpreter can see an -ENOSYS response > and handle it appropriately. If the flag is silently ignored, the > interpreter has no idea whether it can do a racy check or whether to > skip even trying to do the check. Right, but the interpreter should interpret the script if the open with O_MAYEXEC succeed (but not otherwise): it may be because the flag is known by the kernel and the system policy allow this call, or because the (old) kernel doesn't known about this flag (which is fine and needed for backward compatibility). The script interpretation must not failed if the kernel doesn't support O_MAYEXEC, it is then useless for the interpreter to do any additional check.
On Thu, Dec 13, 2018 at 06:36:15PM +0100, Mickaël Salaün wrote: > On 13/12/2018 18:13, Matthew Wilcox wrote: > > On Thu, Dec 13, 2018 at 04:17:29PM +0100, Mickaël Salaün wrote: > >> Adding a new syscall for this simple use case seems excessive. I think > > > > We have somewhat less than 400 syscalls today. We have 20 O_ bits defined. > > Obviously there's a lower practical limit on syscalls, but in principle > > we could have up to 2^32 syscalls, and there are only 12 O_ bits remaining. > > > >> that the open/openat syscall familly are the right place to do an atomic > >> open and permission check, the same way the kernel does for other file > >> access. Moreover, it will be easier to patch upstream interpreters > >> without the burden of handling a (new) syscall that may not exist on the > >> running system, whereas unknown open flags are ignored. > > > > Ah, but that's the problem. The interpreter can see an -ENOSYS response > > and handle it appropriately. If the flag is silently ignored, the > > interpreter has no idea whether it can do a racy check or whether to > > skip even trying to do the check. > > Right, but the interpreter should interpret the script if the open with > O_MAYEXEC succeed (but not otherwise): it may be because the flag is > known by the kernel and the system policy allow this call, or because > the (old) kernel doesn't known about this flag (which is fine and needed > for backward compatibility). The script interpretation must not failed > if the kernel doesn't support O_MAYEXEC, it is then useless for the > interpreter to do any additional check. If that's the way interpreters want to work, then that's fine. They can just call the verify() syscall and ignore the -ENOSYS. Done. Or somebody who cares very, very deeply can change the interpreter to decline to run any scripts if the kernel returns -ENOSYS.