Skip to content

Commit 89a8c59

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 fixes from Martin Schwidefsky: "An update for the BFP jit to the latest and greatest, two patches to get kdump working again, the random-abort ptrace extention for transactional execution, the z90crypt module alias for ap and a tiny cleanup" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: s390/zcrypt: Alias for new zcrypt device driver base module s390/kdump: Allow copy_oldmem_page() copy to virtual memory s390/kdump: Disable mmap for s390 s390/bpf,jit: add pkt_type support s390/bpf,jit: address randomize and write protect jit code s390/bpf,jit: use generic jit dumper s390/bpf,jit: call module_free() from any context s390/qdio: remove unused variable s390/ptrace: PTRACE_TE_ABORT_RAND
2 parents b8a33fc + 9da3545 commit 89a8c59

File tree

9 files changed

+190
-46
lines changed

9 files changed

+190
-46
lines changed

arch/s390/include/asm/processor.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,15 @@ struct thread_struct {
9191
#endif
9292
};
9393

94-
#define PER_FLAG_NO_TE 1UL /* Flag to disable transactions. */
94+
/* Flag to disable transactions. */
95+
#define PER_FLAG_NO_TE 1UL
96+
/* Flag to enable random transaction aborts. */
97+
#define PER_FLAG_TE_ABORT_RAND 2UL
98+
/* Flag to specify random transaction abort mode:
99+
* - abort each transaction at a random instruction before TEND if set.
100+
* - abort random transactions at a random instruction if cleared.
101+
*/
102+
#define PER_FLAG_TE_ABORT_RAND_TEND 4UL
95103

96104
typedef struct thread_struct thread_struct;
97105

arch/s390/include/asm/switch_to.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#include <linux/thread_info.h>
1111

1212
extern struct task_struct *__switch_to(void *, void *);
13-
extern void update_per_regs(struct task_struct *task);
13+
extern void update_cr_regs(struct task_struct *task);
1414

1515
static inline void save_fp_regs(s390_fp_regs *fpregs)
1616
{
@@ -86,7 +86,7 @@ static inline void restore_access_regs(unsigned int *acrs)
8686
restore_fp_regs(&next->thread.fp_regs); \
8787
restore_access_regs(&next->thread.acrs[0]); \
8888
restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb); \
89-
update_per_regs(next); \
89+
update_cr_regs(next); \
9090
} \
9191
prev = __switch_to(prev,next); \
9292
} while (0)

arch/s390/include/uapi/asm/ptrace.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ typedef struct
400400
#define PTRACE_POKE_SYSTEM_CALL 0x5008
401401
#define PTRACE_ENABLE_TE 0x5009
402402
#define PTRACE_DISABLE_TE 0x5010
403+
#define PTRACE_TE_ABORT_RAND 0x5011
403404

