Re: [RFC PATCH 2/3] Introduce arch_prctl(ARCH_X86_CET_MARK_LEGACY_CODE)

From: Andy Lutomirski
Date: Sat Jun 29 2019 - 19:43:41 EST


> On Jun 28, 2019, at 12:41 PM, Yu-cheng Yu <yu-cheng.yu@xxxxxxxxx> wrote:
>
> The CET legacy code bitmap covers the whole user-mode address space and is
> located at the top of the user-mode address space. It is allocated only
> when the first time arch_prctl(ARCH_X86_MARK_LEGACY_CODE) is called from
> an application.
>
> Introduce:
>
> arch_prctl(ARCH_X86_MARK_LEGACY_CODE, unsigned long *buf)
> Mark an address range as IBT legacy code.

How about defining a struct for this?

The change log should discuss where the bitmap goes and how itâs allocated.

> +static int alloc_bitmap(void)
> +{
> + unsigned long addr;
> + u64 msr_ia32_u_cet;
> +
> + addr = do_mmap_locked(NULL, IBT_BITMAP_ADDR, IBT_BITMAP_SIZE,
> + PROT_READ | PROT_WRITE,
> + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE,
> + VM_IBT | VM_NORESERVE, NULL);
> +
> + if (IS_ERR((void *)addr))
> + return addr;
> +
> + current->thread.cet.ibt_bitmap_addr = addr;

addr is a constant. Why are you storing it? If it ends up not being
constant, you should wire up mremap like the vDSO does.


> +static int set_user_bits(unsigned long __user *buf, unsigned long buf_size,
> + unsigned long start_bit, unsigned long end_bit, unsigned long set)
> +{
> + unsigned long start_ul, end_ul, total_ul;
> + int i, j, r;
> +
> + if (round_up(end_bit, BITS_PER_BYTE) / BITS_PER_BYTE > buf_size)
> + end_bit = buf_size * BITS_PER_BYTE - 1;
> +
> + start_ul = start_bit / BITS_PER_LONG;
> + end_ul = end_bit / BITS_PER_LONG;
> + total_ul = (end_ul - start_ul + 1);
> +
> + i = start_bit % BITS_PER_LONG;
> + j = end_bit % BITS_PER_LONG;
> +
> + r = 0;
> + put_user_try {

put_user_try is obsolete. Just use get_user(), etc.

Also, I must be missing something fundamental, because this series
claims that user code can't write directly to the bitmap. This means
that this entire function shouldn't work at all.