Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date: Mon, 18 Jan 2016 09:22:33 +0000
From: "Reshetova, Elena" <elena.reshetova@...el.com>
To: "kernel-hardening@...ts.openwall.com"
	<kernel-hardening@...ts.openwall.com>
CC: Daniel Borkmann <daniel@...earbox.net>, "Schaufler, Casey"
	<casey.schaufler@...el.com>, "Leibowitz, Michael"
	<michael.leibowitz@...el.com>
Subject: Understanding the JIT Hardening feature

Hi,

 

I got to spend some time reading the 3.15 grsecurity patch with regards to
JIT hardening feature and wanted to share my thoughts on what the patch was
attempting to do.

 

It seems that the bulk of changes was done in bpf_jit_compile() function
(corresponds to the do_jit() 4.4 function). 

The way how it was done was to generate a random value (randkey =
prandom_u32();) and then use that value to dilute (by xor with this value)
the the four cases of operations:

 

case BPF_S_ALU_MUL_K: /* A *= K */

case BPF_S_ALU_MOD_K: /* A %= K; */

case BPF_S_ALU_DIV_K: /* A /= K */

case BPF_S_ALU_AND_X:

 

 

Another part of the patch was making changes to the bpf_alloc_binary()
function. That part I don't really understand since it didn't seem to make
any security improvements, but merely setting the header length to be 128 ad
changing the bpf_binary_header pointer structure. If this change is to be
moved to the latest kernel, modifications to the
<http://lxr.free-electrons.com/ident?i=bpf_jit_binary_alloc>
bpf_jit_binary_alloc() function (kernel/bpf/core.c) are needed as well as
changes in  <http://lxr.free-electrons.com/ident?i=bpf_binary_header>
bpf_binary_header pointer structure (include/linux/filter.h). But again, I
do not understand what security improvements these changes make and why they
were done at the first place. 

 

The last change from the patch was done in EMIT_COND_JMP() function (which
in later kernels is included into emit_cond_jmp switch statement), which was
adding a conditional jz into the flow based on the randkey value. It was
affecting the following cases:

 

case BPF_S_ALU_DIV_X: /* A /= X; */
case BPF_S_ALU_MOD_X: /* A %= X; */
case BPF_S_ANC_IFINDEX:
 

as well as conditional branch. 

 

The above doesn't seem to go very much in line with what Daniel suggested
earlier:

 

"We agreed that the way to go would be to try mitigating it on a BPF
bytecode level iff feasible. For example, by expanding/rewriting things like
loading constants into a i) load where the constant is xored with a (each
time newly generated) prandom_u32()/.. value followed by ii) xor on the same
reg with that prandom value itself."

 

It is also very likely that I didn't understand what you mean Daniel. So
some clarification questions: 

 

-          would you agree with the places where the original grsecurity
patch attempts to add randomization or do you think places should be
different?

-          for the actual randomization, are you proposing to enhance it by
not only xor to a prandom_u32() but also xor with the same reg? Could you
explain what do you mean by this part? 

 

I was also trying to find more info about how JIT code itself works, but
wasn't able to find anything reasonable, so have to make all my statements
from just reading the code, which turned out isn't the most easiest thing to
understand for smbd not familiar with topic.  So, any pointers to the
reading material, if exist, are very much appreciated. 

 

Best Regards,
Elena. 

 

 


Content of type "text/html" skipped

Download attachment "smime.p7s" of type "application/pkcs7-signature" (7586 bytes)

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.