aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-01-12 16:27:18 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-12 16:27:18 -0500
commit4f31d774dd5239e563f22ffe1403292414e6f779 (patch)
tree5edfdcc2adf491f340510694b8718d09378fdd15
parent1baa5efbeb6eb75de697f7b5931094be33f12005 (diff)
parent3e46b25376321db119bc8507ce8c8841c580e736 (diff)
Merge branch 'for-linus-4.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml
Pull UML updates from Richard Weinberger: "This contains beside of random fixes/cleanups two bigger changes: - seccomp support by Mickaël Salaün - IRQ rework by Anton Ivanov" * 'for-linus-4.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml: um: Use race-free temporary file creation um: Do not set unsecure permission for temporary file um: Fix build error and kconfig for i386 um: Add seccomp support um: Add full asm/syscall.h support selftests/seccomp: Remove the need for HAVE_ARCH_TRACEHOOK um: Fix ptrace GETREGS/SETREGS bugs um: link with -lpthread um: Update UBD to use pread/pwrite family of functions um: Do not change hard IRQ flags in soft IRQ processing um: Prevent IRQ handler reentrancy uml: flush stdout before forking uml: fix hostfs mknod()
-rw-r--r--Documentation/features/seccomp/seccomp-filter/arch-support.txt2
-rw-r--r--arch/um/Kconfig.common1
-rw-r--r--arch/um/Kconfig.um16
-rw-r--r--arch/um/drivers/ubd_kern.c27
-rw-r--r--arch/um/include/asm/hardirq.h23
-rw-r--r--arch/um/include/asm/syscall-generic.h138
-rw-r--r--arch/um/include/asm/thread_info.h2
-rw-r--r--arch/um/include/shared/os.h3
-rw-r--r--arch/um/kernel/skas/syscall.c31
-rw-r--r--arch/um/os-Linux/file.c19
-rw-r--r--arch/um/os-Linux/mem.c17
-rw-r--r--arch/um/os-Linux/signal.c16
-rw-r--r--arch/um/os-Linux/skas/process.c7
-rw-r--r--arch/um/os-Linux/start_up.c2
-rw-r--r--arch/x86/um/Makefile2
-rw-r--r--arch/x86/um/asm/syscall.h1
-rw-r--r--arch/x86/um/ptrace_32.c8
-rw-r--r--fs/hostfs/hostfs_kern.c4
-rwxr-xr-xscripts/link-vmlinux.sh2
-rw-r--r--tools/testing/selftests/seccomp/seccomp_bpf.c27
20 files changed, 285 insertions, 63 deletions
diff --git a/Documentation/features/seccomp/seccomp-filter/arch-support.txt b/Documentation/features/seccomp/seccomp-filter/arch-support.txt
index 76d39d66a5d7..4f66ec133951 100644
--- a/Documentation/features/seccomp/seccomp-filter/arch-support.txt
+++ b/Documentation/features/seccomp/seccomp-filter/arch-support.txt
@@ -33,7 +33,7 @@
33 | sh: | TODO | 33 | sh: | TODO |
34 | sparc: | TODO | 34 | sparc: | TODO |
35 | tile: | ok | 35 | tile: | ok |
36 | um: | TODO | 36 | um: | ok |
37 | unicore32: | TODO | 37 | unicore32: | TODO |
38 | x86: | ok | 38 | x86: | ok |
39 | xtensa: | TODO | 39 | xtensa: | TODO |
diff --git a/arch/um/Kconfig.common b/arch/um/Kconfig.common
index d195a87ca542..cc0013475444 100644
--- a/arch/um/Kconfig.common
+++ b/arch/um/Kconfig.common
@@ -2,6 +2,7 @@ config UML
2 bool 2 bool
3 default y 3 default y
4 select HAVE_ARCH_AUDITSYSCALL 4 select HAVE_ARCH_AUDITSYSCALL
5 select HAVE_ARCH_SECCOMP_FILTER
5 select HAVE_UID16 6 select HAVE_UID16
6 select HAVE_FUTEX_CMPXCHG if FUTEX 7 select HAVE_FUTEX_CMPXCHG if FUTEX
7 select GENERIC_IRQ_SHOW 8 select GENERIC_IRQ_SHOW
diff --git a/arch/um/Kconfig.um b/arch/um/Kconfig.um
index 28a9885e3a37..4b2ed5858b2e 100644
--- a/arch/um/Kconfig.um
+++ b/arch/um/Kconfig.um
@@ -104,3 +104,19 @@ config PGTABLE_LEVELS
104 int 104 int
105 default 3 if 3_LEVEL_PGTABLES 105 default 3 if 3_LEVEL_PGTABLES
106 default 2 106 default 2
107
108config SECCOMP
109 def_bool y
110 prompt "Enable seccomp to safely compute untrusted bytecode"
111 ---help---
112 This kernel feature is useful for number crunching applications
113 that may need to compute untrusted bytecode during their
114 execution. By using pipes or other transports made available to
115 the process as file descriptors supporting the read/write
116 syscalls, it's possible to isolate those applications in
117 their own address space using seccomp. Once seccomp is
118 enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
119 and the task is only allowed to execute a few safe syscalls
120 defined by each seccomp mode.
121
122 If unsure, say Y.
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index e8ab93c3e638..39ba20755e03 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -535,11 +535,7 @@ static int read_cow_bitmap(int fd, void *buf, int offset, int len)
535{ 535{
536 int err; 536 int err;
537 537
538 err = os_seek_file(fd, offset); 538 err = os_pread_file(fd, buf, len, offset);
539 if (err < 0)
540 return err;
541
542 err = os_read_file(fd, buf, len);
543 if (err < 0) 539 if (err < 0)
544 return err; 540 return err;
545 541
@@ -1377,14 +1373,8 @@ static int update_bitmap(struct io_thread_req *req)
1377 if(req->cow_offset == -1) 1373 if(req->cow_offset == -1)
1378 return 0; 1374 return 0;
1379 1375
1380 n = os_seek_file(req->fds[1], req->cow_offset); 1376 n = os_pwrite_file(req->fds[1], &req->bitmap_words,
1381 if(n < 0){ 1377 sizeof(req->bitmap_words), req->cow_offset);
1382 printk("do_io - bitmap lseek failed : err = %d\n", -n);
1383 return 1;
1384 }
1385
1386 n = os_write_file(req->fds[1], &req->bitmap_words,
1387 sizeof(req->bitmap_words));
1388 if(n != sizeof(req->bitmap_words)){ 1378 if(n != sizeof(req->bitmap_words)){
1389 printk("do_io - bitmap update failed, err = %d fd = %d\n", -n, 1379 printk("do_io - bitmap update failed, err = %d fd = %d\n", -n,
1390 req->fds[1]); 1380 req->fds[1]);
@@ -1399,7 +1389,6 @@ static void do_io(struct io_thread_req *req)
1399 char *buf; 1389 char *buf;
1400 unsigned long len; 1390 unsigned long len;
1401 int n, nsectors, start, end, bit; 1391 int n, nsectors, start, end, bit;
1402 int err;
1403 __u64 off; 1392 __u64 off;
1404 1393
1405 if (req->op == UBD_FLUSH) { 1394 if (req->op == UBD_FLUSH) {
@@ -1428,18 +1417,12 @@ static void do_io(struct io_thread_req *req)
1428 len = (end - start) * req->sectorsize; 1417 len = (end - start) * req->sectorsize;
1429 buf = &req->buffer[start * req->sectorsize]; 1418 buf = &req->buffer[start * req->sectorsize];
1430 1419
1431 err = os_seek_file(req->fds[bit], off);
1432 if(err < 0){
1433 printk("do_io - lseek failed : err = %d\n", -err);
1434 req->error = 1;
1435 return;
1436 }
1437 if(req->op == UBD_READ){ 1420 if(req->op == UBD_READ){
1438 n = 0; 1421 n = 0;
1439 do { 1422 do {
1440 buf = &buf[n]; 1423 buf = &buf[n];
1441 len -= n; 1424 len -= n;
1442 n = os_read_file(req->fds[bit], buf, len); 1425 n = os_pread_file(req->fds[bit], buf, len, off);
1443 if (n < 0) { 1426 if (n < 0) {
1444 printk("do_io - read failed, err = %d " 1427 printk("do_io - read failed, err = %d "
1445 "fd = %d\n", -n, req->fds[bit]); 1428 "fd = %d\n", -n, req->fds[bit]);
@@ -1449,7 +1432,7 @@ static void do_io(struct io_thread_req *req)
1449 } while((n < len) && (n != 0)); 1432 } while((n < len) && (n != 0));
1450 if (n < len) memset(&buf[n], 0, len - n); 1433 if (n < len) memset(&buf[n], 0, len - n);
1451 } else { 1434 } else {
1452 n = os_write_file(req->fds[bit], buf, len); 1435 n = os_pwrite_file(req->fds[bit], buf, len, off);
1453 if(n != len){ 1436 if(n != len){
1454 printk("do_io - write failed err = %d " 1437 printk("do_io - write failed err = %d "
1455 "fd = %d\n", -n, req->fds[bit]); 1438 "fd = %d\n", -n, req->fds[bit]);
diff --git a/arch/um/include/asm/hardirq.h b/arch/um/include/asm/hardirq.h
new file mode 100644
index 000000000000..756f0778e327
--- /dev/null
+++ b/arch/um/include/asm/hardirq.h
@@ -0,0 +1,23 @@
1#ifndef __ASM_UM_HARDIRQ_H
2#define __ASM_UM_HARDIRQ_H
3
4#include <linux/cache.h>
5#include <linux/threads.h>
6
7typedef struct {
8 unsigned int __softirq_pending;
9} ____cacheline_aligned irq_cpustat_t;
10
11#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
12#include <linux/irq.h>
13
14#ifndef ack_bad_irq
15static inline void ack_bad_irq(unsigned int irq)
16{
17 printk(KERN_CRIT "unexpected IRQ trap at vector %02x\n", irq);
18}
19#endif
20
21#define __ARCH_IRQ_EXIT_IRQS_DISABLED 1
22
23#endif /* __ASM_UM_HARDIRQ_H */
diff --git a/arch/um/include/asm/syscall-generic.h b/arch/um/include/asm/syscall-generic.h
new file mode 100644
index 000000000000..9fb9cf8cd39a
--- /dev/null
+++ b/arch/um/include/asm/syscall-generic.h
@@ -0,0 +1,138 @@
1/*
2 * Access to user system call parameters and results
3 *
4 * See asm-generic/syscall.h for function descriptions.
5 *
6 * Copyright (C) 2015 Mickaël Salaün <mic@digikod.net>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __UM_SYSCALL_GENERIC_H
14#define __UM_SYSCALL_GENERIC_H
15
16#include <asm/ptrace.h>
17#include <linux/err.h>
18#include <linux/sched.h>
19#include <sysdep/ptrace.h>
20
21static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
22{
23
24 return PT_REGS_SYSCALL_NR(regs);
25}
26
27static inline void syscall_rollback(struct task_struct *task,
28 struct pt_regs *regs)
29{
30 /* do nothing */
31}
32
33static inline long syscall_get_error(struct task_struct *task,
34 struct pt_regs *regs)
35{
36 const long error = regs_return_value(regs);
37
38 return IS_ERR_VALUE(error) ? error : 0;
39}
40
41static inline long syscall_get_return_value(struct task_struct *task,
42 struct pt_regs *regs)
43{
44 return regs_return_value(regs);
45}
46
47static inline void syscall_set_return_value(struct task_struct *task,
48 struct pt_regs *regs,
49 int error, long val)
50{
51 PT_REGS_SET_SYSCALL_RETURN(regs, (long) error ?: val);
52}
53
54static inline void syscall_get_arguments(struct task_struct *task,
55 struct pt_regs *regs,
56 unsigned int i, unsigned int n,
57 unsigned long *args)
58{
59 const struct uml_pt_regs *r = &regs->regs;
60
61 switch (i) {
62 case 0:
63 if (!n--)
64 break;
65 *args++ = UPT_SYSCALL_ARG1(r);
66 case 1:
67 if (!n--)
68 break;
69 *args++ = UPT_SYSCALL_ARG2(r);
70 case 2:
71 if (!n--)
72 break;
73 *args++ = UPT_SYSCALL_ARG3(r);
74 case 3:
75 if (!n--)
76 break;
77 *args++ = UPT_SYSCALL_ARG4(r);
78 case 4:
79 if (!n--)
80 break;
81 *args++ = UPT_SYSCALL_ARG5(r);
82 case 5:
83 if (!n--)
84 break;
85 *args++ = UPT_SYSCALL_ARG6(r);
86 case 6:
87 if (!n--)
88 break;
89 default:
90 BUG();
91 break;
92 }
93}
94
95static inline void syscall_set_arguments(struct task_struct *task,
96 struct pt_regs *regs,
97 unsigned int i, unsigned int n,
98 const unsigned long *args)
99{
100 struct uml_pt_regs *r = &regs->regs;
101
102 switch (i) {
103 case 0:
104 if (!n--)
105 break;
106 UPT_SYSCALL_ARG1(r) = *args++;
107 case 1:
108 if (!n--)
109 break;
110 UPT_SYSCALL_ARG2(r) = *args++;
111 case 2:
112 if (!n--)
113 break;
114 UPT_SYSCALL_ARG3(r) = *args++;
115 case 3:
116 if (!n--)
117 break;
118 UPT_SYSCALL_ARG4(r) = *args++;
119 case 4:
120 if (!n--)
121 break;
122 UPT_SYSCALL_ARG5(r) = *args++;
123 case 5:
124 if (!n--)
125 break;
126 UPT_SYSCALL_ARG6(r) = *args++;
127 case 6:
128 if (!n--)
129 break;
130 default:
131 BUG();
132 break;
133 }
134}
135
136/* See arch/x86/um/asm/syscall.h for syscall_get_arch() definition. */
137
138#endif /* __UM_SYSCALL_GENERIC_H */
diff --git a/arch/um/include/asm/thread_info.h b/arch/um/include/asm/thread_info.h
index 53968aaf76f9..053baff03674 100644
--- a/arch/um/include/asm/thread_info.h
+++ b/arch/um/include/asm/thread_info.h
@@ -62,11 +62,13 @@ static inline struct thread_info *current_thread_info(void)
62#define TIF_SYSCALL_AUDIT 6 62#define TIF_SYSCALL_AUDIT 6
63#define TIF_RESTORE_SIGMASK 7 63#define TIF_RESTORE_SIGMASK 7
64#define TIF_NOTIFY_RESUME 8 64#define TIF_NOTIFY_RESUME 8
65#define TIF_SECCOMP 9 /* secure computing */
65 66
66#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) 67#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
67#define _TIF_SIGPENDING (1 << TIF_SIGPENDING) 68#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
68#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) 69#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
69#define _TIF_MEMDIE (1 << TIF_MEMDIE) 70#define _TIF_MEMDIE (1 << TIF_MEMDIE)
70#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) 71#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
72#define _TIF_SECCOMP (1 << TIF_SECCOMP)
71 73
72#endif 74#endif
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h
index 868e6c3f83dd..de5d572225f3 100644
--- a/arch/um/include/shared/os.h
+++ b/arch/um/include/shared/os.h
@@ -146,6 +146,8 @@ extern int os_read_file(int fd, void *buf, int len);
146extern int os_write_file(int fd, const void *buf, int count); 146extern int os_write_file(int fd, const void *buf, int count);
147extern int os_sync_file(int fd); 147extern int os_sync_file(int fd);
148extern int os_file_size(const char *file, unsigned long long *size_out); 148extern int os_file_size(const char *file, unsigned long long *size_out);
149extern int os_pread_file(int fd, void *buf, int len, unsigned long long offset);
150extern int os_pwrite_file(int fd, const void *buf, int count, unsigned long long offset);
149extern int os_file_modtime(const char *file, unsigned long *modtime); 151extern int os_file_modtime(const char *file, unsigned long *modtime);
150extern int os_pipe(int *fd, int stream, int close_on_exec); 152extern int os_pipe(int *fd, int stream, int close_on_exec);
151extern int os_set_fd_async(int fd); 153extern int os_set_fd_async(int fd);
@@ -282,7 +284,6 @@ extern void initial_thread_cb_skas(void (*proc)(void *),
282 void *arg); 284 void *arg);
283extern void halt_skas(void); 285extern void halt_skas(void);
284extern void reboot_skas(void); 286extern void reboot_skas(void);
285extern int get_syscall(struct uml_pt_regs *regs);
286 287
287/* irq.c */ 288/* irq.c */
288extern int os_waiting_for_events(struct irq_fd *active_fds); 289extern int os_waiting_for_events(struct irq_fd *active_fds);
diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c
index 1683b8efdfda..48b0dcbd87be 100644
--- a/arch/um/kernel/skas/syscall.c
+++ b/arch/um/kernel/skas/syscall.c
@@ -5,31 +5,38 @@
5 5
6#include <linux/kernel.h> 6#include <linux/kernel.h>
7#include <linux/ptrace.h> 7#include <linux/ptrace.h>
8#include <linux/seccomp.h>
8#include <kern_util.h> 9#include <kern_util.h>
9#include <sysdep/ptrace.h> 10#include <sysdep/ptrace.h>
11#include <sysdep/ptrace_user.h>
10#include <sysdep/syscalls.h> 12#include <sysdep/syscalls.h>
11#include <os.h>
12 13
13void handle_syscall(struct uml_pt_regs *r) 14void handle_syscall(struct uml_pt_regs *r)
14{ 15{
15 struct pt_regs *regs = container_of(r, struct pt_regs, regs); 16 struct pt_regs *regs = container_of(r, struct pt_regs, regs);
16 long result;
17 int syscall; 17 int syscall;
18 18
19 if (syscall_trace_enter(regs)) { 19 /* Initialize the syscall number and default return value. */
20 result = -ENOSYS; 20 UPT_SYSCALL_NR(r) = PT_SYSCALL_NR(r->gp);
21 PT_REGS_SET_SYSCALL_RETURN(regs, -ENOSYS);
22
23 /* Do the secure computing check first; failures should be fast. */
24 if (secure_computing() == -1)
25 return;
26
27 if (syscall_trace_enter(regs))
21 goto out; 28 goto out;
22 }
23 29
24 syscall = get_syscall(r); 30 /* Update the syscall number after orig_ax has potentially been updated
31 * with ptrace.
32 */
33 UPT_SYSCALL_NR(r) = PT_SYSCALL_NR(r->gp);
34 syscall = UPT_SYSCALL_NR(r);
25 35
26 if ((syscall > __NR_syscall_max) || syscall < 0) 36 if (syscall >= 0 && syscall <= __NR_syscall_max)
27 result = -ENOSYS; 37 PT_REGS_SET_SYSCALL_RETURN(regs,
28 else 38 EXECUTE_SYSCALL(syscall, regs));
29 result = EXECUTE_SYSCALL(syscall, regs);
30 39
31out: 40out:
32 PT_REGS_SET_SYSCALL_RETURN(regs, result);
33
34 syscall_trace_leave(regs); 41 syscall_trace_leave(regs);
35} 42}
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index 26e0164895e4..2db18cbbb0ea 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -264,6 +264,15 @@ int os_read_file(int fd, void *buf, int len)
264 return n; 264 return n;
265} 265}
266 266
267int os_pread_file(int fd, void *buf, int len, unsigned long long offset)
268{
269 int n = pread(fd, buf, len, offset);
270
271 if (n < 0)
272 return -errno;
273 return n;
274}
275
267int os_write_file(int fd, const void *buf, int len) 276int os_write_file(int fd, const void *buf, int len)
268{ 277{
269 int n = write(fd, (void *) buf, len); 278 int n = write(fd, (void *) buf, len);
@@ -282,6 +291,16 @@ int os_sync_file(int fd)
282 return n; 291 return n;
283} 292}
284 293
294int os_pwrite_file(int fd, const void *buf, int len, unsigned long long offset)
295{
296 int n = pwrite(fd, (void *) buf, len, offset);
297
298 if (n < 0)
299 return -errno;
300 return n;
301}
302
303
285int os_file_size(const char *file, unsigned long long *size_out) 304int os_file_size(const char *file, unsigned long long *size_out)
286{ 305{
287 struct uml_stat buf; 306 struct uml_stat buf;
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index 897e9ad0c108..8b1767668515 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -106,6 +106,17 @@ static int __init make_tempfile(const char *template)
106 } 106 }
107 } 107 }
108 108
109#ifdef O_TMPFILE
110 fd = open(tempdir, O_CLOEXEC | O_RDWR | O_EXCL | O_TMPFILE, 0700);
111 /*
112 * If the running system does not support O_TMPFILE flag then retry
113 * without it.
114 */
115 if (fd != -1 || (errno != EINVAL && errno != EISDIR &&
116 errno != EOPNOTSUPP))
117 return fd;
118#endif
119
109 tempname = malloc(strlen(tempdir) + strlen(template) + 1); 120 tempname = malloc(strlen(tempdir) + strlen(template) + 1);
110 if (tempname == NULL) 121 if (tempname == NULL)
111 return -1; 122 return -1;
@@ -142,12 +153,6 @@ static int __init create_tmp_file(unsigned long long len)
142 if (fd < 0) 153 if (fd < 0)
143 exit(1); 154 exit(1);
144 155
145 err = fchmod(fd, 0777);
146 if (err < 0) {
147 perror("fchmod");
148 exit(1);
149 }
150
151 /* 156 /*
152 * Seek to len - 1 because writing a character there will 157 * Seek to len - 1 because writing a character there will
153 * increase the file size by one byte, to the desired length. 158 * increase the file size by one byte, to the desired length.
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index c211153ca69a..7801666514ed 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -62,6 +62,7 @@ static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
62 62
63static int signals_enabled; 63static int signals_enabled;
64static unsigned int signals_pending; 64static unsigned int signals_pending;
65static unsigned int signals_active = 0;
65 66
66void sig_handler(int sig, struct siginfo *si, mcontext_t *mc) 67void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
67{ 68{
@@ -101,7 +102,12 @@ void timer_alarm_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
101 102
102 block_signals(); 103 block_signals();
103 104
105 signals_active |= SIGALRM_MASK;
106
104 timer_real_alarm_handler(mc); 107 timer_real_alarm_handler(mc);
108
109 signals_active &= ~SIGALRM_MASK;
110
105 set_signals(enabled); 111 set_signals(enabled);
106} 112}
107 113
@@ -286,8 +292,16 @@ void unblock_signals(void)
286 if (save_pending & SIGIO_MASK) 292 if (save_pending & SIGIO_MASK)
287 sig_handler_common(SIGIO, NULL, NULL); 293 sig_handler_common(SIGIO, NULL, NULL);
288 294
289 if (save_pending & SIGALRM_MASK) 295 /* Do not reenter the handler */
296
297 if ((save_pending & SIGALRM_MASK) && (!(signals_active & SIGALRM_MASK)))
290 timer_real_alarm_handler(NULL); 298 timer_real_alarm_handler(NULL);
299
300 /* Rerun the loop only if there is still pending SIGIO and not in TIMER handler */
301
302 if (!(signals_pending & SIGIO_MASK) && (signals_active & SIGALRM_MASK))
303 return;
304
291 } 305 }
292} 306}
293 307
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index b856c66ebd3a..23025d645160 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -172,13 +172,6 @@ static void handle_trap(int pid, struct uml_pt_regs *regs,
172 handle_syscall(regs); 172 handle_syscall(regs);
173} 173}
174 174
175int get_syscall(struct uml_pt_regs *regs)
176{
177 UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->gp);
178
179 return UPT_SYSCALL_NR(regs);
180}
181
182extern char __syscall_stub_start[]; 175extern char __syscall_stub_start[];
183 176
184static int userspace_tramp(void *stack) 177static int userspace_tramp(void *stack)
diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c
index 47f1ff056a54..22a358ef1b0c 100644
--- a/arch/um/os-Linux/start_up.c
+++ b/arch/um/os-Linux/start_up.c
@@ -94,6 +94,8 @@ static int start_ptraced_child(void)
94{ 94{
95 int pid, n, status; 95 int pid, n, status;
96 96
97 fflush(stdout);
98
97 pid = fork(); 99 pid = fork();
98 if (pid == 0) 100 if (pid == 0)
99 ptrace_child(); 101 ptrace_child();
diff --git a/arch/x86/um/Makefile b/arch/x86/um/Makefile
index a8fecc226946..3ee2bb6b440b 100644
--- a/arch/x86/um/Makefile
+++ b/arch/x86/um/Makefile
@@ -17,7 +17,7 @@ obj-y = bug.o bugs_$(BITS).o delay.o fault.o ksyms.o ldt.o \
17ifeq ($(CONFIG_X86_32),y) 17ifeq ($(CONFIG_X86_32),y)
18 18
19obj-y += checksum_32.o 19obj-y += checksum_32.o
20obj-$(CONFIG_BINFMT_ELF) += elfcore.o 20obj-$(CONFIG_ELF_CORE) += elfcore.o
21 21
22subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o 22subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o
23subarch-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += ../lib/rwsem.o 23subarch-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += ../lib/rwsem.o
diff --git a/arch/x86/um/asm/syscall.h b/arch/x86/um/asm/syscall.h
index 81d6562ce01d..11ab90dc5f14 100644
--- a/arch/x86/um/asm/syscall.h
+++ b/arch/x86/um/asm/syscall.h
@@ -1,6 +1,7 @@
1#ifndef __UM_ASM_SYSCALL_H 1#ifndef __UM_ASM_SYSCALL_H
2#define __UM_ASM_SYSCALL_H 2#define __UM_ASM_SYSCALL_H
3 3
4#include <asm/syscall-generic.h>
4#include <uapi/linux/audit.h> 5#include <uapi/linux/audit.h>
5 6
6typedef asmlinkage long (*sys_call_ptr_t)(unsigned long, unsigned long, 7typedef asmlinkage long (*sys_call_ptr_t)(unsigned long, unsigned long,
diff --git a/arch/x86/um/ptrace_32.c b/arch/x86/um/ptrace_32.c
index a29756f2d940..47c78d5e5c32 100644
--- a/arch/x86/um/ptrace_32.c
+++ b/arch/x86/um/ptrace_32.c
@@ -68,6 +68,7 @@ static const int reg_offsets[] = {
68 [EFL] = HOST_EFLAGS, 68 [EFL] = HOST_EFLAGS,
69 [UESP] = HOST_SP, 69 [UESP] = HOST_SP,
70 [SS] = HOST_SS, 70 [SS] = HOST_SS,
71 [ORIG_EAX] = HOST_ORIG_AX,
71}; 72};
72 73
73int putreg(struct task_struct *child, int regno, unsigned long value) 74int putreg(struct task_struct *child, int regno, unsigned long value)
@@ -83,6 +84,7 @@ int putreg(struct task_struct *child, int regno, unsigned long value)
83 case EAX: 84 case EAX:
84 case EIP: 85 case EIP:
85 case UESP: 86 case UESP:
87 case ORIG_EAX:
86 break; 88 break;
87 case FS: 89 case FS:
88 if (value && (value & 3) != 3) 90 if (value && (value & 3) != 3)
@@ -108,9 +110,6 @@ int putreg(struct task_struct *child, int regno, unsigned long value)
108 value &= FLAG_MASK; 110 value &= FLAG_MASK;
109 child->thread.regs.regs.gp[HOST_EFLAGS] |= value; 111 child->thread.regs.regs.gp[HOST_EFLAGS] |= value;
110 return 0; 112 return 0;
111 case ORIG_EAX:
112 child->thread.regs.regs.syscall = value;
113 return 0;
114 default : 113 default :
115 panic("Bad register in putreg() : %d\n", regno); 114 panic("Bad register in putreg() : %d\n", regno);
116 } 115 }
@@ -143,8 +142,6 @@ unsigned long getreg(struct task_struct *child, int regno)
143 142
144 regno >>= 2; 143 regno >>= 2;
145 switch (regno) { 144 switch (regno) {
146 case ORIG_EAX:
147 return child->thread.regs.regs.syscall;
148 case FS: 145 case FS:
149 case GS: 146 case GS:
150 case DS: 147 case DS:
@@ -163,6 +160,7 @@ unsigned long getreg(struct task_struct *child, int regno)
163 case EDI: 160 case EDI:
164 case EBP: 161 case EBP:
165 case EFL: 162 case EFL:
163 case ORIG_EAX:
166 break; 164 break;
167 default: 165 default:
168 panic("Bad register in getreg() : %d\n", regno); 166 panic("Bad register in getreg() : %d\n", regno);
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 7db524cc85b6..f49be23e78aa 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -730,15 +730,13 @@ static int hostfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode,
730 730
731 init_special_inode(inode, mode, dev); 731 init_special_inode(inode, mode, dev);
732 err = do_mknod(name, mode, MAJOR(dev), MINOR(dev)); 732 err = do_mknod(name, mode, MAJOR(dev), MINOR(dev));
733 if (!err) 733 if (err)
734 goto out_free; 734 goto out_free;
735 735
736 err = read_name(inode, name); 736 err = read_name(inode, name);
737 __putname(name); 737 __putname(name);
738 if (err) 738 if (err)
739 goto out_put; 739 goto out_put;
740 if (err)
741 goto out_put;
742 740
743 d_instantiate(dentry, inode); 741 d_instantiate(dentry, inode);
744 return 0; 742 return 0;
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index dacf71a43ad4..ba6c34ea5429 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -62,7 +62,7 @@ vmlinux_link()
62 -Wl,--start-group \ 62 -Wl,--start-group \
63 ${KBUILD_VMLINUX_MAIN} \ 63 ${KBUILD_VMLINUX_MAIN} \
64 -Wl,--end-group \ 64 -Wl,--end-group \
65 -lutil -lrt ${1} 65 -lutil -lrt -lpthread ${1}
66 rm -f linux 66 rm -f linux
67 fi 67 fi
68} 68}
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index 882fe83a3554..b9453b838162 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -1246,11 +1246,24 @@ TEST_F(TRACE_poke, getpid_runs_normally)
1246# error "Do not know how to find your architecture's registers and syscalls" 1246# error "Do not know how to find your architecture's registers and syscalls"
1247#endif 1247#endif
1248 1248
1249/* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for
1250 * architectures without HAVE_ARCH_TRACEHOOK (e.g. User-mode Linux).
1251 */
1252#if defined(__x86_64__) || defined(__i386__)
1253#define HAVE_GETREGS
1254#endif
1255
1249/* Architecture-specific syscall fetching routine. */ 1256/* Architecture-specific syscall fetching routine. */
1250int get_syscall(struct __test_metadata *_metadata, pid_t tracee) 1257int get_syscall(struct __test_metadata *_metadata, pid_t tracee)
1251{ 1258{
1252 struct iovec iov;
1253 ARCH_REGS regs; 1259 ARCH_REGS regs;
1260#ifdef HAVE_GETREGS
1261 EXPECT_EQ(0, ptrace(PTRACE_GETREGS, tracee, 0, &regs)) {
1262 TH_LOG("PTRACE_GETREGS failed");
1263 return -1;
1264 }
1265#else
1266 struct iovec iov;
1254 1267
1255 iov.iov_base = &regs; 1268 iov.iov_base = &regs;
1256 iov.iov_len = sizeof(regs); 1269 iov.iov_len = sizeof(regs);
@@ -1258,6 +1271,7 @@ int get_syscall(struct __test_metadata *_metadata, pid_t tracee)
1258 TH_LOG("PTRACE_GETREGSET failed"); 1271 TH_LOG("PTRACE_GETREGSET failed");
1259 return -1; 1272 return -1;
1260 } 1273 }
1274#endif
1261 1275
1262 return regs.SYSCALL_NUM; 1276 return regs.SYSCALL_NUM;
1263} 1277}
@@ -1266,13 +1280,16 @@ int get_syscall(struct __test_metadata *_metadata, pid_t tracee)
1266void change_syscall(struct __test_metadata *_metadata, 1280void change_syscall(struct __test_metadata *_metadata,
1267 pid_t tracee, int syscall) 1281 pid_t tracee, int syscall)
1268{ 1282{
1269 struct iovec iov;
1270 int ret; 1283 int ret;
1271 ARCH_REGS regs; 1284 ARCH_REGS regs;
1272 1285#ifdef HAVE_GETREGS
1286 ret = ptrace(PTRACE_GETREGS, tracee, 0, &regs);
1287#else
1288 struct iovec iov;
1273 iov.iov_base = &regs; 1289 iov.iov_base = &regs;
1274 iov.iov_len = sizeof(regs); 1290 iov.iov_len = sizeof(regs);
1275 ret = ptrace(PTRACE_GETREGSET, tracee, NT_PRSTATUS, &iov); 1291 ret = ptrace(PTRACE_GETREGSET, tracee, NT_PRSTATUS, &iov);
1292#endif
1276 EXPECT_EQ(0, ret); 1293 EXPECT_EQ(0, ret);
1277 1294
1278#if defined(__x86_64__) || defined(__i386__) || defined(__powerpc__) || \ 1295#if defined(__x86_64__) || defined(__i386__) || defined(__powerpc__) || \
@@ -1312,9 +1329,13 @@ void change_syscall(struct __test_metadata *_metadata,
1312 if (syscall == -1) 1329 if (syscall == -1)
1313 regs.SYSCALL_RET = 1; 1330 regs.SYSCALL_RET = 1;
1314 1331
1332#ifdef HAVE_GETREGS
1333 ret = ptrace(PTRACE_SETREGS, tracee, 0, &regs);
1334#else
1315 iov.iov_base = &regs; 1335 iov.iov_base = &regs;
1316 iov.iov_len = sizeof(regs); 1336 iov.iov_len = sizeof(regs);
1317 ret = ptrace(PTRACE_SETREGSET, tracee, NT_PRSTATUS, &iov); 1337 ret = ptrace(PTRACE_SETREGSET, tracee, NT_PRSTATUS, &iov);
1338#endif
1318 EXPECT_EQ(0, ret); 1339 EXPECT_EQ(0, ret);
1319} 1340}
1320 1341