404405
/*
405406
* PT_PROT definition is loosely based on hppa bsd definition in

arch/s390/kernel/crash_dump.c

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,48 @@
2121
#define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y)))
2222
#define PTR_DIFF(x, y) ((unsigned long)(((char *) (x)) - ((unsigned long) (y))))
2323

24+
25+
/*
26+
* Return physical address for virtual address
27+
*/
28+
static inline void *load_real_addr(void *addr)
29+
{
30+
unsigned long real_addr;
31+
32+
asm volatile(
33+
" lra %0,0(%1)\n"
34+
" jz 0f\n"
35+
" la %0,0\n"
36+
"0:"
37+
: "=a" (real_addr) : "a" (addr) : "cc");
38+
return (void *)real_addr;
39+
}
40+
41+
/*
42+
* Copy up to one page to vmalloc or real memory
43+
*/
44+
static ssize_t copy_page_real(void *buf, void *src, size_t csize)
45+
{
46+
size_t size;
47+
48+
if (is_vmalloc_addr(buf)) {
49+
BUG_ON(csize >= PAGE_SIZE);
50+
/* If buf is not page aligned, copy first part */
51+
size = min(roundup(__pa(buf), PAGE_SIZE) - __pa(buf), csize);
52+
if (size) {
53+
if (memcpy_real(load_real_addr(buf), src, size))
54+
return -EFAULT;
55+
buf += size;
56+
src += size;
57+
}
58+
/* Copy second part */
59+
size = csize - size;
60+
return (size) ? memcpy_real(load_real_addr(buf), src, size) : 0;
61+
} else {
62+
return memcpy_real(buf, src, csize);
63+
}
64+
}
65+
2466
/*
2567
* Copy one page from "oldmem"
2668
*
@@ -32,6 +74,7 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
3274
size_t csize, unsigned long offset, int userbuf)
3375
{
3476
unsigned long src;
77+
int rc;
3578

3679
if (!csize)
3780
return 0;
@@ -43,11 +86,11 @@ ssize_t copy_oldmem_page(unsigned long pfn, char *buf,
4386
src < OLDMEM_BASE + OLDMEM_SIZE)
4487
src -= OLDMEM_BASE;
4588
if (userbuf)
46-
copy_to_user_real((void __force __user *) buf, (void *) src,
47-
csize);
89+
rc = copy_to_user_real((void __force __user *) buf,
90+
(void *) src, csize);
4891
else
49-
memcpy_real(buf, (void *) src, csize);
50-
return csize;
92+
rc = copy_page_real(buf, (void *) src, csize);
93+
return (rc == 0) ? csize : rc;
5194
}
5295

5396
/*

arch/s390/kernel/ptrace.c

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ enum s390_regset {
4747
REGSET_GENERAL_EXTENDED,
4848
};
4949

50-
void update_per_regs(struct task_struct *task)
50+
void update_cr_regs(struct task_struct *task)
5151
{
5252
struct pt_regs *regs = task_pt_regs(task);
5353
struct thread_struct *thread = &task->thread;
@@ -56,17 +56,25 @@ void update_per_regs(struct task_struct *task)
5656
#ifdef CONFIG_64BIT
5757
/* Take care of the enable/disable of transactional execution. */
5858
if (MACHINE_HAS_TE) {
59-
unsigned long cr0, cr0_new;
59+
unsigned long cr[3], cr_new[3];
6060

61-
__ctl_store(cr0, 0, 0);
62-
/* set or clear transaction execution bits 8 and 9. */
61+
__ctl_store(cr, 0, 2);
62+
cr_new[1] = cr[1];
63+
/* Set or clear transaction execution TXC/PIFO bits 8 and 9. */
6364
if (task->thread.per_flags & PER_FLAG_NO_TE)
64-
cr0_new = cr0 & ~(3UL << 54);
65+
cr_new[0] = cr[0] & ~(3UL << 54);
6566
else
66-
cr0_new = cr0 | (3UL << 54);
67-
/* Only load control register 0 if necessary. */
68-
if (cr0 != cr0_new)
69-
__ctl_load(cr0_new, 0, 0);
67+
cr_new[0] = cr[0] | (3UL << 54);
68+
/* Set or clear transaction execution TDC bits 62 and 63. */
69+
cr_new[2] = cr[2] & ~3UL;
70+
if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND) {
71+
if (task->thread.per_flags & PER_FLAG_TE_ABORT_RAND_TEND)
72+
cr_new[2] |= 1UL;
73+
else
74+
cr_new[2] |= 2UL;
75+
}
76+
if (memcmp(&cr_new, &cr, sizeof(cr)))
77+
__ctl_load(cr_new, 0, 2);
7078
}
7179
#endif
7280
/* Copy user specified PER registers */
@@ -100,14 +108,14 @@ void user_enable_single_step(struct task_struct *task)
100108
{
101109
set_tsk_thread_flag(task, TIF_SINGLE_STEP);
102110
if (task == current)
103-
update_per_regs(task);
111+
update_cr_regs(task);
104112
}
105113

106114
void user_disable_single_step(struct task_struct *task)
107115
{
108116
clear_tsk_thread_flag(task, TIF_SINGLE_STEP);
109117
if (task == current)
110-
update_per_regs(task);
118+
update_cr_regs(task);
111119
}
112120

113121
/*
@@ -447,6 +455,26 @@ long arch_ptrace(struct task_struct *child, long request,
447455
if (!MACHINE_HAS_TE)
448456
return -EIO;
449457
child->thread.per_flags |= PER_FLAG_NO_TE;
458+
child->thread.per_flags &= ~PER_FLAG_TE_ABORT_RAND;
459+
return 0;
460+
case PTRACE_TE_ABORT_RAND:
461+
if (!MACHINE_HAS_TE || (child->thread.per_flags & PER_FLAG_NO_TE))
462+
return -EIO;
463+
switch (data) {
464+
case 0UL:
465+
child->thread.per_flags &= ~PER_FLAG_TE_ABORT_RAND;
466+
break;
467+
case 1UL:
468+
child->thread.per_flags |= PER_FLAG_TE_ABORT_RAND;
469+
child->thread.per_flags |= PER_FLAG_TE_ABORT_RAND_TEND;
470+
break;
471+
case 2UL:
472+
child->thread.per_flags |= PER_FLAG_TE_ABORT_RAND;
473+
child->thread.per_flags &= ~PER_FLAG_TE_ABORT_RAND_TEND;
474+
break;
475+
default:
476+
return -EINVAL;
477+
}
450478
return 0;
451479
default:
452480
/* Removing high order bit from addr (only for 31 bit). */

