* [PATCH] proc: prevent a task from writing on its own /proc/*/mem
@ 2018-05-26 14:50 Salvatore Mesoraca
2018-05-26 15:48 ` Alexey Dobriyan
` (2 more replies)
0 siblings, 3 replies; 11+ messages in thread
From: Salvatore Mesoraca @ 2018-05-26 14:50 UTC (permalink / raw)
To: kernel-hardening
Cc: linux-security-module, linux-kernel, linux-mm,
Salvatore Mesoraca, Andrew Morton, Alexey Dobriyan, Akinobu Mita,
Dmitry Vyukov, Arnd Bergmann, Davidlohr Bueso, Kees Cook
Prevent a task from opening, in "write" mode, any /proc/*/mem
file that operates on the task's mm.
/proc/*/mem is mainly a debugging means and, as such, it shouldn't
be used by the inspected process itself.
Current implementation always allow a task to access its own
/proc/*/mem file.
A process can use it to overwrite read-only memory, making
pointless the use of security_file_mprotect() or other ways to
enforce RO memory.
Signed-off-by: Salvatore Mesoraca <s.mesoraca16@gmail.com>
---
fs/proc/base.c | 25 ++++++++++++++++++-------
fs/proc/internal.h | 3 ++-
fs/proc/task_mmu.c | 4 ++--
fs/proc/task_nommu.c | 2 +-
4 files changed, 23 insertions(+), 11 deletions(-)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 1a76d75..01ecfec 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -762,8 +762,9 @@ static int proc_single_open(struct inode *inode, struct file *filp)
.release = single_release,
};
-
-struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode)
+struct mm_struct *proc_mem_open(struct inode *inode,
+ unsigned int mode,
+ fmode_t f_mode)
{
struct task_struct *task = get_proc_task(inode);
struct mm_struct *mm = ERR_PTR(-ESRCH);
@@ -773,10 +774,20 @@ struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode)
put_task_struct(task);
if (!IS_ERR_OR_NULL(mm)) {
- /* ensure this mm_struct can't be freed */
- mmgrab(mm);
- /* but do not pin its memory */
- mmput(mm);
+ /*
+ * Prevent this interface from being used as a mean
+ * to bypass memory restrictions, including those
+ * imposed by LSMs.
+ */
+ if (mm == current->mm &&
+ f_mode & FMODE_WRITE)
+ mm = ERR_PTR(-EACCES);
+ else {
+ /* ensure this mm_struct can't be freed */
+ mmgrab(mm);
+ /* but do not pin its memory */
+ mmput(mm);
+ }
}
}
@@ -785,7 +796,7 @@ struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode)
static int __mem_open(struct inode *inode, struct file *file, unsigned int mode)
{
- struct mm_struct *mm = proc_mem_open(inode, mode);
+ struct mm_struct *mm = proc_mem_open(inode, mode, file->f_mode);
if (IS_ERR(mm))
return PTR_ERR(mm);
diff --git a/fs/proc/internal.h b/fs/proc/internal.h
index 0f1692e..8d38cc7 100644
--- a/fs/proc/internal.h
+++ b/fs/proc/internal.h
@@ -275,7 +275,8 @@ struct proc_maps_private {
#endif
} __randomize_layout;
-struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode);
+struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode,
+ fmode_t f_mode);
extern const struct file_operations proc_pid_maps_operations;
extern const struct file_operations proc_tid_maps_operations;
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index c486ad4..efb6535 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -227,7 +227,7 @@ static int proc_maps_open(struct inode *inode, struct file *file,
return -ENOMEM;
priv->inode = inode;
- priv->mm = proc_mem_open(inode, PTRACE_MODE_READ);
+ priv->mm = proc_mem_open(inode, PTRACE_MODE_READ, file->f_mode);
if (IS_ERR(priv->mm)) {
int err = PTR_ERR(priv->mm);
@@ -1534,7 +1534,7 @@ static int pagemap_open(struct inode *inode, struct file *file)
{
struct mm_struct *mm;
- mm = proc_mem_open(inode, PTRACE_MODE_READ);
+ mm = proc_mem_open(inode, PTRACE_MODE_READ, file->f_mode);
if (IS_ERR(mm))
return PTR_ERR(mm);
file->private_data = mm;
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c
index 5b62f57..dc38516 100644
--- a/fs/proc/task_nommu.c
+++ b/fs/proc/task_nommu.c
@@ -280,7 +280,7 @@ static int maps_open(struct inode *inode, struct file *file,
return -ENOMEM;
priv->inode = inode;
- priv->mm = proc_mem_open(inode, PTRACE_MODE_READ);
+ priv->mm = proc_mem_open(inode, PTRACE_MODE_READ, file->f_mode);
if (IS_ERR(priv->mm)) {
int err = PTR_ERR(priv->mm);
--
1.9.1
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH] proc: prevent a task from writing on its own /proc/*/mem 2018-05-26 14:50 [PATCH] proc: prevent a task from writing on its own /proc/*/mem Salvatore Mesoraca @ 2018-05-26 15:48 ` Alexey Dobriyan 2018-05-26 17:30 ` Salvatore Mesoraca 2018-05-27 0:31 ` Kees Cook 2018-05-28 9:06 ` Jann Horn 2 siblings, 1 reply; 11+ messages in thread From: Alexey Dobriyan @ 2018-05-26 15:48 UTC (permalink / raw) To: Salvatore Mesoraca Cc: kernel-hardening, linux-security-module, linux-kernel, linux-mm, Andrew Morton, Akinobu Mita, Dmitry Vyukov, Arnd Bergmann, Davidlohr Bueso, Kees Cook On Sat, May 26, 2018 at 04:50:46PM +0200, Salvatore Mesoraca wrote: > Prevent a task from opening, in "write" mode, any /proc/*/mem > file that operates on the task's mm. > /proc/*/mem is mainly a debugging means and, as such, it shouldn't > be used by the inspected process itself. > Current implementation always allow a task to access its own > /proc/*/mem file. > A process can use it to overwrite read-only memory, making > pointless the use of security_file_mprotect() or other ways to > enforce RO memory. You can do it in security_ptrace_access_check() or security_file_open() ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] proc: prevent a task from writing on its own /proc/*/mem 2018-05-26 15:48 ` Alexey Dobriyan @ 2018-05-26 17:30 ` Salvatore Mesoraca 2018-05-26 17:53 ` Casey Schaufler 2018-05-26 17:58 ` Alexey Dobriyan 0 siblings, 2 replies; 11+ messages in thread From: Salvatore Mesoraca @ 2018-05-26 17:30 UTC (permalink / raw) To: Alexey Dobriyan Cc: Kernel Hardening, linux-security-module, linux-kernel, linux-mm, Andrew Morton, Akinobu Mita, Dmitry Vyukov, Arnd Bergmann, Davidlohr Bueso, Kees Cook 2018-05-26 17:48 GMT+02:00 Alexey Dobriyan <adobriyan@gmail.com>: > On Sat, May 26, 2018 at 04:50:46PM +0200, Salvatore Mesoraca wrote: >> Prevent a task from opening, in "write" mode, any /proc/*/mem >> file that operates on the task's mm. >> /proc/*/mem is mainly a debugging means and, as such, it shouldn't >> be used by the inspected process itself. >> Current implementation always allow a task to access its own >> /proc/*/mem file. >> A process can use it to overwrite read-only memory, making >> pointless the use of security_file_mprotect() or other ways to >> enforce RO memory. > > You can do it in security_ptrace_access_check() No, because that hook is skipped when mm == current->mm: https://elixir.bootlin.com/linux/v4.17-rc6/source/kernel/fork.c#L1111 > or security_file_open() This is true, but it looks a bit overkill to me, especially since many of the macros/functions used to handle proc's files won't be in scope for an external LSM. Is there any particular reason why you prefer it done via LSM? Thank you, Salvatore ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] proc: prevent a task from writing on its own /proc/*/mem 2018-05-26 17:30 ` Salvatore Mesoraca @ 2018-05-26 17:53 ` Casey Schaufler 2018-05-26 17:58 ` Alexey Dobriyan 1 sibling, 0 replies; 11+ messages in thread From: Casey Schaufler @ 2018-05-26 17:53 UTC (permalink / raw) To: Salvatore Mesoraca, Alexey Dobriyan Cc: Kernel Hardening, linux-security-module, linux-kernel, linux-mm, Andrew Morton, Akinobu Mita, Dmitry Vyukov, Arnd Bergmann, Davidlohr Bueso, Kees Cook On 5/26/2018 10:30 AM, Salvatore Mesoraca wrote: > 2018-05-26 17:48 GMT+02:00 Alexey Dobriyan <adobriyan@gmail.com>: >> On Sat, May 26, 2018 at 04:50:46PM +0200, Salvatore Mesoraca wrote: >>> Prevent a task from opening, in "write" mode, any /proc/*/mem >>> file that operates on the task's mm. >>> /proc/*/mem is mainly a debugging means and, as such, it shouldn't >>> be used by the inspected process itself. >>> Current implementation always allow a task to access its own >>> /proc/*/mem file. >>> A process can use it to overwrite read-only memory, making >>> pointless the use of security_file_mprotect() or other ways to >>> enforce RO memory. >> You can do it in security_ptrace_access_check() > No, because that hook is skipped when mm == current->mm: > https://elixir.bootlin.com/linux/v4.17-rc6/source/kernel/fork.c#L1111 > >> or security_file_open() > This is true, but it looks a bit overkill to me, especially since many of > the macros/functions used to handle proc's files won't be in scope > for an external LSM. > Is there any particular reason why you prefer it done via LSM? If you did a Yama style LSM it would be easy to configure. Even though it might make no sense to allow this behavior, someone, somewhere is counting on it. > > Thank you, > > Salvatore > -- > To unsubscribe from this list: send the line "unsubscribe linux-security-module" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html > ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] proc: prevent a task from writing on its own /proc/*/mem 2018-05-26 17:30 ` Salvatore Mesoraca 2018-05-26 17:53 ` Casey Schaufler @ 2018-05-26 17:58 ` Alexey Dobriyan 1 sibling, 0 replies; 11+ messages in thread From: Alexey Dobriyan @ 2018-05-26 17:58 UTC (permalink / raw) To: Salvatore Mesoraca Cc: Kernel Hardening, linux-security-module, linux-kernel, linux-mm, Andrew Morton, Akinobu Mita, Dmitry Vyukov, Arnd Bergmann, Davidlohr Bueso, Kees Cook On Sat, May 26, 2018 at 07:30:47PM +0200, Salvatore Mesoraca wrote: > 2018-05-26 17:48 GMT+02:00 Alexey Dobriyan <adobriyan@gmail.com>: > > On Sat, May 26, 2018 at 04:50:46PM +0200, Salvatore Mesoraca wrote: > >> Prevent a task from opening, in "write" mode, any /proc/*/mem > >> file that operates on the task's mm. > >> /proc/*/mem is mainly a debugging means and, as such, it shouldn't > >> be used by the inspected process itself. > >> Current implementation always allow a task to access its own > >> /proc/*/mem file. > >> A process can use it to overwrite read-only memory, making > >> pointless the use of security_file_mprotect() or other ways to > >> enforce RO memory. > > > > You can do it in security_ptrace_access_check() > > No, because that hook is skipped when mm == current->mm: > https://elixir.bootlin.com/linux/v4.17-rc6/source/kernel/fork.c#L1111 OK > > or security_file_open() > > This is true, but it looks a bit overkill to me, especially since many of > the macros/functions used to handle proc's files won't be in scope > for an external LSM. > Is there any particular reason why you prefer it done via LSM? Well, it exists to implement all kinds of non-standard restrictions. You're probably blacklisting mprotect() and worry that compromised program might use /proc/self/mem instead. But you need to blacklist much more that mprotect(). I think forking a dummy "worker" process to open your /proc/*/mem and pass a descriptor back should still work with your patch. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] proc: prevent a task from writing on its own /proc/*/mem 2018-05-26 14:50 [PATCH] proc: prevent a task from writing on its own /proc/*/mem Salvatore Mesoraca 2018-05-26 15:48 ` Alexey Dobriyan @ 2018-05-27 0:31 ` Kees Cook 2018-05-27 1:33 ` Linus Torvalds 2018-05-28 9:06 ` Jann Horn 2 siblings, 1 reply; 11+ messages in thread From: Kees Cook @ 2018-05-27 0:31 UTC (permalink / raw) To: Salvatore Mesoraca, Linus Torvalds, Jann Horn Cc: Kernel Hardening, linux-security-module, LKML, Linux-MM, Andrew Morton, Alexey Dobriyan, Akinobu Mita, Dmitry Vyukov, Arnd Bergmann, Davidlohr Bueso On Sat, May 26, 2018 at 7:50 AM, Salvatore Mesoraca <s.mesoraca16@gmail.com> wrote: > Prevent a task from opening, in "write" mode, any /proc/*/mem > file that operates on the task's mm. > /proc/*/mem is mainly a debugging means and, as such, it shouldn't > be used by the inspected process itself. > Current implementation always allow a task to access its own > /proc/*/mem file. > A process can use it to overwrite read-only memory, making > pointless the use of security_file_mprotect() or other ways to > enforce RO memory. I went through some old threads from 2012 when e268337dfe26 was introduced, and later when things got looked at during DirtyCOW. There was discussion about removing FOLL_FORCE (in order to block writes on a read-only memory region). But that was much more general, touched ptrace, etc. I think this patch would be okay, since it's specific to the proc "self" mem interface, not remote processes (via ptrace). This patch would also have blocked the /proc/self/mem path to DirtyCOW (though not ptrace), so that would be nice if we have similar issues in the future. So, as long as this doesn't break anything, I'm for it in general. I've CCed Linus and Jann too, since they've stared at this a lot too. :P Note that you're re-checking the mm-check-for-self in mm_access(). That's used in /proc and for process_vm_write(). Ptrace (and mm_access()) uses ptrace_may_access() for stuff (which has a similar check to bypass LSMs), so I'd be curious what would happen if this logic was plumbed into mm_access() instead of into proc_mem_open(). (Does anything open /proc/$pid files for writing? Does anything using process_vm_write() on itself?) -Kees > > Signed-off-by: Salvatore Mesoraca <s.mesoraca16@gmail.com> > --- > fs/proc/base.c | 25 ++++++++++++++++++------- > fs/proc/internal.h | 3 ++- > fs/proc/task_mmu.c | 4 ++-- > fs/proc/task_nommu.c | 2 +- > 4 files changed, 23 insertions(+), 11 deletions(-) > > diff --git a/fs/proc/base.c b/fs/proc/base.c > index 1a76d75..01ecfec 100644 > --- a/fs/proc/base.c > +++ b/fs/proc/base.c > @@ -762,8 +762,9 @@ static int proc_single_open(struct inode *inode, struct file *filp) > .release = single_release, > }; > > - > -struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode) > +struct mm_struct *proc_mem_open(struct inode *inode, > + unsigned int mode, > + fmode_t f_mode) > { > struct task_struct *task = get_proc_task(inode); > struct mm_struct *mm = ERR_PTR(-ESRCH); > @@ -773,10 +774,20 @@ struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode) > put_task_struct(task); > > if (!IS_ERR_OR_NULL(mm)) { > - /* ensure this mm_struct can't be freed */ > - mmgrab(mm); > - /* but do not pin its memory */ > - mmput(mm); > + /* > + * Prevent this interface from being used as a mean > + * to bypass memory restrictions, including those > + * imposed by LSMs. > + */ > + if (mm == current->mm && > + f_mode & FMODE_WRITE) > + mm = ERR_PTR(-EACCES); > + else { > + /* ensure this mm_struct can't be freed */ > + mmgrab(mm); > + /* but do not pin its memory */ > + mmput(mm); > + } > } > } > > @@ -785,7 +796,7 @@ struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode) > > static int __mem_open(struct inode *inode, struct file *file, unsigned int mode) > { > - struct mm_struct *mm = proc_mem_open(inode, mode); > + struct mm_struct *mm = proc_mem_open(inode, mode, file->f_mode); > > if (IS_ERR(mm)) > return PTR_ERR(mm); > diff --git a/fs/proc/internal.h b/fs/proc/internal.h > index 0f1692e..8d38cc7 100644 > --- a/fs/proc/internal.h > +++ b/fs/proc/internal.h > @@ -275,7 +275,8 @@ struct proc_maps_private { > #endif > } __randomize_layout; > > -struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode); > +struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode, > + fmode_t f_mode); > > extern const struct file_operations proc_pid_maps_operations; > extern const struct file_operations proc_tid_maps_operations; > diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c > index c486ad4..efb6535 100644 > --- a/fs/proc/task_mmu.c > +++ b/fs/proc/task_mmu.c > @@ -227,7 +227,7 @@ static int proc_maps_open(struct inode *inode, struct file *file, > return -ENOMEM; > > priv->inode = inode; > - priv->mm = proc_mem_open(inode, PTRACE_MODE_READ); > + priv->mm = proc_mem_open(inode, PTRACE_MODE_READ, file->f_mode); > if (IS_ERR(priv->mm)) { > int err = PTR_ERR(priv->mm); > > @@ -1534,7 +1534,7 @@ static int pagemap_open(struct inode *inode, struct file *file) > { > struct mm_struct *mm; > > - mm = proc_mem_open(inode, PTRACE_MODE_READ); > + mm = proc_mem_open(inode, PTRACE_MODE_READ, file->f_mode); > if (IS_ERR(mm)) > return PTR_ERR(mm); > file->private_data = mm; > diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c > index 5b62f57..dc38516 100644 > --- a/fs/proc/task_nommu.c > +++ b/fs/proc/task_nommu.c > @@ -280,7 +280,7 @@ static int maps_open(struct inode *inode, struct file *file, > return -ENOMEM; > > priv->inode = inode; > - priv->mm = proc_mem_open(inode, PTRACE_MODE_READ); > + priv->mm = proc_mem_open(inode, PTRACE_MODE_READ, file->f_mode); > if (IS_ERR(priv->mm)) { > int err = PTR_ERR(priv->mm); > > -- > 1.9.1 > -- Kees Cook Pixel Security ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] proc: prevent a task from writing on its own /proc/*/mem 2018-05-27 0:31 ` Kees Cook @ 2018-05-27 1:33 ` Linus Torvalds 2018-05-27 14:41 ` Kees Cook 2018-05-28 9:32 ` Salvatore Mesoraca 0 siblings, 2 replies; 11+ messages in thread From: Linus Torvalds @ 2018-05-27 1:33 UTC (permalink / raw) To: Kees Cook Cc: Salvatore Mesoraca, Jann Horn, Kernel Hardening, LSM List, Linux Kernel Mailing List, linux-mm, Andrew Morton, Alexey Dobriyan, Akinobu Mita, Dmitry Vyukov, Arnd Bergmann, Davidlohr Bueso On Sat, May 26, 2018 at 5:32 PM Kees Cook <keescook@chromium.org> wrote: > I went through some old threads from 2012 when e268337dfe26 was > introduced, and later when things got looked at during DirtyCOW. There > was discussion about removing FOLL_FORCE (in order to block writes on > a read-only memory region). Side note, we did that for /dev/mem, and things broke. Thus commit f511c0b17b08 "Yes, people use FOLL_FORCE ;)" Side note, that very sam ecommit f511c0b17b08 is also the explanation for why the patch under discussion now seems broken. People really do use "write to /proc/self/mem" as a way to keep the mappings read-only, but have a way to change them when required. Linus ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] proc: prevent a task from writing on its own /proc/*/mem 2018-05-27 1:33 ` Linus Torvalds @ 2018-05-27 14:41 ` Kees Cook 2018-05-28 9:32 ` Salvatore Mesoraca 1 sibling, 0 replies; 11+ messages in thread From: Kees Cook @ 2018-05-27 14:41 UTC (permalink / raw) To: Linus Torvalds Cc: Salvatore Mesoraca, Jann Horn, Kernel Hardening, LSM List, Linux Kernel Mailing List, linux-mm, Andrew Morton, Alexey Dobriyan, Akinobu Mita, Dmitry Vyukov, Arnd Bergmann, Davidlohr Bueso On Sat, May 26, 2018 at 6:33 PM, Linus Torvalds <torvalds@linux-foundation.org> wrote: > Thus commit f511c0b17b08 "Yes, people use FOLL_FORCE ;)" > > Side note, that very sam ecommit f511c0b17b08 is also the explanation for > why the patch under discussion now seems broken. > > People really do use "write to /proc/self/mem" as a way to keep the > mappings read-only, but have a way to change them when required. Ah! Yes, that is the commit I was trying to find. Thanks! -Kees -- Kees Cook Pixel Security ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] proc: prevent a task from writing on its own /proc/*/mem 2018-05-27 1:33 ` Linus Torvalds 2018-05-27 14:41 ` Kees Cook @ 2018-05-28 9:32 ` Salvatore Mesoraca 1 sibling, 0 replies; 11+ messages in thread From: Salvatore Mesoraca @ 2018-05-28 9:32 UTC (permalink / raw) To: Linus Torvalds Cc: Kees Cook, Jann Horn, Kernel Hardening, LSM List, Linux Kernel Mailing List, linux-mm, Andrew Morton, Alexey Dobriyan, Akinobu Mita, Dmitry Vyukov, Arnd Bergmann, Davidlohr Bueso 2018-05-27 3:33 GMT+02:00 Linus Torvalds <torvalds@linux-foundation.org>: > On Sat, May 26, 2018 at 5:32 PM Kees Cook <keescook@chromium.org> wrote: > >> I went through some old threads from 2012 when e268337dfe26 was >> introduced, and later when things got looked at during DirtyCOW. There >> was discussion about removing FOLL_FORCE (in order to block writes on >> a read-only memory region). > > Side note, we did that for /dev/mem, and things broke. > > Thus commit f511c0b17b08 "Yes, people use FOLL_FORCE ;)" > > Side note, that very sam ecommit f511c0b17b08 is also the explanation for > why the patch under discussion now seems broken. > > People really do use "write to /proc/self/mem" as a way to keep the > mappings read-only, but have a way to change them when required. Oh, I didn't expect this, interesting... A configurable LSM is probably the right way to do this. Thank you for your time, Salvatore ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] proc: prevent a task from writing on its own /proc/*/mem 2018-05-26 14:50 [PATCH] proc: prevent a task from writing on its own /proc/*/mem Salvatore Mesoraca 2018-05-26 15:48 ` Alexey Dobriyan 2018-05-27 0:31 ` Kees Cook @ 2018-05-28 9:06 ` Jann Horn 2018-05-28 9:33 ` Salvatore Mesoraca 2 siblings, 1 reply; 11+ messages in thread From: Jann Horn @ 2018-05-28 9:06 UTC (permalink / raw) To: Salvatore Mesoraca Cc: Kernel Hardening, linux-security-module, kernel list, Linux-MM, Andrew Morton, Alexey Dobriyan, Akinobu Mita, Dmitry Vyukov, Arnd Bergmann, Davidlohr Bueso, Kees Cook On Sat, May 26, 2018 at 4:50 PM, Salvatore Mesoraca <s.mesoraca16@gmail.com> wrote: > Prevent a task from opening, in "write" mode, any /proc/*/mem > file that operates on the task's mm. > /proc/*/mem is mainly a debugging means and, as such, it shouldn't > be used by the inspected process itself. > Current implementation always allow a task to access its own > /proc/*/mem file. > A process can use it to overwrite read-only memory, making > pointless the use of security_file_mprotect() or other ways to > enforce RO memory. > > Signed-off-by: Salvatore Mesoraca <s.mesoraca16@gmail.com> > --- > fs/proc/base.c | 25 ++++++++++++++++++------- > fs/proc/internal.h | 3 ++- > fs/proc/task_mmu.c | 4 ++-- > fs/proc/task_nommu.c | 2 +- > 4 files changed, 23 insertions(+), 11 deletions(-) > > diff --git a/fs/proc/base.c b/fs/proc/base.c > index 1a76d75..01ecfec 100644 > --- a/fs/proc/base.c > +++ b/fs/proc/base.c > @@ -762,8 +762,9 @@ static int proc_single_open(struct inode *inode, struct file *filp) > .release = single_release, > }; > > - > -struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode) > +struct mm_struct *proc_mem_open(struct inode *inode, > + unsigned int mode, > + fmode_t f_mode) > { > struct task_struct *task = get_proc_task(inode); > struct mm_struct *mm = ERR_PTR(-ESRCH); > @@ -773,10 +774,20 @@ struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode) > put_task_struct(task); > > if (!IS_ERR_OR_NULL(mm)) { > - /* ensure this mm_struct can't be freed */ > - mmgrab(mm); > - /* but do not pin its memory */ > - mmput(mm); > + /* > + * Prevent this interface from being used as a mean > + * to bypass memory restrictions, including those > + * imposed by LSMs. > + */ > + if (mm == current->mm && > + f_mode & FMODE_WRITE) > + mm = ERR_PTR(-EACCES); > + else { > + /* ensure this mm_struct can't be freed */ > + mmgrab(mm); > + /* but do not pin its memory */ > + mmput(mm); > + } > } > } I don't have an opinion on the overall patch, but this part looks buggy: In the error path, you set `mm` to an error pointer, but you still own the reference that mm_access() took on the old `mm`. The error path needs to call `mmput(mm)`. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] proc: prevent a task from writing on its own /proc/*/mem 2018-05-28 9:06 ` Jann Horn @ 2018-05-28 9:33 ` Salvatore Mesoraca 0 siblings, 0 replies; 11+ messages in thread From: Salvatore Mesoraca @ 2018-05-28 9:33 UTC (permalink / raw) To: Jann Horn Cc: Kernel Hardening, linux-security-module, kernel list, Linux-MM, Andrew Morton, Alexey Dobriyan, Akinobu Mita, Dmitry Vyukov, Arnd Bergmann, Davidlohr Bueso, Kees Cook 2018-05-28 11:06 GMT+02:00 Jann Horn <jannh@google.com>: > On Sat, May 26, 2018 at 4:50 PM, Salvatore Mesoraca > <s.mesoraca16@gmail.com> wrote: >> Prevent a task from opening, in "write" mode, any /proc/*/mem >> file that operates on the task's mm. >> /proc/*/mem is mainly a debugging means and, as such, it shouldn't >> be used by the inspected process itself. >> Current implementation always allow a task to access its own >> /proc/*/mem file. >> A process can use it to overwrite read-only memory, making >> pointless the use of security_file_mprotect() or other ways to >> enforce RO memory. >> >> Signed-off-by: Salvatore Mesoraca <s.mesoraca16@gmail.com> >> --- >> fs/proc/base.c | 25 ++++++++++++++++++------- >> fs/proc/internal.h | 3 ++- >> fs/proc/task_mmu.c | 4 ++-- >> fs/proc/task_nommu.c | 2 +- >> 4 files changed, 23 insertions(+), 11 deletions(-) >> >> diff --git a/fs/proc/base.c b/fs/proc/base.c >> index 1a76d75..01ecfec 100644 >> --- a/fs/proc/base.c >> +++ b/fs/proc/base.c >> @@ -762,8 +762,9 @@ static int proc_single_open(struct inode *inode, struct file *filp) >> .release = single_release, >> }; >> >> - >> -struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode) >> +struct mm_struct *proc_mem_open(struct inode *inode, >> + unsigned int mode, >> + fmode_t f_mode) >> { >> struct task_struct *task = get_proc_task(inode); >> struct mm_struct *mm = ERR_PTR(-ESRCH); >> @@ -773,10 +774,20 @@ struct mm_struct *proc_mem_open(struct inode *inode, unsigned int mode) >> put_task_struct(task); >> >> if (!IS_ERR_OR_NULL(mm)) { >> - /* ensure this mm_struct can't be freed */ >> - mmgrab(mm); >> - /* but do not pin its memory */ >> - mmput(mm); >> + /* >> + * Prevent this interface from being used as a mean >> + * to bypass memory restrictions, including those >> + * imposed by LSMs. >> + */ >> + if (mm == current->mm && >> + f_mode & FMODE_WRITE) >> + mm = ERR_PTR(-EACCES); >> + else { >> + /* ensure this mm_struct can't be freed */ >> + mmgrab(mm); >> + /* but do not pin its memory */ >> + mmput(mm); >> + } >> } >> } > > I don't have an opinion on the overall patch, but this part looks > buggy: In the error path, you set `mm` to an error pointer, but you > still own the reference that mm_access() took on the old `mm`. The > error path needs to call `mmput(mm)`. You are absolutely right, Thank you, Salvatore ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2018-05-28 9:33 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2018-05-26 14:50 [PATCH] proc: prevent a task from writing on its own /proc/*/mem Salvatore Mesoraca 2018-05-26 15:48 ` Alexey Dobriyan 2018-05-26 17:30 ` Salvatore Mesoraca 2018-05-26 17:53 ` Casey Schaufler 2018-05-26 17:58 ` Alexey Dobriyan 2018-05-27 0:31 ` Kees Cook 2018-05-27 1:33 ` Linus Torvalds 2018-05-27 14:41 ` Kees Cook 2018-05-28 9:32 ` Salvatore Mesoraca 2018-05-28 9:06 ` Jann Horn 2018-05-28 9:33 ` Salvatore Mesoraca
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox