[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <87r2ecunc2.fsf@morokweng.localdomain>
Date: Thu, 20 Dec 2018 15:20:29 -0200
From: Thiago Jung Bauermann <bauerman@...ux.ibm.com>
To: Igor Stoppa <igor.stoppa@...il.com>
Cc: Andy Lutomirski <luto@...capital.net>,
Matthew Wilcox <willy@...radead.org>,
Peter Zijlstra <peterz@...radead.org>,
Dave Hansen <dave.hansen@...ux.intel.com>,
Mimi Zohar <zohar@...ux.vnet.ibm.com>, igor.stoppa@...wei.com,
Nadav Amit <nadav.amit@...il.com>,
Kees Cook <keescook@...omium.org>,
linux-integrity@...r.kernel.org,
kernel-hardening@...ts.openwall.com, linux-mm@...ck.org,
linux-kernel@...r.kernel.org
Subject: Re: [PATCH 04/12] __wr_after_init: x86_64: __wr_op
Hello Igor,
> +/*
> + * The following two variables are statically allocated by the linker
> + * script at the the boundaries of the memory region (rounded up to
> + * multiples of PAGE_SIZE) reserved for __wr_after_init.
> + */
> +extern long __start_wr_after_init;
> +extern long __end_wr_after_init;
> +
> +static inline bool is_wr_after_init(unsigned long ptr, __kernel_size_t size)
> +{
> + unsigned long start = (unsigned long)&__start_wr_after_init;
> + unsigned long end = (unsigned long)&__end_wr_after_init;
> + unsigned long low = ptr;
> + unsigned long high = ptr + size;
> +
> + return likely(start <= low && low <= high && high <= end);
> +}
> +
> +void *__wr_op(unsigned long dst, unsigned long src, __kernel_size_t len,
> + enum wr_op_type op)
> +{
> + temporary_mm_state_t prev;
> + unsigned long offset;
> + unsigned long wr_poking_addr;
> +
> + /* Confirm that the writable mapping exists. */
> + if (WARN_ONCE(!wr_ready, "No writable mapping available"))
> + return (void *)dst;
> +
> + if (WARN_ONCE(op >= WR_OPS_NUMBER, "Invalid WR operation.") ||
> + WARN_ONCE(!is_wr_after_init(dst, len), "Invalid WR range."))
> + return (void *)dst;
> +
> + offset = dst - (unsigned long)&__start_wr_after_init;
> + wr_poking_addr = wr_poking_base + offset;
> + local_irq_disable();
> + prev = use_temporary_mm(wr_poking_mm);
> +
> + if (op == WR_MEMCPY)
> + copy_to_user((void __user *)wr_poking_addr, (void *)src, len);
> + else if (op == WR_MEMSET)
> + memset_user((void __user *)wr_poking_addr, (u8)src, len);
> +
> + unuse_temporary_mm(prev);
> + local_irq_enable();
> + return (void *)dst;
> +}
There's a lot of casting back and forth between unsigned long and void *
(also in the previous patch). Is there a reason for that? My impression
is that there would be less casts if variables holding addresses were
declared as void * in the first place. In that case, it wouldn't hurt to
have an additional argument in __rw_op() to carry the byte value for the
WR_MEMSET operation.
> +
> +#define TB (1UL << 40)
> +
> +struct mm_struct *copy_init_mm(void);
> +void __init wr_poking_init(void)
> +{
> + unsigned long start = (unsigned long)&__start_wr_after_init;
> + unsigned long end = (unsigned long)&__end_wr_after_init;
> + unsigned long i;
> + unsigned long wr_range;
> +
> + wr_poking_mm = copy_init_mm();
> + if (WARN_ONCE(!wr_poking_mm, "No alternate mapping available."))
> + return;
> +
> + wr_range = round_up(end - start, PAGE_SIZE);
> +
> + /* Randomize the poking address base*/
> + wr_poking_base = TASK_UNMAPPED_BASE +
> + (kaslr_get_random_long("Write Rare Poking") & PAGE_MASK) %
> + (TASK_SIZE - (TASK_UNMAPPED_BASE + wr_range));
> +
> + /*
> + * Place 64TB of kernel address space within 128TB of user address
> + * space, at a random page aligned offset.
> + */
> + wr_poking_base = (((unsigned long)kaslr_get_random_long("WR Poke")) &
> + PAGE_MASK) % (64 * _BITUL(40));
You're setting wr_poking_base twice in a row? Is this an artifact from
rebase?
--
Thiago Jung Bauermann
IBM Linux Technology Center
Powered by blists - more mailing lists