arch/s390/net/bpf_jit_comp.c

Lines changed: 88 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include <linux/netdevice.h>
1010
#include <linux/if_vlan.h>
1111
#include <linux/filter.h>
12+
#include <linux/random.h>
13+
#include <linux/init.h>
1214
#include <asm/cacheflush.h>
1315
#include <asm/processor.h>
1416
#include <asm/facility.h>
@@ -221,6 +223,37 @@ static void bpf_jit_epilogue(struct bpf_jit *jit)
221223
EMIT2(0x07fe);
222224
}
223225

226+
/* Helper to find the offset of pkt_type in sk_buff
227+
* Make sure its still a 3bit field starting at the MSBs within a byte.
228+
*/
229+
#define PKT_TYPE_MAX 0xe0
230+
static int pkt_type_offset;
231+
232+
static int __init bpf_pkt_type_offset_init(void)
233+
{
234+
struct sk_buff skb_probe = {
235+
.pkt_type = ~0,
236+
};
237+
char *ct = (char *)&skb_probe;
238+
int off;
239+
240+
pkt_type_offset = -1;
241+
for (off = 0; off < sizeof(struct sk_buff); off++) {
242+
if (!ct[off])
243+
continue;
244+
if (ct[off] == PKT_TYPE_MAX)
245+
pkt_type_offset = off;
246+
else {
247+
/* Found non matching bit pattern, fix needed. */
248+
WARN_ON_ONCE(1);
249+
pkt_type_offset = -1;
250+
return -1;
251+
}
252+
}
253+
return 0;
254+
}
255+
device_initcall(bpf_pkt_type_offset_init);
256+
224257
/*
225258
* make sure we dont leak kernel information to user
226259
*/
@@ -720,6 +753,16 @@ load_abs: if ((int) K < 0)
720753
EMIT4_DISP(0x88500000, 12);
721754
}
722755
break;
756+
case BPF_S_ANC_PKTTYPE:
757+
if (pkt_type_offset < 0)
758+
goto out;
759+
/* lhi %r5,0 */
760+
EMIT4(0xa7580000);
761+
/* ic %r5,<d(pkt_type_offset)>(%r2) */
762+
EMIT4_DISP(0x43502000, pkt_type_offset);
763+
/* srl %r5,5 */
764+
EMIT4_DISP(0x88500000, 5);
765+
break;
723766
case BPF_S_ANC_CPU: /* A = smp_processor_id() */
724767
#ifdef CONFIG_SMP
725768
/* l %r5,<d(cpu_nr)> */
@@ -738,8 +781,41 @@ load_abs: if ((int) K < 0)
738781
return -1;
739782
}
740783

