[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <YmGTRQA74n/ZF7Vl@arm.com>
Date: Thu, 21 Apr 2022 18:24:21 +0100
From: Catalin Marinas <catalin.marinas@....com>
To: Kees Cook <keescook@...omium.org>
Cc: Topi Miettinen <toiwoton@...il.com>,
Andrew Morton <akpm@...ux-foundation.org>,
Christoph Hellwig <hch@...radead.org>,
Lennart Poettering <lennart@...ttering.net>,
Zbigniew Jędrzejewski-Szmek <zbyszek@...waw.pl>,
Will Deacon <will@...nel.org>,
Alexander Viro <viro@...iv.linux.org.uk>,
Eric Biederman <ebiederm@...ssion.com>,
Szabolcs Nagy <szabolcs.nagy@....com>,
Mark Brown <broonie@...nel.org>,
Jeremy Linton <jeremy.linton@....com>, linux-mm@...ck.org,
linux-arm-kernel@...ts.infradead.org, linux-kernel@...r.kernel.org,
linux-abi-devel@...ts.sourceforge.net,
linux-hardening@...r.kernel.org, Jann Horn <jannh@...gle.com>,
Salvatore Mesoraca <s.mesoraca16@...il.com>,
Igor Zhbanov <izh1979@...il.com>
Subject: Re: [PATCH RFC 0/4] mm, arm64: In-kernel support for
memory-deny-write-execute (MDWE)
On Thu, Apr 21, 2022 at 09:42:23AM -0700, Kees Cook wrote:
> On Thu, Apr 21, 2022 at 04:35:15PM +0100, Catalin Marinas wrote:
> > Do we want the "was PROT_WRITE" or we just reject mprotect(PROT_EXEC) if
> > the vma is not already PROT_EXEC? The latter is closer to the current
> > systemd approach. The former allows an mprotect(PROT_EXEC) if the
> > mapping was PROT_READ only for example.
> >
> > I'd drop the "was PROT_WRITE" for now if the aim is a drop-in
> > replacement for BPF MDWE.
>
> I think "was PROT_WRITE" is an important part of the defense that
> couldn't be done with a simple seccomp filter (which is why the filter
> ended up being a problem in the first place).
I would say "was PROT_WRITE" is slightly more relaxed than "is not
already PROT_EXEC". The seccomp filter can't do "is not already
PROT_EXEC" either since it only checks the mprotect() arguments, not the
current vma flags.
So we have (with sub-cases):
1. Current BPF filter:
a) mmap(PROT_READ|PROT_WRITE|PROT_EXEC); // fails
b) mmap(PROT_READ|PROT_EXEC);
mprotect(PROT_READ|PROT_EXEC|PROT_BTI); // fails
2. "is not already PROT_EXEC":
a) mmap(PROT_READ|PROT_WRITE|PROT_EXEC); // fails
b) mmap(PROT_READ|PROT_EXEC);
mmap(PROT_READ|PROT_EXEC|PROT_BTI); // passes
c) mmap(PROT_READ);
mprotect(PROT_READ|PROT_EXEC); // fails
3. "is or was not PROT_WRITE":
a) mmap(PROT_READ|PROT_WRITE|PROT_EXEC); // fails
b) mmap(PROT_READ|PROT_EXEC);
mmap(PROT_READ|PROT_EXEC|PROT_BTI); // passes
c) mmap(PROT_READ);
mprotect(PROT_READ|PROT_EXEC); // passes
d) mmap(PROT_READ|PROT_WRITE);
mprotect(PROT_READ);
mprotect(PROT_READ|PROT_EXEC); // fails (was write)
The current seccomp filter is the strictest. If we go for (2), it allows
PROT_BTI as in 2.b but prevents 2.c (as would the current seccomp
filter). (3) relaxes 2.c as in 3.c while still preventing 3.d. Both (1)
and (2) prevent 3.d by simply rejecting mprotect(PROT_EXEC).
If we don't care about 3.c, we might as well go for (2). I don't mind,
already went for (3) in this series. I think either of them would not be
a regression on MDWE, unless there is some test that attempts 3.c and
expects it to fail.
--
Catalin
Powered by blists - more mailing lists