diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-12 16:27:18 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-12 16:27:18 -0500 |
commit | 4f31d774dd5239e563f22ffe1403292414e6f779 (patch) | |
tree | 5edfdcc2adf491f340510694b8718d09378fdd15 | |
parent | 1baa5efbeb6eb75de697f7b5931094be33f12005 (diff) | |
parent | 3e46b25376321db119bc8507ce8c8841c580e736 (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.txt | 2 | ||||
-rw-r--r-- | arch/um/Kconfig.common | 1 | ||||
-rw-r--r-- | arch/um/Kconfig.um | 16 | ||||
-rw-r--r-- | arch/um/drivers/ubd_kern.c | 27 | ||||
-rw-r--r-- | arch/um/include/asm/hardirq.h | 23 | ||||
-rw-r--r-- | arch/um/include/asm/syscall-generic.h | 138 | ||||
-rw-r--r-- | arch/um/include/asm/thread_info.h | 2 | ||||
-rw-r--r-- | arch/um/include/shared/os.h | 3 | ||||
-rw-r--r-- | arch/um/kernel/skas/syscall.c | 31 | ||||
-rw-r--r-- | arch/um/os-Linux/file.c | 19 | ||||
-rw-r--r-- | arch/um/os-Linux/mem.c | 17 | ||||
-rw-r--r-- | arch/um/os-Linux/signal.c | 16 | ||||
-rw-r--r-- | arch/um/os-Linux/skas/process.c | 7 | ||||
-rw-r--r-- | arch/um/os-Linux/start_up.c | 2 | ||||
-rw-r--r-- | arch/x86/um/Makefile | 2 | ||||
-rw-r--r-- | arch/x86/um/asm/syscall.h | 1 | ||||
-rw-r--r-- | arch/x86/um/ptrace_32.c | 8 | ||||
-rw-r--r-- | fs/hostfs/hostfs_kern.c | 4 | ||||
-rwxr-xr-x | scripts/link-vmlinux.sh | 2 | ||||
-rw-r--r-- | tools/testing/selftests/seccomp/seccomp_bpf.c | 27 |
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 | |||
108 | config 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 | |||
7 | typedef 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 | ||
15 | static 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 | |||
21 | static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs) | ||
22 | { | ||
23 | |||
24 | return PT_REGS_SYSCALL_NR(regs); | ||
25 | } | ||
26 | |||
27 | static inline void syscall_rollback(struct task_struct *task, | ||
28 | struct pt_regs *regs) | ||
29 | { | ||
30 | /* do nothing */ | ||
31 | } | ||
32 | |||
33 | static 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 | |||
41 | static inline long syscall_get_return_value(struct task_struct *task, | ||
42 | struct pt_regs *regs) | ||
43 | { | ||
44 | return regs_return_value(regs); | ||
45 | } | ||
46 | |||
47 | static 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 | |||
54 | static 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 = ®s->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 | |||
95 | static 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 = ®s->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); | |||
146 | extern int os_write_file(int fd, const void *buf, int count); | 146 | extern int os_write_file(int fd, const void *buf, int count); |
147 | extern int os_sync_file(int fd); | 147 | extern int os_sync_file(int fd); |
148 | extern int os_file_size(const char *file, unsigned long long *size_out); | 148 | extern int os_file_size(const char *file, unsigned long long *size_out); |
149 | extern int os_pread_file(int fd, void *buf, int len, unsigned long long offset); | ||
150 | extern int os_pwrite_file(int fd, const void *buf, int count, unsigned long long offset); | ||
149 | extern int os_file_modtime(const char *file, unsigned long *modtime); | 151 | extern int os_file_modtime(const char *file, unsigned long *modtime); |
150 | extern int os_pipe(int *fd, int stream, int close_on_exec); | 152 | extern int os_pipe(int *fd, int stream, int close_on_exec); |
151 | extern int os_set_fd_async(int fd); | 153 | extern 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); |
283 | extern void halt_skas(void); | 285 | extern void halt_skas(void); |
284 | extern void reboot_skas(void); | 286 | extern void reboot_skas(void); |
285 | extern int get_syscall(struct uml_pt_regs *regs); | ||
286 | 287 | ||
287 | /* irq.c */ | 288 | /* irq.c */ |
288 | extern int os_waiting_for_events(struct irq_fd *active_fds); | 289 | extern 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 | ||
13 | void handle_syscall(struct uml_pt_regs *r) | 14 | void 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 | ||
31 | out: | 40 | out: |
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 | ||
267 | int 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 | |||
267 | int os_write_file(int fd, const void *buf, int len) | 276 | int 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 | ||
294 | int 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 | |||
285 | int os_file_size(const char *file, unsigned long long *size_out) | 304 | int 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 | ||
63 | static int signals_enabled; | 63 | static int signals_enabled; |
64 | static unsigned int signals_pending; | 64 | static unsigned int signals_pending; |
65 | static unsigned int signals_active = 0; | ||
65 | 66 | ||
66 | void sig_handler(int sig, struct siginfo *si, mcontext_t *mc) | 67 | void 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 | ||
175 | int 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 | |||
182 | extern char __syscall_stub_start[]; | 175 | extern char __syscall_stub_start[]; |
183 | 176 | ||
184 | static int userspace_tramp(void *stack) | 177 | static 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 \ | |||
17 | ifeq ($(CONFIG_X86_32),y) | 17 | ifeq ($(CONFIG_X86_32),y) |
18 | 18 | ||
19 | obj-y += checksum_32.o | 19 | obj-y += checksum_32.o |
20 | obj-$(CONFIG_BINFMT_ELF) += elfcore.o | 20 | obj-$(CONFIG_ELF_CORE) += elfcore.o |
21 | 21 | ||
22 | subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o | 22 | subarch-y = ../lib/string_32.o ../lib/atomic64_32.o ../lib/atomic64_cx8_32.o |
23 | subarch-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += ../lib/rwsem.o | 23 | subarch-$(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 | ||
6 | typedef asmlinkage long (*sys_call_ptr_t)(unsigned long, unsigned long, | 7 | typedef 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 | ||
73 | int putreg(struct task_struct *child, int regno, unsigned long value) | 74 | int 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. */ |
1250 | int get_syscall(struct __test_metadata *_metadata, pid_t tracee) | 1257 | int 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, ®s)) { | ||
1262 | TH_LOG("PTRACE_GETREGS failed"); | ||
1263 | return -1; | ||
1264 | } | ||
1265 | #else | ||
1266 | struct iovec iov; | ||
1254 | 1267 | ||
1255 | iov.iov_base = ®s; | 1268 | iov.iov_base = ®s; |
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) | |||
1266 | void change_syscall(struct __test_metadata *_metadata, | 1280 | void 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, ®s); | ||
1287 | #else | ||
1288 | struct iovec iov; | ||
1273 | iov.iov_base = ®s; | 1289 | iov.iov_base = ®s; |
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, ®s); | ||
1334 | #else | ||
1315 | iov.iov_base = ®s; | 1335 | iov.iov_base = ®s; |
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 | ||