Once an address range is associated with an allocated pkey, it cannot be
reverted back to key-0. There is no valid reason for the above behavior. On
the contrary applications need the ability to do so.
The patch relaxes the restriction.
Tested on powerpc and x86_64.
cc: Dave Hansen <redacted>
cc: Michael Ellermen <mpe@ellerman.id.au>
cc: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Ram Pai <redacted>
---
arch/powerpc/include/asm/pkeys.h | 19 ++++++++++++++-----
arch/x86/include/asm/pkeys.h | 5 +++--
2 files changed, 17 insertions(+), 7 deletions(-)
@@ -101,10 +101,18 @@ static inline u16 pte_to_pkey_bits(u64 pteflags)staticinlineboolmm_pkey_is_allocated(structmm_struct*mm,intpkey){-/* A reserved key is never considered as 'explicitly allocated' */-return((pkey<arch_max_pkey())&&-!__mm_pkey_is_reserved(pkey)&&-__mm_pkey_is_allocated(mm,pkey));+/* pkey 0 is allocated by default. */+if(!pkey)+returntrue;++if(pkey<0||pkey>=arch_max_pkey())+returnfalse;++/* reserved keys are never allocated. */+if(__mm_pkey_is_reserved(pkey))+returnfalse;++return(__mm_pkey_is_allocated(mm,pkey));}externvoid__arch_activate_pkey(intpkey);
@@ -150,7 +158,8 @@ static inline int mm_pkey_free(struct mm_struct *mm, int pkey)if(static_branch_likely(&pkey_disabled))return-1;-if(!mm_pkey_is_allocated(mm,pkey))+/* pkey 0 cannot be freed */+if(!pkey||!mm_pkey_is_allocated(mm,pkey))return-EINVAL;/*
@@ -52,7 +52,7 @@ bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey)*frompkey_alloc().pkey0isspecial,andnever*returnedfrompkey_alloc().*/-if(pkey<=0)+if(pkey<0)returnfalse;if(pkey>=arch_max_pkey())returnfalse;
@@ -92,7 +92,8 @@ int mm_pkey_alloc(struct mm_struct *mm)staticinlineintmm_pkey_free(structmm_struct*mm,intpkey){-if(!mm_pkey_is_allocated(mm,pkey))+/* pkey 0 is special and can never be freed */+if(!pkey||!mm_pkey_is_allocated(mm,pkey))return-EINVAL;mm_set_pkey_free(mm,pkey);
On Fri, Mar 9, 2018 at 7:12 PM, Ram Pai [off-list ref] wrote:
Once an address range is associated with an allocated pkey, it cannot be
reverted back to key-0. There is no valid reason for the above behavior. On
the contrary applications need the ability to do so.
The patch relaxes the restriction.
I looked at the code and my observation was going to be that we need
to change mm_pkey_is_allocated. I still fail to understand what
happens if pkey 0 is reserved? What is the default key is it the first
available key? Assuming 0 is the default key may work and seems to
work, but I am sure its mostly by accident. It would be nice, if we
could have a notion of the default key. I don't like the special
meaning given to key 0 here. Remember on powerpc if 0 is reserved and
UAMOR/AMOR does not allow modification because it's reserved, setting
0 will still fail
Balbir
Once an address range is associated with an allocated pkey, it cannot be
reverted back to key-0. There is no valid reason for the above behavior. On
the contrary applications need the ability to do so.
The patch relaxes the restriction.
Tested on powerpc and x86_64.
cc: Dave Hansen <redacted>
cc: Michael Ellermen <mpe@ellerman.id.au>
cc: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Ram Pai <redacted>
---
arch/powerpc/include/asm/pkeys.h | 19 ++++++++++++++-----
arch/x86/include/asm/pkeys.h | 5 +++--
2 files changed, 17 insertions(+), 7 deletions(-)
@@ -101,10 +101,18 @@ static inline u16 pte_to_pkey_bits(u64 pteflags)staticinlineboolmm_pkey_is_allocated(structmm_struct*mm,intpkey){-/* A reserved key is never considered as 'explicitly allocated' */-return((pkey<arch_max_pkey())&&-!__mm_pkey_is_reserved(pkey)&&-__mm_pkey_is_allocated(mm,pkey));+/* pkey 0 is allocated by default. */+if(!pkey)+returntrue;++if(pkey<0||pkey>=arch_max_pkey())+returnfalse;++/* reserved keys are never allocated. */+if(__mm_pkey_is_reserved(pkey))+returnfalse;
Please capitalize in comments consistently, i.e.:
/* Reserved keys are never allocated: */
From: Michael Ellerman <mpe@ellerman.id.au> Date: 2018-03-09 10:20:01
Ram Pai [off-list ref] writes:
Once an address range is associated with an allocated pkey, it cannot be
reverted back to key-0. There is no valid reason for the above behavior. On
the contrary applications need the ability to do so.
Please explain this in much more detail. Is it an ABI change?
And why did we just notice this?
The patch relaxes the restriction.
Tested on powerpc and x86_64.
Thanks, but please split the patch, one for each arch.
cheers
@@ -101,10 +101,18 @@ static inline u16 pte_to_pkey_bits(u64 pteflags)staticinlineboolmm_pkey_is_allocated(structmm_struct*mm,intpkey){-/* A reserved key is never considered as 'explicitly allocated' */-return((pkey<arch_max_pkey())&&-!__mm_pkey_is_reserved(pkey)&&-__mm_pkey_is_allocated(mm,pkey));+/* pkey 0 is allocated by default. */+if(!pkey)+returntrue;++if(pkey<0||pkey>=arch_max_pkey())+returnfalse;++/* reserved keys are never allocated. */+if(__mm_pkey_is_reserved(pkey))+returnfalse;++return(__mm_pkey_is_allocated(mm,pkey));}externvoid__arch_activate_pkey(intpkey);
@@ -150,7 +158,8 @@ static inline int mm_pkey_free(struct mm_struct *mm, int pkey)if(static_branch_likely(&pkey_disabled))return-1;-if(!mm_pkey_is_allocated(mm,pkey))+/* pkey 0 cannot be freed */+if(!pkey||!mm_pkey_is_allocated(mm,pkey))return-EINVAL;/*
@@ -52,7 +52,7 @@ bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey)*frompkey_alloc().pkey0isspecial,andnever*returnedfrompkey_alloc().*/-if(pkey<=0)+if(pkey<0)returnfalse;if(pkey>=arch_max_pkey())returnfalse;
@@ -92,7 +92,8 @@ int mm_pkey_alloc(struct mm_struct *mm)staticinlineintmm_pkey_free(structmm_struct*mm,intpkey){-if(!mm_pkey_is_allocated(mm,pkey))+/* pkey 0 is special and can never be freed */+if(!pkey||!mm_pkey_is_allocated(mm,pkey))return-EINVAL;mm_set_pkey_free(mm,pkey);
Once an address range is associated with an allocated pkey, it cannot be
reverted back to key-0. There is no valid reason for the above behavior.
mprotect without a key does not necessarily use key 0, e.g. if
protection keys are used to emulate page protection flag combination
which is not directly supported by the hardware.
Therefore, it seems to me that filtering out non-allocated keys is the
right thing to do.
Thanks,
Florian
On Fri, Mar 09, 2018 at 07:37:04PM +1100, Balbir Singh wrote:
On Fri, Mar 9, 2018 at 7:12 PM, Ram Pai [off-list ref] wrote:
quoted
Once an address range is associated with an allocated pkey, it cannot be
reverted back to key-0. There is no valid reason for the above behavior. On
the contrary applications need the ability to do so.
The patch relaxes the restriction.
I looked at the code and my observation was going to be that we need
to change mm_pkey_is_allocated. I still fail to understand what
happens if pkey 0 is reserved? What is the default key is it the first
available key? Assuming 0 is the default key may work and seems to
work, but I am sure its mostly by accident. It would be nice, if we
could have a notion of the default key. I don't like the special
meaning given to key 0 here. Remember on powerpc if 0 is reserved and
UAMOR/AMOR does not allow modification because it's reserved, setting
0 will still fail
The linux pkey API, assumes pkey-0 is the default key. If no key is
explicitly associated with a page, the default key gets associated.
When a default key gets associated with a page, the permissions on the
page are not dictated by the permissions of the default key, but by the
permission of other bits in the pte; i.e _PAGE_RWX.
On powerpc, and AFAICT on x86, neither the hardware nor the hypervisor
reserves key-0. Hence the OS is free to use the key value, the
way it chooses. On Linux we choose to associate key-0 the special status
called default-key.
However I see your point. If some cpu architecture takes away key-0 from
Linux, than implementing the special status for key-0 on that
architecture can become challenging, though not impossible. That
architecture implementation can internally map key-0 value to some other
available key, and associate that key to the page. And offcourse make
sure that the hardware/MMU uses the pte's RWX bits to enforce
permissions, for that key.
--
Ram Pai
On Fri, Mar 09, 2018 at 12:04:49PM +0100, Florian Weimer wrote:
On 03/09/2018 09:12 AM, Ram Pai wrote:
quoted
Once an address range is associated with an allocated pkey, it cannot be
reverted back to key-0. There is no valid reason for the above behavior.
mprotect without a key does not necessarily use key 0, e.g. if
protection keys are used to emulate page protection flag combination
which is not directly supported by the hardware.
Therefore, it seems to me that filtering out non-allocated keys is
the right thing to do.
I am not sure, what you mean. Do you agree with the patch or otherwise?
RP
On Fri, Mar 09, 2018 at 09:43:32AM +0100, Ingo Molnar wrote:
* Ram Pai [off-list ref] wrote:
quoted
Once an address range is associated with an allocated pkey, it cannot be
reverted back to key-0. There is no valid reason for the above behavior. On
the contrary applications need the ability to do so.
The patch relaxes the restriction.
Tested on powerpc and x86_64.
cc: Dave Hansen <redacted>
cc: Michael Ellermen <mpe@ellerman.id.au>
cc: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Ram Pai <redacted>
---
arch/powerpc/include/asm/pkeys.h | 19 ++++++++++++++-----
arch/x86/include/asm/pkeys.h | 5 +++--
2 files changed, 17 insertions(+), 7 deletions(-)
@@ -101,10 +101,18 @@ static inline u16 pte_to_pkey_bits(u64 pteflags)staticinlineboolmm_pkey_is_allocated(structmm_struct*mm,intpkey){-/* A reserved key is never considered as 'explicitly allocated' */-return((pkey<arch_max_pkey())&&-!__mm_pkey_is_reserved(pkey)&&-__mm_pkey_is_allocated(mm,pkey));+/* pkey 0 is allocated by default. */+if(!pkey)+returntrue;++if(pkey<0||pkey>=arch_max_pkey())+returnfalse;++/* reserved keys are never allocated. */+if(__mm_pkey_is_reserved(pkey))+returnfalse;
From: Dave Hansen <hidden> Date: 2018-03-09 22:40:39
On 03/09/2018 12:12 AM, Ram Pai wrote:
Once an address range is associated with an allocated pkey, it cannot be
reverted back to key-0. There is no valid reason for the above behavior. On
the contrary applications need the ability to do so.
Why don't we just set pkey 0 to be allocated in the allocation bitmap by
default?
We *could* also just not let it be special and let it be freed. An app
could theoretically be careful and make sure nothing is using it.
On Fri, Mar 09, 2018 at 02:40:32PM -0800, Dave Hansen wrote:
On 03/09/2018 12:12 AM, Ram Pai wrote:
quoted
Once an address range is associated with an allocated pkey, it cannot be
reverted back to key-0. There is no valid reason for the above behavior. On
the contrary applications need the ability to do so.
Why don't we just set pkey 0 to be allocated in the allocation bitmap by
default?
ok. that will make it allocatable. But it will not be associatable,
given the bug in the current code. And what will be the
default key associated with a pte? zero? or something else?
We *could* also just not let it be special and let it be freed. An app
could theoretically be careful and make sure nothing is using it.
unable to see how this solves the problem. Need some more explaination.
RP
From: Dave Hansen <hidden> Date: 2018-03-10 06:50:38
On 03/09/2018 09:55 PM, Ram Pai wrote:
On Fri, Mar 09, 2018 at 02:40:32PM -0800, Dave Hansen wrote:
quoted
On 03/09/2018 12:12 AM, Ram Pai wrote:
quoted
Once an address range is associated with an allocated pkey, it cannot be
reverted back to key-0. There is no valid reason for the above behavior. On
the contrary applications need the ability to do so.
Why don't we just set pkey 0 to be allocated in the allocation bitmap by
default?
ok. that will make it allocatable. But it will not be associatable,
given the bug in the current code. And what will be the
default key associated with a pte? zero? or something else?
I'm just saying that I think we should try to keep from making it
special as much as possible.
Let's fix the bug that keeps it from being associatable.
From: Dave Hansen <hidden> Date: 2018-03-12 15:46:07
On 03/09/2018 12:06 PM, Ram Pai wrote:
On Fri, Mar 09, 2018 at 09:19:53PM +1100, Michael Ellerman wrote:
quoted
Ram Pai [off-list ref] writes:
quoted
Once an address range is associated with an allocated pkey, it cannot be
reverted back to key-0. There is no valid reason for the above behavior. On
the contrary applications need the ability to do so.
Please explain this in much more detail. Is it an ABI change?
Not necessarily an ABI change. older binary applications will continue
to work. It can be considered as a bug-fix.
Yeah, agreed. I do not think this is an ABI change.
On Fri, Mar 09, 2018 at 12:04:49PM +0100, Florian Weimer wrote:
quoted
On 03/09/2018 09:12 AM, Ram Pai wrote:
quoted
Once an address range is associated with an allocated pkey, it cannot be
reverted back to key-0. There is no valid reason for the above behavior.
mprotect without a key does not necessarily use key 0, e.g. if
protection keys are used to emulate page protection flag combination
which is not directly supported by the hardware.
Therefore, it seems to me that filtering out non-allocated keys is
the right thing to do.
I am not sure, what you mean. Do you agree with the patch or otherwise?
I think it's inconsistent to make key 0 allocated, but not the key which
is used for PROT_EXEC emulation, which is still reserved. Even if you
change the key 0 behavior, it is still not possible to emulate mprotect
behavior faithfully with an allocated key.
Thanks,
Florian
On Fri, Mar 09, 2018 at 12:04:49PM +0100, Florian Weimer wrote:
quoted
On 03/09/2018 09:12 AM, Ram Pai wrote:
quoted
Once an address range is associated with an allocated pkey, it
cannot be
reverted back to key-0. There is no valid reason for the above
behavior.
mprotect without a key does not necessarily use key 0, e.g. if
protection keys are used to emulate page protection flag combination
which is not directly supported by the hardware.
Therefore, it seems to me that filtering out non-allocated keys is
the right thing to do.
I am not sure, what you mean. Do you agree with the patch or otherwise?
I think it's inconsistent to make key 0 allocated, but not the key which
is used for PROT_EXEC emulation, which is still reserved. Even if you
change the key 0 behavior, it is still not possible to emulate mprotect
behavior faithfully with an allocated key.
Ugh. Should have read the code first before replying:
/* Do we need to assign a pkey for mm's execute-only maps? */
if (execute_only_pkey == -1) {
/* Go allocate one to use, which might fail */
execute_only_pkey = mm_pkey_alloc(mm);
if (execute_only_pkey < 0)
return -1;
need_to_set_mm_pkey = true;
}
So we do allocate the PROT_EXEC-only key, and I assume it means that the
key can be restored using pkey_mprotect. So the key 0 behavior is a
true exception after all, and it makes sense to realign the behavior
with the other keys.
Thanks,
Florian