restorer: shstk: add shstk_min_mmap_addr()

* default: return whatever passed in
  eg. to be used as
     shtk_min_mmap_addr(kdat.mmap_min_addr)
* x86: ignore def and return 4G

On x86, CET shadow stack is required to be mapped above 4GiB
On the other hand forcing 4GiB globally would break 32-bit restores.

Co-Authored-By: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
This commit is contained in:
Alexander Mikhalitsyn 2025-10-17 18:53:01 +02:00 committed by Andrei Vagin
parent f29cb750db
commit b18c07d8a8
3 changed files with 18 additions and 4 deletions

View file

@ -84,6 +84,12 @@ static always_inline void shstk_set_restorer_stack(struct rst_shstk_info *info,
}
#define shstk_set_restorer_stack shstk_set_restorer_stack
static always_inline long shstk_min_mmap_addr(struct rst_shstk_info *info, unsigned long __maybe_unused def)
{
return !(info->cet & ARCH_SHSTK_SHSTK) ? def : (4UL << 30);
}
#define shstk_min_mmap_addr shstk_min_mmap_addr
#ifdef CR_NOGLIBC
#include <compel/plugins/std/syscall.h>

View file

@ -2431,16 +2431,15 @@ err:
return ret;
}
static long restorer_get_vma_hint(struct list_head *tgt_vma_list, struct list_head *self_vma_list, long vma_len)
static long restorer_get_vma_hint(struct list_head *tgt_vma_list, struct list_head *self_vma_list, long min_addr, long vma_len)
{
struct vma_area *t_vma, *s_vma;
long prev_vma_end = 0;
long prev_vma_end = min_addr;
struct vma_area end_vma;
VmaEntry end_e;
end_vma.e = &end_e;
end_e.start = end_e.end = kdat.task_size;
prev_vma_end = kdat.mmap_min_addr;
s_vma = list_first_entry(self_vma_list, struct vma_area, list);
t_vma = list_first_entry(tgt_vma_list, struct vma_area, list);
@ -3226,7 +3225,9 @@ static int sigreturn_restore(pid_t pid, struct task_restore_args *task_args, uns
* or inited from scratch).
*/
mem = (void *)restorer_get_vma_hint(&vmas->h, &self_vmas.h, task_args->bootstrap_len);
mem = (void *)restorer_get_vma_hint(&vmas->h, &self_vmas.h,
shstk_min_mmap_addr(&task_args->shstk, kdat.mmap_min_addr),
task_args->bootstrap_len);
if (mem == (void *)-1) {
pr_err("No suitable area for task_restore bootstrap (%ldK)\n", task_args->bootstrap_len);
goto err;

View file

@ -53,4 +53,11 @@ static always_inline long shstk_set_restorer_stack(struct rst_shstk_info *info,
}
#endif
#ifndef shstk_min_mmap_addr
static always_inline long shstk_min_mmap_addr(struct rst_shstk_info *info, unsigned long def)
{
return def;
}
#endif
#endif