Shadow Stack Locking Semantics between arch's

Bill Roberts <[email protected]>
Newsgroups org.infradead.lists.linux-riscv,org.infradead.lists.linux-arm-kernel,org.kernel.vger.linux-api,org.kernel.vger.linux-hardening,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Howdy folks,

If you haven't seen, I have been floating some patches to bring x86-64 
shadow stack controls over to prctl, and it's generally straight forward.
The larger motivation, is that I am doing all of this so we can place 
LSM controls on shadow stack manipulations. For x86 will we need to hook
the old and new implementations.

I have noticed some semantic differences between the arches. Given this 
example of current thread state, current thread locking state and the
new features requested, as shown below:

unsigned long locked = 0x2; // Kernel Task State -> LOCK WRITE
unsigned long cur_val = 0x3; // Kernel Task State -> WRITE and 
SHADOWSTACK ENABLED
unsigned long new_val = 0x0; // Userspace Feature Change via syscall -> 
DISABLE

| x86-64 | risc-v | arm64 |
| ---------- | -------- | --------- |
| Works  | Fails  | Fails     |

Besides the locking difference, I have also noticed a few other issues 
noted below:

Risc-v:
- shouldn't reject all bits in locking, it supports shadow stack.
- shouldn't return EINVAL on locking checks

See the code snippets for these below:

if (is_shstk_locked(t))
                 return -EINVAL;

int arch_lock_shadow_stack_status(struct task_struct *task,
                                   unsigned long arg)
{
         /* If shtstk not supported or not enabled on task, nothing to 
lock here */
         if (!is_user_shstk_enabled() ||
             !is_shstk_enabled(task) || arg != 0)
                 return -EINVAL;

         set_shstk_lock(task, true);

         return 0;
}

arm64:
1. Locking failures return -EBUSY vs -EPERM, I spoke with Mark (on CC) 
he seemed OK with this,

I would like to find a way to rectify this so userspace has a common API.

I am proposing and have questions over the following:
1. What should the behavior be if you had write locked and disable the 
shadow stack?
   - I can argue both ways here, -EPERM or success. I think I and most 
arches lead to failure.
2. riscv should check that the low bit is set in locking not just that 
its 0, it should be 1
3. riscv should return -EPERM vs -EINVAL
4. x86 locking state should fail

If we can all agree on item 1, that locked bits check can be refactored 
and shared in one of
two ways:
1. within prctl itself, before the arch hook is called, we would need 
helpers per-arch to extract the thread features and lock bits
2. as a helper where folks just pass the unsigned long of the bits to 
get the result

Thanks everyone


_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.