784+
/*
785+
* Note: for security reasons, bpf code will follow a randomly
786+
* sized amount of illegal instructions.
787+
*/
788+
struct bpf_binary_header {
789+
unsigned int pages;
790+
u8 image[];
791+
};
792+
793+
static struct bpf_binary_header *bpf_alloc_binary(unsigned int bpfsize,
794+
u8 **image_ptr)
795+
{
796+
struct bpf_binary_header *header;
797+
unsigned int sz, hole;
798+
799+
/* Most BPF filters are really small, but if some of them fill a page,
800+
* allow at least 128 extra bytes for illegal instructions.
801+
*/
802+
sz = round_up(bpfsize + sizeof(*header) + 128, PAGE_SIZE);
803+
header = module_alloc(sz);
804+
if (!header)
805+
return NULL;
806+
memset(header, 0, sz);
807+
header->pages = sz / PAGE_SIZE;
808+
hole = sz - bpfsize + sizeof(*header);
809+
/* Insert random number of illegal instructions before BPF code
810+
* and make sure the first instruction starts at an even address.
811+
*/
812+
*image_ptr = &header->image[(prandom_u32() % hole) & -2];
813+
return header;
814+
}
815+
741816
void bpf_jit_compile(struct sk_filter *fp)
742817
{
818+
struct bpf_binary_header *header = NULL;
743819
unsigned long size, prg_len, lit_len;
744820
struct bpf_jit jit, cjit;
745821
unsigned int *addrs;
@@ -772,12 +848,11 @@ void bpf_jit_compile(struct sk_filter *fp)
772848
} else if (jit.prg == cjit.prg && jit.lit == cjit.lit) {
773849
prg_len = jit.prg - jit.start;
774850
lit_len = jit.lit - jit.mid;
775-
size = max_t(unsigned long, prg_len + lit_len,
776-
sizeof(struct work_struct));
851+
size = prg_len + lit_len;
777852
if (size >= BPF_SIZE_MAX)
778853
goto out;
779-
jit.start = module_alloc(size);
780-
if (!jit.start)
854+
header = bpf_alloc_binary(size, &jit.start);
855+
if (!header)
781856
goto out;
782857
jit.prg = jit.mid = jit.start + prg_len;
783858
jit.lit = jit.end = jit.start + prg_len + lit_len;
@@ -788,37 +863,25 @@ void bpf_jit_compile(struct sk_filter *fp)
788863
cjit = jit;
789864
}
790865
if (bpf_jit_enable > 1) {
791-
pr_err("flen=%d proglen=%lu pass=%d image=%p\n",
792-
fp->len, jit.end - jit.start, pass, jit.start);
793-
if (jit.start) {
794-
printk(KERN_ERR "JIT code:\n");
866+
bpf_jit_dump(fp->len, jit.end - jit.start, pass, jit.start);
867+
if (jit.start)
795868
print_fn_code(jit.start, jit.mid - jit.start);
796-
print_hex_dump(KERN_ERR, "JIT literals:\n",
797-
DUMP_PREFIX_ADDRESS, 16, 1,
798-
jit.mid, jit.end - jit.mid, false);
799-
}
800869
}
801-
if (jit.start)
870+
if (jit.start) {
871+
set_memory_ro((unsigned long)header, header->pages);
802872
fp->bpf_func = (void *) jit.start;
873+
}
803874
out:
804875
kfree(addrs);
805876
}
806877

807-
static void jit_free_defer(struct work_struct *arg)
808-
{
809-
module_free(NULL, arg);
810-
}
811-
812-
/* run from softirq, we must use a work_struct to call
813-
* module_free() from process context
814-
*/
815878
void bpf_jit_free(struct sk_filter *fp)
816879
{
817-
struct work_struct *work;
880+
unsigned long addr = (unsigned long)fp->bpf_func & PAGE_MASK;
881+
struct bpf_binary_header *header = (void *)addr;
818882

819883
if (fp->bpf_func == sk_run_filter)
820884
return;
821-
work = (struct work_struct *)fp->bpf_func;
822-
INIT_WORK(work, jit_free_defer);
823-
schedule_work(work);
885+
set_memory_rw(addr, header->pages);
886+
module_free(NULL, header);
824887
}

drivers/s390/cio/qdio_main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1497,7 +1497,7 @@ static inline int buf_in_between(int bufnr, int start, int count)
14971497
static int handle_inbound(struct qdio_q *q, unsigned int callflags,
14981498
int bufnr, int count)
14991499
{
1500-
int used, diff;
1500+
int diff;
15011501

15021502
qperf_inc(q, inbound_call);
15031503

@@ -1530,7 +1530,7 @@ static int handle_inbound(struct qdio_q *q, unsigned int callflags,
15301530

15311531
set:
15321532
count = set_buf_states(q, bufnr, SLSB_CU_INPUT_EMPTY, count);
1533-
used = atomic_add_return(count, &q->nr_buf_used) - count;
1533+
atomic_add(count, &q->nr_buf_used);
15341534

15351535
if (need_siga_in(q))
15361536
return qdio_siga_input(q);

drivers/s390/crypto/ap_bus.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ MODULE_AUTHOR("IBM Corporation");
7171
MODULE_DESCRIPTION("Adjunct Processor Bus driver, " \
7272
"Copyright IBM Corp. 2006, 2012");
7373
MODULE_LICENSE("GPL");
74+
MODULE_ALIAS("z90crypt");
7475

7576
/*
7677
* Module parameter

0 commit comments

Comments
 (0)