kernelnewbies.kernelnewbies.org archive mirror
 help / color / mirror / Atom feed
* How to forbid user space and kernel executable pages from becoming writable?
@ 2019-01-05 15:30 Lev Olshvang
  2019-01-05 20:22 ` Shachar Shemesh
  2019-01-05 20:35 ` valdis.kletnieks
  0 siblings, 2 replies; 3+ messages in thread
From: Lev Olshvang @ 2019-01-05 15:30 UTC (permalink / raw)
  To: linux-il, kernelnewbies

I am researching this issue and I am confused with the finding

Some articles, ex https://shanetully.com/2013/12/writing-a-self-mutating-x86_64-c-program/
state that mprotect() can change protection of executable section.

As I understanf pte entry has page protection bits set to RO so  mprotect should change pte which is loaded to MMU/TLB. Why kernel can not refuse do perform this mprotect call(). Whu we do norhave kernel config options to forbid user-space mutable code as security feature?



From the other side,  when  run-time linker or elf_loader loads the executable it uses MAP_DENYWRITE which protect executable file from being overwritten. 

But writing to  executable text  will make  page dirty and require the write-back which is disabled by MAP_DENYWRITE. (or it might be disable for other processes except current, I am not sure?)


To add to the confusion, the following quote from the LWN articlle 
https://lwn.net/Articles/422487/ about CONFIG_DEBUG_SET_MODULE_RONX 
"Marking the kernel module pages as RO and/or NX is important not only because it is consistent with how the rest of the kernel pages are handled"
  
Digging dipper I see that ARM since kernel version 4.11 has CONFIG_STRICT_KERNEL_RWX ,  and as I understand it is enforced in hardware.

But I am not sure that some variant of pte_clear(), pte_mkexec(0 can not disable it.

So let me cut to final qiestion:

Suppose I want to cut off dynamic code instrumentation, like ftrace and friends.
Is it achievable at least at ARM architecture to enforce RO+X at hardware or kernel? 

Thanks to all folks for reading till this point.

Regards
Lev



_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: How to forbid user space and kernel executable pages from becoming writable?
  2019-01-05 15:30 How to forbid user space and kernel executable pages from becoming writable? Lev Olshvang
@ 2019-01-05 20:22 ` Shachar Shemesh
  2019-01-05 20:35 ` valdis.kletnieks
  1 sibling, 0 replies; 3+ messages in thread
From: Shachar Shemesh @ 2019-01-05 20:22 UTC (permalink / raw)
  To: Lev Olshvang, linux-il, kernelnewbies

[-- Attachment #1: Type: text/html, Size: 5157 bytes --]

[-- Attachment #2: Type: text/plain, Size: 170 bytes --]

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: How to forbid user space and kernel executable pages from becoming writable?
  2019-01-05 15:30 How to forbid user space and kernel executable pages from becoming writable? Lev Olshvang
  2019-01-05 20:22 ` Shachar Shemesh
@ 2019-01-05 20:35 ` valdis.kletnieks
  1 sibling, 0 replies; 3+ messages in thread
From: valdis.kletnieks @ 2019-01-05 20:35 UTC (permalink / raw)
  To: Lev Olshvang; +Cc: linux-il, kernelnewbies

On Sat, 05 Jan 2019 18:30:01 +0300, Lev Olshvang said:

> Some articles, ex https://shanetully.com/2013/12/writing-a-self-mutating-x86_64-c-program/
> state that mprotect() can change protection of executable section.

Note that appears to be a 5 year old article, and one that tries to be operating system
agnostic.

> As I understanf pte entry has page protection bits set to RO so  mprotect
> should change pte which is loaded to MMU/TLB. Why kernel can not refuse do
> perform this mprotect call(). Whu we do norhave kernel config options to forbid
> user-space mutable code as security feature?

Hint: Read up on how shared libraries get loaded when a process starts up, and
also read up on dlopen() 

Think about how you get those to work if you can't have user-space mutable code
at all.

Are you ready to accept the performance hit of statically linked binaries?  Or the
maintenance nightmare of replacing every relevant binary whenever a bug is
found in a library (use glibc as an example)?

> From the other side,  when  run-time linker or elf_loader loads the
> executable it uses MAP_DENYWRITE which protect executable file from being
> overwritten. 

Now, That's a reasonably cheap protection that closes a fairly large attack surface.
It's a lot harder to exploit a buffer overrun or similar if it's difficult to find or create
a page that's both writable and executable.  Of course, there's always ways to change
a page mapping to allow it - the other half of the protection is that the vast majority
of exploits are severely limited in how many bytes can be injected.

> To add to the confusion, the following quote from the LWN articlle 
> https://lwn.net/Articles/422487/ about CONFIG_DEBUG_SET_MODULE_RONX 
> "Marking the kernel module pages as RO and/or NX is important not only because

> But I am not sure that some variant of pte_clear(), pte_mkexec() can not disable it.

So how would modprobe and (possibly more importantly) rmmod work if it couldn't
be disabled?

> So let me cut to final qiestion:
>
> Suppose I want to cut off dynamic code instrumentation, like ftrace and friends.
> Is it achievable at least at ARM architecture to enforce RO+X at hardware or kernel? 

And here is where we get into a discussion of computer security, and this thing
called a "treat model".  Basically, it boils down to several questions:

1) What sensitive data are you trying to protect?
2) Who/what are you trying to protect it from?
3) Why do you think "I should prevent XYZ" is a reasonable protection?

If you're trying to harden a given feature, it's important to ask whether it's worth the
effort (and include "amount of inconvenience caused" in there).  

And an often overlooked part is "how easy is it to bypass?".  Say you manage to fix
dlopen() and the dynamic loader to totally prevent code outside dlopen() from finding
a writable executable page.  What stops an attacker from simply handing an existing
program a booby-trapped shared library via LD_LIBRARY_PATH?

Similarly, disabling ftrace in the kernel doesn't buy you much if an attacker can
modprobe code that re-enables it, or write a new kernel down into /boot and
waiting for (or causing) a reboot.

So now your security measure needs to include modifying the shared library loader
to ignore environment variables when loading into a setuid binary, and add support
for secure boot and crypto signing of kernel modules and other similar things....

_______________________________________________
Kernelnewbies mailing list
Kernelnewbies@kernelnewbies.org
https://lists.kernelnewbies.org/mailman/listinfo/kernelnewbies

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2019-01-08  2:51 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-05 15:30 How to forbid user space and kernel executable pages from becoming writable? Lev Olshvang
2019-01-05 20:22 ` Shachar Shemesh
2019-01-05 20:35 ` valdis.kletnieks

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).