From: Michal Hocko <mhocko@kernel.org> Date: 2017-11-13 09:20:14
[Cc arm and ppc maintainers]
Thanks a lot for testing!
On Sun 12-11-17 11:38:02, Joel Stanley wrote:
On Fri, Nov 10, 2017 at 11:00 PM, Michal Hocko [off-list ref] wrote:
quoted
Hi Joel,
On Wed 08-11-17 15:20:50, Michal Hocko wrote:
[...]
quoted
quoted
There are a lot of messages on the way up that look like this:
[ 2.527460] Uhuuh, elf segement at 000d9000 requested but the
memory is mapped already
[ 2.540160] Uhuuh, elf segement at 000d9000 requested but the
memory is mapped already
[ 2.546153] Uhuuh, elf segement at 000d9000 requested but the
memory is mapped already
And then trying to run userspace looks like this:
Did you have chance to test with this debugging patch, please?
Lots of this:
[ 1.177266] Uhuuh, elf segement at 000d9000 requested but the memory is mapped already, got 000dd000
[ 1.177555] Clashing vma [dd000, de000] flags:100873 name:(null)
This smells like the problem I've expected that mmap with hint doesn't
respect the hint even though there is no clashing mapping. The above
basically says that we didn't map at 0xd9000 but it has placed it at
0xdd000. The nearest (clashing) vma is at 0xdd000 so this is our new
mapping. find_vma returns the closest vma (with addr < vm_end) for the
given address 0xd9000 so this address cannot be mapped by any other vma.
Now that I am looking at arm's arch_get_unmapped_area it does perform
aligning for shared vmas. We do not do that for MAP_FIXED. Powepc,
reported earlier [1] seems to suffer from the similar problem.
slice_get_unmapped_area alignes to slices, whatever that means.
I can see two possible ways around that. Either we explicitly request
non-aligned mappings via a special MAP_$FOO (e.g. MAP_FIXED_SAFE) or
simply opt out from the MAP_FIXED protection via ifdefs. The first
option sounds more generic to me but also more tricky to not introduce
other user visible effects. The later is quite straightforward. What do
you think about the following on top of the previous patch?
It is rather terse and disables the MAP_FIXED protection for arm
comletely because I couldn't find a way to make it conditional on
CACHEID_VIPT_ALIASING. But this can be always handled later. I find the
protection for other archtectures useful enough to have this working for
most architectures now and handle others specially.
[1] http://lkml.kernel.org/r/1510048229.12079.7.camel@abdul.in.ibm.com
---
@@ -99,6 +99,7 @@ config ARMselectPERF_USE_VMALLOCselectRTC_LIBselectSYS_SUPPORTS_APM_EMULATION+selectARCH_ALIGNED_MMAPS# Above selects are sorted alphabetically; please add new ones# according to that. Thanks.help
From: Russell King - ARM Linux <linux@armlinux.org.uk> Date: 2017-11-13 09:34:47
On Mon, Nov 13, 2017 at 10:20:06AM +0100, Michal Hocko wrote:
[Cc arm and ppc maintainers]
Thanks a lot for testing!
On Sun 12-11-17 11:38:02, Joel Stanley wrote:
quoted
On Fri, Nov 10, 2017 at 11:00 PM, Michal Hocko [off-list ref] wrote:
quoted
Hi Joel,
On Wed 08-11-17 15:20:50, Michal Hocko wrote:
[...]
quoted
quoted
There are a lot of messages on the way up that look like this:
[ 2.527460] Uhuuh, elf segement at 000d9000 requested but the
memory is mapped already
[ 2.540160] Uhuuh, elf segement at 000d9000 requested but the
memory is mapped already
[ 2.546153] Uhuuh, elf segement at 000d9000 requested but the
memory is mapped already
And then trying to run userspace looks like this:
Did you have chance to test with this debugging patch, please?
Lots of this:
[ 1.177266] Uhuuh, elf segement at 000d9000 requested but the memory is mapped already, got 000dd000
[ 1.177555] Clashing vma [dd000, de000] flags:100873 name:(null)
This smells like the problem I've expected that mmap with hint doesn't
respect the hint even though there is no clashing mapping. The above
basically says that we didn't map at 0xd9000 but it has placed it at
0xdd000. The nearest (clashing) vma is at 0xdd000 so this is our new
mapping. find_vma returns the closest vma (with addr < vm_end) for the
given address 0xd9000 so this address cannot be mapped by any other vma.
Now that I am looking at arm's arch_get_unmapped_area it does perform
aligning for shared vmas. We do not do that for MAP_FIXED. Powepc,
reported earlier [1] seems to suffer from the similar problem.
slice_get_unmapped_area alignes to slices, whatever that means.
I can see two possible ways around that. Either we explicitly request
non-aligned mappings via a special MAP_$FOO (e.g. MAP_FIXED_SAFE) or
simply opt out from the MAP_FIXED protection via ifdefs. The first
option sounds more generic to me but also more tricky to not introduce
other user visible effects. The later is quite straightforward. What do
you think about the following on top of the previous patch?
It is rather terse and disables the MAP_FIXED protection for arm
comletely because I couldn't find a way to make it conditional on
CACHEID_VIPT_ALIASING. But this can be always handled later. I find the
protection for other archtectures useful enough to have this working for
most architectures now and handle others specially.
Can someone provide the background information for this please?
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
From: Michal Hocko <mhocko@kernel.org> Date: 2017-11-13 09:42:09
On Mon 13-11-17 10:20:06, Michal Hocko wrote:
[Cc arm and ppc maintainers]
Hmm, it turned out to be a problem on other architectures as well.
CCing more maintainers. For your reference, we are talking about
http://lkml.kernel.org/r/20171023082608.6167-1-mhocko@kernel.org
which has broken architectures which do apply aligning on the mmap
address hint without MAP_FIXED applied. See below my proposed way
around this issue because I belive that the above patch is quite
valuable on its own to be dropped for all archs.
Thanks a lot for testing!
On Sun 12-11-17 11:38:02, Joel Stanley wrote:
quoted
On Fri, Nov 10, 2017 at 11:00 PM, Michal Hocko [off-list ref] wrote:
quoted
Hi Joel,
On Wed 08-11-17 15:20:50, Michal Hocko wrote:
[...]
quoted
quoted
There are a lot of messages on the way up that look like this:
[ 2.527460] Uhuuh, elf segement at 000d9000 requested but the
memory is mapped already
[ 2.540160] Uhuuh, elf segement at 000d9000 requested but the
memory is mapped already
[ 2.546153] Uhuuh, elf segement at 000d9000 requested but the
memory is mapped already
And then trying to run userspace looks like this:
Did you have chance to test with this debugging patch, please?
Lots of this:
[ 1.177266] Uhuuh, elf segement at 000d9000 requested but the memory is mapped already, got 000dd000
[ 1.177555] Clashing vma [dd000, de000] flags:100873 name:(null)
This smells like the problem I've expected that mmap with hint doesn't
respect the hint even though there is no clashing mapping. The above
basically says that we didn't map at 0xd9000 but it has placed it at
0xdd000. The nearest (clashing) vma is at 0xdd000 so this is our new
mapping. find_vma returns the closest vma (with addr < vm_end) for the
given address 0xd9000 so this address cannot be mapped by any other vma.
Now that I am looking at arm's arch_get_unmapped_area it does perform
aligning for shared vmas. We do not do that for MAP_FIXED. Powepc,
reported earlier [1] seems to suffer from the similar problem.
slice_get_unmapped_area alignes to slices, whatever that means.
I can see two possible ways around that. Either we explicitly request
non-aligned mappings via a special MAP_$FOO (e.g. MAP_FIXED_SAFE) or
simply opt out from the MAP_FIXED protection via ifdefs. The first
option sounds more generic to me but also more tricky to not introduce
other user visible effects. The later is quite straightforward. What do
you think about the following on top of the previous patch?
It is rather terse and disables the MAP_FIXED protection for arm
comletely because I couldn't find a way to make it conditional on
CACHEID_VIPT_ALIASING. But this can be always handled later. I find the
protection for other archtectures useful enough to have this working for
most architectures now and handle others specially.
[1] http://lkml.kernel.org/r/1510048229.12079.7.camel@abdul.in.ibm.com
---
@@ -99,6 +99,7 @@ config ARMselectPERF_USE_VMALLOCselectRTC_LIBselectSYS_SUPPORTS_APM_EMULATION+selectARCH_ALIGNED_MMAPS# Above selects are sorted alphabetically; please add new ones# according to that. Thanks.help
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2017-11-13 11:34:56
Hi Michal,
Michal Hocko [off-list ref] writes:
On Mon 13-11-17 10:20:06, Michal Hocko wrote:
quoted
[Cc arm and ppc maintainers]
Hmm, it turned out to be a problem on other architectures as well.
CCing more maintainers. For your reference, we are talking about
http://lkml.kernel.org/r/20171023082608.6167-1-mhocko@kernel.org
which has broken architectures which do apply aligning on the mmap
address hint without MAP_FIXED applied. See below my proposed way
around this issue because I belive that the above patch is quite
valuable on its own to be dropped for all archs.
I don't really like your solution sorry :) The fact that you've had to
patch seven arches seems like a red flag.
I think this is a generic problem with MAP_FIXED, which I've heard
userspace folks complain about in the past.
Currently MAP_FIXED does two things:
1. makes addr not a hint but the required address
2. blasts any existing mapping
You want 1) but not 2).
So the right solution IMHO would be to add a new mmap flag to request
that behaviour, ie. a fixed address but iff there is nothing already
mapped there.
I don't know the mm code well enough to know if that's hard for some
reason, but it *seems* like it should be doable.
cheers
From: Michal Hocko <mhocko@kernel.org> Date: 2017-11-13 12:01:06
On Mon 13-11-17 22:34:50, Michael Ellerman wrote:
Hi Michal,
Michal Hocko [off-list ref] writes:
quoted
On Mon 13-11-17 10:20:06, Michal Hocko wrote:
quoted
[Cc arm and ppc maintainers]
Hmm, it turned out to be a problem on other architectures as well.
CCing more maintainers. For your reference, we are talking about
http://lkml.kernel.org/r/20171023082608.6167-1-mhocko@kernel.org
which has broken architectures which do apply aligning on the mmap
address hint without MAP_FIXED applied. See below my proposed way
around this issue because I belive that the above patch is quite
valuable on its own to be dropped for all archs.
I don't really like your solution sorry :) The fact that you've had to
patch seven arches seems like a red flag.
I think this is a generic problem with MAP_FIXED, which I've heard
userspace folks complain about in the past.
The thing is that we canno change MAP_FIXED behavior as it is carved in
stone
Currently MAP_FIXED does two things:
1. makes addr not a hint but the required address
2. blasts any existing mapping
You want 1) but not 2).
+ fail if there is a clashing range
So the right solution IMHO would be to add a new mmap flag to request
that behaviour, ie. a fixed address but iff there is nothing already
mapped there.
I don't know the mm code well enough to know if that's hard for some
reason, but it *seems* like it should be doable.
Yes, I have mentioned that in the previous email but the amount of code
would be even larger. Basically every arch which reimplements
arch_get_unmapped_area would have to special case new MAP_FIXED flag to
do vma lookup. So this was the most simple solution I could come up
with. If there was a general interest for MAP_FIXED_SAFE then we can
introduce it later of course. I would just like the hardening merged
sooner rather than later.
--
Michal Hocko
SUSE Labs
From: Michal Hocko <mhocko@kernel.org> Date: 2017-11-13 14:11:45
On Mon 13-11-17 10:20:06, Michal Hocko wrote:
[Cc arm and ppc maintainers]
Thanks a lot for testing!
On Sun 12-11-17 11:38:02, Joel Stanley wrote:
quoted
On Fri, Nov 10, 2017 at 11:00 PM, Michal Hocko [off-list ref] wrote:
quoted
Hi Joel,
On Wed 08-11-17 15:20:50, Michal Hocko wrote:
[...]
quoted
quoted
There are a lot of messages on the way up that look like this:
[ 2.527460] Uhuuh, elf segement at 000d9000 requested but the
memory is mapped already
[ 2.540160] Uhuuh, elf segement at 000d9000 requested but the
memory is mapped already
[ 2.546153] Uhuuh, elf segement at 000d9000 requested but the
memory is mapped already
And then trying to run userspace looks like this:
Did you have chance to test with this debugging patch, please?
Lots of this:
[ 1.177266] Uhuuh, elf segement at 000d9000 requested but the memory is mapped already, got 000dd000
[ 1.177555] Clashing vma [dd000, de000] flags:100873 name:(null)
This smells like the problem I've expected that mmap with hint doesn't
respect the hint even though there is no clashing mapping. The above
basically says that we didn't map at 0xd9000 but it has placed it at
0xdd000. The nearest (clashing) vma is at 0xdd000 so this is our new
mapping. find_vma returns the closest vma (with addr < vm_end) for the
given address 0xd9000 so this address cannot be mapped by any other vma.
Now that I am looking at arm's arch_get_unmapped_area it does perform
aligning for shared vmas.
Sorry for confusion here. These are not shared mappings as pointed out
by Russell in a private email. I got confused by the above flags which I
have misinterpreted as bit 0 set => MAP_SHARED. These are vm_flags
obviously so the bit 0 is VM_READ. Sorry about the confusion. The real
reason we are doing the alignment is that we do a file mapping
/*
* We only need to do colour alignment if either the I or D
* caches alias.
*/
if (aliasing)
do_align = filp || (flags & MAP_SHARED);
I am not really familiar with this architecture to understand why do we
need aliasing for file mappings, though.
--
Michal Hocko
SUSE Labs
From: Russell King - ARM Linux <linux@armlinux.org.uk> Date: 2017-11-13 15:09:35
On Mon, Nov 13, 2017 at 03:11:40PM +0100, Michal Hocko wrote:
On Mon 13-11-17 10:20:06, Michal Hocko wrote:
quoted
[Cc arm and ppc maintainers]
Thanks a lot for testing!
On Sun 12-11-17 11:38:02, Joel Stanley wrote:
quoted
On Fri, Nov 10, 2017 at 11:00 PM, Michal Hocko [off-list ref] wrote:
quoted
Hi Joel,
On Wed 08-11-17 15:20:50, Michal Hocko wrote:
[...]
quoted
quoted
There are a lot of messages on the way up that look like this:
[ 2.527460] Uhuuh, elf segement at 000d9000 requested but the
memory is mapped already
[ 2.540160] Uhuuh, elf segement at 000d9000 requested but the
memory is mapped already
[ 2.546153] Uhuuh, elf segement at 000d9000 requested but the
memory is mapped already
And then trying to run userspace looks like this:
Did you have chance to test with this debugging patch, please?
Lots of this:
[ 1.177266] Uhuuh, elf segement at 000d9000 requested but the memory is mapped already, got 000dd000
[ 1.177555] Clashing vma [dd000, de000] flags:100873 name:(null)
This smells like the problem I've expected that mmap with hint doesn't
respect the hint even though there is no clashing mapping. The above
basically says that we didn't map at 0xd9000 but it has placed it at
0xdd000. The nearest (clashing) vma is at 0xdd000 so this is our new
mapping. find_vma returns the closest vma (with addr < vm_end) for the
given address 0xd9000 so this address cannot be mapped by any other vma.
Now that I am looking at arm's arch_get_unmapped_area it does perform
aligning for shared vmas.
Sorry for confusion here. These are not shared mappings as pointed out
by Russell in a private email. I got confused by the above flags which I
have misinterpreted as bit 0 set => MAP_SHARED. These are vm_flags
obviously so the bit 0 is VM_READ. Sorry about the confusion. The real
reason we are doing the alignment is that we do a file mapping
/*
* We only need to do colour alignment if either the I or D
* caches alias.
*/
if (aliasing)
do_align = filp || (flags & MAP_SHARED);
I am not really familiar with this architecture to understand why do we
need aliasing for file mappings, though.
I think it's there so that flush_dcache_page() works - possibly
get_user_pages() being used on a private mapping of page cache pages,
but that's guessing.
I'm afraid I don't remember all the details, this is code from around
15 years ago, and I'd be very nervous about changing it now without
fully understanding the issues.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
From: Michal Hocko <mhocko@kernel.org> Date: 2017-11-13 15:16:51
On Mon 13-11-17 13:00:57, Michal Hocko wrote:
[...]
Yes, I have mentioned that in the previous email but the amount of code
would be even larger. Basically every arch which reimplements
arch_get_unmapped_area would have to special case new MAP_FIXED flag to
do vma lookup.
It turned out that this might be much more easier than I thought after
all. It seems we can really handle that in the common code. This would
mean that we are exposing a new functionality to the userspace though.
Myabe this would be useful on its own though. Just a quick draft (not
even compile tested) whether this makes sense in general. I would be
worried about unexpected behavior when somebody set other bit without a
good reason and we might fail with ENOMEM for such a call now.
Elf loader would then use MAP_FIXED_SAFE rather than MAP_FIXED.
---
@@ -49,6 +49,9 @@#define MAP_STACK 0x40000 /* give out an address that is best suited for process/thread stacks */#define MAP_HUGETLB 0x80000 /* create a huge page mapping */+#define MAP_KEEP_MAPPING 0x2000000+#define MAP_FIXED_SAFE MAP_FIXED|MAP_KEEP_MAPPING /* enforce MAP_FIXED without clobbering an existing mapping */+/**Flagsformsync*/
From: Michal Hocko <mhocko@kernel.org> Date: 2017-11-13 15:31:46
On Mon 13-11-17 15:09:09, Russell King - ARM Linux wrote:
On Mon, Nov 13, 2017 at 03:11:40PM +0100, Michal Hocko wrote:
quoted
On Mon 13-11-17 10:20:06, Michal Hocko wrote:
quoted
[Cc arm and ppc maintainers]
Thanks a lot for testing!
On Sun 12-11-17 11:38:02, Joel Stanley wrote:
quoted
On Fri, Nov 10, 2017 at 11:00 PM, Michal Hocko [off-list ref] wrote:
quoted
Hi Joel,
On Wed 08-11-17 15:20:50, Michal Hocko wrote:
[...]
quoted
quoted
There are a lot of messages on the way up that look like this:
[ 2.527460] Uhuuh, elf segement at 000d9000 requested but the
memory is mapped already
[ 2.540160] Uhuuh, elf segement at 000d9000 requested but the
memory is mapped already
[ 2.546153] Uhuuh, elf segement at 000d9000 requested but the
memory is mapped already
And then trying to run userspace looks like this:
Did you have chance to test with this debugging patch, please?
Lots of this:
[ 1.177266] Uhuuh, elf segement at 000d9000 requested but the memory is mapped already, got 000dd000
[ 1.177555] Clashing vma [dd000, de000] flags:100873 name:(null)
This smells like the problem I've expected that mmap with hint doesn't
respect the hint even though there is no clashing mapping. The above
basically says that we didn't map at 0xd9000 but it has placed it at
0xdd000. The nearest (clashing) vma is at 0xdd000 so this is our new
mapping. find_vma returns the closest vma (with addr < vm_end) for the
given address 0xd9000 so this address cannot be mapped by any other vma.
Now that I am looking at arm's arch_get_unmapped_area it does perform
aligning for shared vmas.
Sorry for confusion here. These are not shared mappings as pointed out
by Russell in a private email. I got confused by the above flags which I
have misinterpreted as bit 0 set => MAP_SHARED. These are vm_flags
obviously so the bit 0 is VM_READ. Sorry about the confusion. The real
reason we are doing the alignment is that we do a file mapping
/*
* We only need to do colour alignment if either the I or D
* caches alias.
*/
if (aliasing)
do_align = filp || (flags & MAP_SHARED);
I am not really familiar with this architecture to understand why do we
need aliasing for file mappings, though.
I think it's there so that flush_dcache_page() works - possibly
get_user_pages() being used on a private mapping of page cache pages,
but that's guessing.
I fail to see how the mixure of MAP_FIXED and regular mapping of the
same file work then, but as I've said I really do not understand this
code.
I'm afraid I don't remember all the details, this is code from around
15 years ago, and I'd be very nervous about changing it now without
fully understanding the issues.
Ohh, absolutely! I didn't dare to touch this code and that's why I took
the easy way and simply opt-out from the harding for all those archs
that are basically sharing this pattern. But after a closer look it
seems that we can really introduce MAP_FIXED_SAFE that would keep the
arch mmap code intact yet we would get the hardening for all archs.
It would allow also allow a safer MAP_FIXED semantic for userspace.
--
Michal Hocko
SUSE Labs
From: Russell King - ARM Linux <linux@armlinux.org.uk> Date: 2017-11-13 15:48:42
On Mon, Nov 13, 2017 at 04:16:41PM +0100, Michal Hocko wrote:
quoted hunk
On Mon 13-11-17 13:00:57, Michal Hocko wrote:
[...]
quoted
Yes, I have mentioned that in the previous email but the amount of code
would be even larger. Basically every arch which reimplements
arch_get_unmapped_area would have to special case new MAP_FIXED flag to
do vma lookup.
It turned out that this might be much more easier than I thought after
all. It seems we can really handle that in the common code. This would
mean that we are exposing a new functionality to the userspace though.
Myabe this would be useful on its own though. Just a quick draft (not
even compile tested) whether this makes sense in general. I would be
worried about unexpected behavior when somebody set other bit without a
good reason and we might fail with ENOMEM for such a call now.
Elf loader would then use MAP_FIXED_SAFE rather than MAP_FIXED.
---
@@ -31,6 +31,9 @@#define MAP_STACK 0x80000 /* give out an address that is best suited for process/thread stacks */#define MAP_HUGETLB 0x100000 /* create a huge page mapping */+#define MAP_KEEP_MAPPING 0x2000000+#define MAP_FIXED_SAFE MAP_FIXED|MAP_KEEP_MAPPING /* enforce MAP_FIXED without clobbering an existing mapping */
A few things...
1. Does this need to be exposed to userland?
2. Can it end up in include/uapi/asm-generic/mman*.h ?
3. The definition of MAP_FIXED_SAFE should really have parens around it.
quoted hunk
@@ -1365,6 +1365,13 @@ unsigned long do_mmap(struct file *file, unsigned long addr, if (offset_in_page(addr)) return addr;+ if ((flags & MAP_FIXED_SAFE) == MAP_FIXED_SAFE) {
I'm surprised this doesn't warn - since this effectively expands to:
flags & MAP_FIXED | MAP_KEEP_MAPPING
hence why MAP_FIXED_SAFE needs parens.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line in suburbia: sync at 8.8Mbps down 630kbps up
According to speedtest.net: 8.21Mbps down 510kbps up
From: Michal Hocko <mhocko@kernel.org> Date: 2017-11-13 15:49:45
On Mon 13-11-17 16:16:41, Michal Hocko wrote:
On Mon 13-11-17 13:00:57, Michal Hocko wrote:
[...]
quoted
Yes, I have mentioned that in the previous email but the amount of code
would be even larger. Basically every arch which reimplements
arch_get_unmapped_area would have to special case new MAP_FIXED flag to
do vma lookup.
It turned out that this might be much more easier than I thought after
all. It seems we can really handle that in the common code. This would
mean that we are exposing a new functionality to the userspace though.
Myabe this would be useful on its own though. Just a quick draft (not
even compile tested) whether this makes sense in general. I would be
worried about unexpected behavior when somebody set other bit without a
good reason and we might fail with ENOMEM for such a call now.
Hmm, the bigger problem would be the backward compatibility actually. We
would get silent corruptions which is exactly what the flag is trying
fix. mmap flags handling really sucks. So I guess we would have to make
the flag internal only :/
--
Michal Hocko
SUSE Labs
From: Michal Hocko <mhocko@kernel.org> Date: 2017-11-13 15:59:19
On Mon 13-11-17 15:48:13, Russell King - ARM Linux wrote:
On Mon, Nov 13, 2017 at 04:16:41PM +0100, Michal Hocko wrote:
quoted
On Mon 13-11-17 13:00:57, Michal Hocko wrote:
[...]
quoted
Yes, I have mentioned that in the previous email but the amount of code
would be even larger. Basically every arch which reimplements
arch_get_unmapped_area would have to special case new MAP_FIXED flag to
do vma lookup.
It turned out that this might be much more easier than I thought after
all. It seems we can really handle that in the common code. This would
mean that we are exposing a new functionality to the userspace though.
Myabe this would be useful on its own though. Just a quick draft (not
even compile tested) whether this makes sense in general. I would be
worried about unexpected behavior when somebody set other bit without a
good reason and we might fail with ENOMEM for such a call now.
Elf loader would then use MAP_FIXED_SAFE rather than MAP_FIXED.
---
@@ -31,6 +31,9 @@#define MAP_STACK 0x80000 /* give out an address that is best suited for process/thread stacks */#define MAP_HUGETLB 0x100000 /* create a huge page mapping */+#define MAP_KEEP_MAPPING 0x2000000+#define MAP_FIXED_SAFE MAP_FIXED|MAP_KEEP_MAPPING /* enforce MAP_FIXED without clobbering an existing mapping */
A few things...
1. Does this need to be exposed to userland?
As I've written in another email, exposing the flag this way would be
really dangerous wrt. backward compatibility. So we would either need some
translation or make it a flag on its own and touch the arch specific
code which I really wanted to prevent from.
Whether this is something useful for the userspace is a separate
question which I should bring up to linux-api for a wider audience to
discuss.
So I guess this goes down to whether we want/need something like
MAP_FIXED_SAFE or opt out the specific hardening code for arches that
cannot make unaligned mappings for the requested address.
2. Can it end up in include/uapi/asm-generic/mman*.h ?
3. The definition of MAP_FIXED_SAFE should really have parens around it.
Of course. I thought I did...
quoted
@@ -1365,6 +1365,13 @@ unsigned long do_mmap(struct file *file, unsigned long addr, if (offset_in_page(addr)) return addr;+ if ((flags & MAP_FIXED_SAFE) == MAP_FIXED_SAFE) {
I'm surprised this doesn't warn - since this effectively expands to:
flags & MAP_FIXED | MAP_KEEP_MAPPING
hence why MAP_FIXED_SAFE needs parens.
From: Michal Hocko <mhocko@kernel.org> Date: 2017-11-13 16:06:42
[Sorry for spamming, this one is the last attempt hopefully]
On Mon 13-11-17 16:49:39, Michal Hocko wrote:
On Mon 13-11-17 16:16:41, Michal Hocko wrote:
quoted
On Mon 13-11-17 13:00:57, Michal Hocko wrote:
[...]
quoted
Yes, I have mentioned that in the previous email but the amount of code
would be even larger. Basically every arch which reimplements
arch_get_unmapped_area would have to special case new MAP_FIXED flag to
do vma lookup.
It turned out that this might be much more easier than I thought after
all. It seems we can really handle that in the common code. This would
mean that we are exposing a new functionality to the userspace though.
Myabe this would be useful on its own though. Just a quick draft (not
even compile tested) whether this makes sense in general. I would be
worried about unexpected behavior when somebody set other bit without a
good reason and we might fail with ENOMEM for such a call now.
Hmm, the bigger problem would be the backward compatibility actually. We
would get silent corruptions which is exactly what the flag is trying
fix. mmap flags handling really sucks. So I guess we would have to make
the flag internal only :/
OK, so this one should take care of the backward compatibility while
still not touching the arch code
---
commit 39ff9bf8597e79a032da0954aea1f0d77d137765
Author: Michal Hocko [off-list ref]
Date: Mon Nov 13 17:06:24 2017 +0100
mm: introduce MAP_FIXED_SAFE
MAP_FIXED is used quite often but it is inherently dangerous because it
unmaps an existing mapping covered by the requested range. While this
might be might be really desidered behavior in many cases there are
others which would rather see a failure than a silent memory corruption.
Introduce a new MAP_FIXED_SAFE flag for mmap to achive this behavior.
It is a MAP_FIXED extension with a single exception that it fails with
ENOMEM if the requested address is already covered by an existing
mapping. We still do rely on get_unmaped_area to handle all the arch
specific MAP_FIXED treatment and check for a conflicting vma after it
returns.
Signed-off-by: Michal Hocko [off-list ref]
@@ -49,6 +49,8 @@#define MAP_STACK 0x40000 /* give out an address that is best suited for process/thread stacks */#define MAP_HUGETLB 0x80000 /* create a huge page mapping */+#define MAP_FIXED_SAFE 0x2000000 /* MAP_FIXED which doesn't unmap underlying mapping */+/**Flagsformsync*/
@@ -1358,6 +1358,10 @@ unsigned long do_mmap(struct file *file, unsigned long addr,if(mm->map_count>sysctl_max_map_count)return-ENOMEM;+/* force arch specific MAP_FIXED handling in get_unmapped_area */+if(flags&MAP_FIXED_SAFE)+flags|=MAP_FIXED;+/* Obtain the address to map to. we verify (or select) it and ensure*thatitrepresentsavalidsectionoftheaddressspace.*/
@@ -1365,6 +1369,13 @@ unsigned long do_mmap(struct file *file, unsigned long addr,if(offset_in_page(addr))returnaddr;+if(flags&MAP_FIXED_SAFE){+structvm_area_struct*vma=find_vma(mm,addr);++if(vma&&vma->vm_start<=addr)+return-ENOMEM;+}+if(prot==PROT_EXEC){pkey=execute_only_pkey(mm);if(pkey<0)
From: Khalid Aziz <hidden> Date: 2017-11-13 16:37:40
On 11/13/2017 09:06 AM, Michal Hocko wrote:
quoted hunk
OK, so this one should take care of the backward compatibility while
still not touching the arch code
---
commit 39ff9bf8597e79a032da0954aea1f0d77d137765
Author: Michal Hocko [off-list ref]
Date: Mon Nov 13 17:06:24 2017 +0100
mm: introduce MAP_FIXED_SAFE
MAP_FIXED is used quite often but it is inherently dangerous because it
unmaps an existing mapping covered by the requested range. While this
might be might be really desidered behavior in many cases there are
others which would rather see a failure than a silent memory corruption.
Introduce a new MAP_FIXED_SAFE flag for mmap to achive this behavior.
It is a MAP_FIXED extension with a single exception that it fails with
ENOMEM if the requested address is already covered by an existing
mapping. We still do rely on get_unmaped_area to handle all the arch
specific MAP_FIXED treatment and check for a conflicting vma after it
returns.
Signed-off-by: Michal Hocko [off-list ref]
...... deleted .......
@@ -1358,6 +1358,10 @@ unsigned long do_mmap(struct file *file, unsigned long addr,if(mm->map_count>sysctl_max_map_count)return-ENOMEM;+/* force arch specific MAP_FIXED handling in get_unmapped_area */+if(flags&MAP_FIXED_SAFE)+flags|=MAP_FIXED;+/* Obtain the address to map to. we verify (or select) it and ensure*thatitrepresentsavalidsectionoftheaddressspace.*/
Do you need to move this code above:
if (!(flags & MAP_FIXED))
addr = round_hint_to_min(addr);
/* Careful about overflows.. */
len = PAGE_ALIGN(len);
if (!len)
return -ENOMEM;
Not doing that might mean the hint address will end up being rounded for
MAP_FIXED_SAFE which would change the behavior from MAP_FIXED.
--
Khalid
From: Michal Hocko <mhocko@kernel.org> Date: 2017-11-14 07:08:05
On Mon 13-11-17 09:35:22, Khalid Aziz wrote:
On 11/13/2017 09:06 AM, Michal Hocko wrote:
quoted
OK, so this one should take care of the backward compatibility while
still not touching the arch code
---
commit 39ff9bf8597e79a032da0954aea1f0d77d137765
Author: Michal Hocko [off-list ref]
Date: Mon Nov 13 17:06:24 2017 +0100
mm: introduce MAP_FIXED_SAFE
MAP_FIXED is used quite often but it is inherently dangerous because it
unmaps an existing mapping covered by the requested range. While this
might be might be really desidered behavior in many cases there are
others which would rather see a failure than a silent memory corruption.
Introduce a new MAP_FIXED_SAFE flag for mmap to achive this behavior.
It is a MAP_FIXED extension with a single exception that it fails with
ENOMEM if the requested address is already covered by an existing
mapping. We still do rely on get_unmaped_area to handle all the arch
specific MAP_FIXED treatment and check for a conflicting vma after it
returns.
Signed-off-by: Michal Hocko [off-list ref]
...... deleted .......
@@ -1358,6 +1358,10 @@ unsigned long do_mmap(struct file *file, unsigned long addr,if(mm->map_count>sysctl_max_map_count)return-ENOMEM;+/* force arch specific MAP_FIXED handling in get_unmapped_area */+if(flags&MAP_FIXED_SAFE)+flags|=MAP_FIXED;+/* Obtain the address to map to. we verify (or select) it and ensure*thatitrepresentsavalidsectionoftheaddressspace.*/
Do you need to move this code above:
if (!(flags & MAP_FIXED))
addr = round_hint_to_min(addr);
/* Careful about overflows.. */
len = PAGE_ALIGN(len);
if (!len)
return -ENOMEM;
Not doing that might mean the hint address will end up being rounded for
MAP_FIXED_SAFE which would change the behavior from MAP_FIXED.
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2017-11-14 08:55:12
Michal Hocko [off-list ref] writes:
On Mon 13-11-17 22:34:50, Michael Ellerman wrote:
quoted
Hi Michal,
Michal Hocko [off-list ref] writes:
quoted
On Mon 13-11-17 10:20:06, Michal Hocko wrote:
quoted
[Cc arm and ppc maintainers]
Hmm, it turned out to be a problem on other architectures as well.
CCing more maintainers. For your reference, we are talking about
http://lkml.kernel.org/r/20171023082608.6167-1-mhocko@kernel.org
which has broken architectures which do apply aligning on the mmap
address hint without MAP_FIXED applied. See below my proposed way
around this issue because I belive that the above patch is quite
valuable on its own to be dropped for all archs.
I don't really like your solution sorry :) The fact that you've had to
patch seven arches seems like a red flag.
I think this is a generic problem with MAP_FIXED, which I've heard
userspace folks complain about in the past.
The thing is that we canno change MAP_FIXED behavior as it is carved in
stone
Yes obviously. I didn't mean to imply we would change MAP_FIXED, rather
we would add a new flag with the new semantics.
quoted
Currently MAP_FIXED does two things:
1. makes addr not a hint but the required address
2. blasts any existing mapping
You want 1) but not 2).
+ fail if there is a clashing range
Yep. I thought that was implied :)
quoted
So the right solution IMHO would be to add a new mmap flag to request
that behaviour, ie. a fixed address but iff there is nothing already
mapped there.
I don't know the mm code well enough to know if that's hard for some
reason, but it *seems* like it should be doable.
Yes, I have mentioned that in the previous email but the amount of code
would be even larger. Basically every arch which reimplements
arch_get_unmapped_area would have to special case new MAP_FIXED flag to
do vma lookup.
I'd have to look, but my memory of the arch code is that it doesn't deal
with the vma so it wouldn't need any change.
So this was the most simple solution I could come up
with. If there was a general interest for MAP_FIXED_SAFE then we can
introduce it later of course. I would just like the hardening merged
sooner rather than later.
Sure. But in the scheme of things one more kernel release is not that
big a deal to get it right. Given that the simple approach of dropping
MAP_FIXED turns out to not be simple at all.
cheers
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2017-11-14 09:02:21
Michal Hocko [off-list ref] writes:
On Mon 13-11-17 13:00:57, Michal Hocko wrote:
[...]
quoted
Yes, I have mentioned that in the previous email but the amount of code
would be even larger. Basically every arch which reimplements
arch_get_unmapped_area would have to special case new MAP_FIXED flag to
do vma lookup.
It turned out that this might be much more easier than I thought after
all. It seems we can really handle that in the common code.
Ah nice. I should have read this before replying to your previous mail.
This would mean that we are exposing a new functionality to the userspace though.
Myabe this would be useful on its own though.
Just a quick draft (not
even compile tested) whether this makes sense in general. I would be
worried about unexpected behavior when somebody set other bit without a
good reason and we might fail with ENOMEM for such a call now.
Elf loader would then use MAP_FIXED_SAFE rather than MAP_FIXED.
---
@@ -31,6 +31,9 @@#define MAP_STACK 0x80000 /* give out an address that is best suited for process/thread stacks */#define MAP_HUGETLB 0x100000 /* create a huge page mapping */+#define MAP_KEEP_MAPPING 0x2000000+#define MAP_FIXED_SAFE MAP_FIXED|MAP_KEEP_MAPPING /* enforce MAP_FIXED without clobbering an existing mapping */
So bike-shedding a bit, but I think "SAFE" is too vague a name.
Perhaps MAP_NO_CLOBBER - which has the single semantic of "do not
clobber any existing mappings".
It would be a flag on its own, so you could pass it with or without
MAP_FIXED, but it would only change the behaviour when MAP_FIXED is
specified also.
cheers
From: Michal Hocko <mhocko@kernel.org> Date: 2017-11-14 09:05:18
On Tue 14-11-17 19:54:59, Michael Ellerman wrote:
Michal Hocko [off-list ref] writes:
[...]
quoted
So this was the most simple solution I could come up
with. If there was a general interest for MAP_FIXED_SAFE then we can
introduce it later of course. I would just like the hardening merged
sooner rather than later.
Sure. But in the scheme of things one more kernel release is not that
big a deal to get it right. Given that the simple approach of dropping
MAP_FIXED turns out to not be simple at all.
Well, my idea was to push this hardening to older kernels because those
were more vulnerable for the PIE base vs. stack placement and stack
controllable size from userspace etc... Anyway, as per [1] it seems that
the MAP_FIXED_SAFE doesn't look terrible from the backporting POV.
If there is a general consensus that this is the preferred way to go, I
will post the patch as an RFC to linux-api
[1] http://lkml.kernel.org/r/20171113160637.jhekbdyfpccme3be@dhcp22.suse.cz
--
Michal Hocko
SUSE Labs
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2017-11-14 09:18:18
Michal Hocko [off-list ref] writes:
[Sorry for spamming, this one is the last attempt hopefully]
On Mon 13-11-17 16:49:39, Michal Hocko wrote:
quoted
On Mon 13-11-17 16:16:41, Michal Hocko wrote:
quoted
On Mon 13-11-17 13:00:57, Michal Hocko wrote:
[...]
quoted
Yes, I have mentioned that in the previous email but the amount of code
would be even larger. Basically every arch which reimplements
arch_get_unmapped_area would have to special case new MAP_FIXED flag to
do vma lookup.
It turned out that this might be much more easier than I thought after
all. It seems we can really handle that in the common code. This would
mean that we are exposing a new functionality to the userspace though.
Myabe this would be useful on its own though. Just a quick draft (not
even compile tested) whether this makes sense in general. I would be
worried about unexpected behavior when somebody set other bit without a
good reason and we might fail with ENOMEM for such a call now.
Hmm, the bigger problem would be the backward compatibility actually. We
would get silent corruptions which is exactly what the flag is trying
fix. mmap flags handling really sucks. So I guess we would have to make
the flag internal only :/
OK, so this one should take care of the backward compatibility while
still not touching the arch code
I'm not sure I understand your worries about backward compatibility?
If we add a new mmap flag which is currently unused then what is the
problem? Are you worried about user code that accidentally passes that
flag already?
@@ -25,6 +25,8 @@# define MAP_UNINITIALIZED 0x0 /* Don't support this flag */#endif+#define MAP_FIXED_SAFE 0x2000000 /* MAP_FIXED which doesn't unmap underlying mapping */+
As I said in my other mail I think this should be a modifier to
MAP_FIXED. That way all the existing code that checks for MAP_FIXED (in
the kernel) works exactly as it currently does - like the check Khalid
pointed out.
And I think MAP_NO_CLOBBER would be a better name.
cheers
From: Michal Hocko <mhocko@kernel.org> Date: 2017-11-14 09:29:27
On Tue 14-11-17 20:18:04, Michael Ellerman wrote:
Michal Hocko [off-list ref] writes:
quoted
[Sorry for spamming, this one is the last attempt hopefully]
On Mon 13-11-17 16:49:39, Michal Hocko wrote:
quoted
On Mon 13-11-17 16:16:41, Michal Hocko wrote:
quoted
On Mon 13-11-17 13:00:57, Michal Hocko wrote:
[...]
quoted
Yes, I have mentioned that in the previous email but the amount of code
would be even larger. Basically every arch which reimplements
arch_get_unmapped_area would have to special case new MAP_FIXED flag to
do vma lookup.
It turned out that this might be much more easier than I thought after
all. It seems we can really handle that in the common code. This would
mean that we are exposing a new functionality to the userspace though.
Myabe this would be useful on its own though. Just a quick draft (not
even compile tested) whether this makes sense in general. I would be
worried about unexpected behavior when somebody set other bit without a
good reason and we might fail with ENOMEM for such a call now.
Hmm, the bigger problem would be the backward compatibility actually. We
would get silent corruptions which is exactly what the flag is trying
fix. mmap flags handling really sucks. So I guess we would have to make
the flag internal only :/
OK, so this one should take care of the backward compatibility while
still not touching the arch code
I'm not sure I understand your worries about backward compatibility?
Just imagine you are running an application which uses the new flag
combination on an older kernel. You will get no warning, yet you have no
way to check that you have actually clobbered an existing mapping
because MAP_FIXED will be used the old way.
If we add a new mmap flag which is currently unused then what is the
problem? Are you worried about user code that accidentally passes that
flag already?
If we add a completely new flag, like in this patch, then the code using
the flag will not clobber an existing mapping on older kernels which do
not recognize it (we will simply fall back to the default hint based
implementation). You might not get the mapping you asked for which sucks
but that is not fixable AFAICS. You can at least do
mapped_addr = mmap(addr, ... MAP_FIXED_SAFE...);
assert(mapped_addr == addr);
So I do not think we can go with the modifier unfortunatelly.
--
Michal Hocko
SUSE Labs