Skip to content

Commit

Permalink
Merge branch 'for-linus-4.5-rc1' of git://git.kernel.org/pub/scm/linu…
Browse files Browse the repository at this point in the history
…x/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()
  • Loading branch information
torvalds committed Jan 12, 2016
2 parents 1baa5ef + 3e46b25 commit 4f31d77
Show file tree
Hide file tree
Showing 20 changed files with 285 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
| sh: | TODO |
| sparc: | TODO |
| tile: | ok |
| um: | TODO |
| um: | ok |
| unicore32: | TODO |
| x86: | ok |
| xtensa: | TODO |
Expand Down
1 change: 1 addition & 0 deletions arch/um/Kconfig.common
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ config UML
bool
default y
select HAVE_ARCH_AUDITSYSCALL
select HAVE_ARCH_SECCOMP_FILTER
select HAVE_UID16
select HAVE_FUTEX_CMPXCHG if FUTEX
select GENERIC_IRQ_SHOW
Expand Down
16 changes: 16 additions & 0 deletions arch/um/Kconfig.um
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,19 @@ config PGTABLE_LEVELS
int
default 3 if 3_LEVEL_PGTABLES
default 2

config SECCOMP
def_bool y
prompt "Enable seccomp to safely compute untrusted bytecode"
---help---
This kernel feature is useful for number crunching applications
that may need to compute untrusted bytecode during their
execution. By using pipes or other transports made available to
the process as file descriptors supporting the read/write
syscalls, it's possible to isolate those applications in
their own address space using seccomp. Once seccomp is
enabled via prctl(PR_SET_SECCOMP), it cannot be disabled
and the task is only allowed to execute a few safe syscalls
defined by each seccomp mode.

If unsure, say Y.
27 changes: 5 additions & 22 deletions arch/um/drivers/ubd_kern.c
Original file line number Diff line number Diff line change
Expand Up @@ -535,11 +535,7 @@ static int read_cow_bitmap(int fd, void *buf, int offset, int len)
{
int err;

err = os_seek_file(fd, offset);
if (err < 0)
return err;

err = os_read_file(fd, buf, len);
err = os_pread_file(fd, buf, len, offset);
if (err < 0)
return err;

Expand Down Expand Up @@ -1377,14 +1373,8 @@ static int update_bitmap(struct io_thread_req *req)
if(req->cow_offset == -1)
return 0;

n = os_seek_file(req->fds[1], req->cow_offset);
if(n < 0){
printk("do_io - bitmap lseek failed : err = %d\n", -n);
return 1;
}

n = os_write_file(req->fds[1], &req->bitmap_words,
sizeof(req->bitmap_words));
n = os_pwrite_file(req->fds[1], &req->bitmap_words,
sizeof(req->bitmap_words), req->cow_offset);
if(n != sizeof(req->bitmap_words)){
printk("do_io - bitmap update failed, err = %d fd = %d\n", -n,
req->fds[1]);
Expand All @@ -1399,7 +1389,6 @@ static void do_io(struct io_thread_req *req)
char *buf;
unsigned long len;
int n, nsectors, start, end, bit;
int err;
__u64 off;

if (req->op == UBD_FLUSH) {
Expand Down Expand Up @@ -1428,18 +1417,12 @@ static void do_io(struct io_thread_req *req)
len = (end - start) * req->sectorsize;
buf = &req->buffer[start * req->sectorsize];

err = os_seek_file(req->fds[bit], off);
if(err < 0){
printk("do_io - lseek failed : err = %d\n", -err);
req->error = 1;
return;
}
if(req->op == UBD_READ){
n = 0;
do {
buf = &buf[n];
len -= n;
n = os_read_file(req->fds[bit], buf, len);
n = os_pread_file(req->fds[bit], buf, len, off);
if (n < 0) {
printk("do_io - read failed, err = %d "
"fd = %d\n", -n, req->fds[bit]);
Expand All @@ -1449,7 +1432,7 @@ static void do_io(struct io_thread_req *req)
} while((n < len) && (n != 0));
if (n < len) memset(&buf[n], 0, len - n);
} else {
n = os_write_file(req->fds[bit], buf, len);
n = os_pwrite_file(req->fds[bit], buf, len, off);
if(n != len){
printk("do_io - write failed err = %d "
"fd = %d\n", -n, req->fds[bit]);
Expand Down
23 changes: 23 additions & 0 deletions arch/um/include/asm/hardirq.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef __ASM_UM_HARDIRQ_H
#define __ASM_UM_HARDIRQ_H

#include <linux/cache.h>
#include <linux/threads.h>

typedef struct {
unsigned int __softirq_pending;
} ____cacheline_aligned irq_cpustat_t;

#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
#include <linux/irq.h>

#ifndef ack_bad_irq
static inline void ack_bad_irq(unsigned int irq)
{
printk(KERN_CRIT "unexpected IRQ trap at vector %02x\n", irq);
}
#endif

#define __ARCH_IRQ_EXIT_IRQS_DISABLED 1

#endif /* __ASM_UM_HARDIRQ_H */
138 changes: 138 additions & 0 deletions arch/um/include/asm/syscall-generic.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/*
* Access to user system call parameters and results
*
* See asm-generic/syscall.h for function descriptions.
*
* Copyright (C) 2015 Mickaël Salaün <mic@digikod.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/

#ifndef __UM_SYSCALL_GENERIC_H
#define __UM_SYSCALL_GENERIC_H

#include <asm/ptrace.h>
#include <linux/err.h>
#include <linux/sched.h>
#include <sysdep/ptrace.h>

static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
{

return PT_REGS_SYSCALL_NR(regs);
}

static inline void syscall_rollback(struct task_struct *task,
struct pt_regs *regs)
{
/* do nothing */
}

static inline long syscall_get_error(struct task_struct *task,
struct pt_regs *regs)
{
const long error = regs_return_value(regs);

return IS_ERR_VALUE(error) ? error : 0;
}

static inline long syscall_get_return_value(struct task_struct *task,
struct pt_regs *regs)
{
return regs_return_value(regs);
}

static inline void syscall_set_return_value(struct task_struct *task,
struct pt_regs *regs,
int error, long val)
{
PT_REGS_SET_SYSCALL_RETURN(regs, (long) error ?: val);
}

static inline void syscall_get_arguments(struct task_struct *task,
struct pt_regs *regs,
unsigned int i, unsigned int n,
unsigned long *args)
{
const struct uml_pt_regs *r = &regs->regs;

switch (i) {
case 0:
if (!n--)
break;
*args++ = UPT_SYSCALL_ARG1(r);
case 1:
if (!n--)
break;
*args++ = UPT_SYSCALL_ARG2(r);
case 2:
if (!n--)
break;
*args++ = UPT_SYSCALL_ARG3(r);
case 3:
if (!n--)
break;
*args++ = UPT_SYSCALL_ARG4(r);
case 4:
if (!n--)
break;
*args++ = UPT_SYSCALL_ARG5(r);
case 5:
if (!n--)
break;
*args++ = UPT_SYSCALL_ARG6(r);
case 6:
if (!n--)
break;
default:
BUG();
break;
}
}

static inline void syscall_set_arguments(struct task_struct *task,
struct pt_regs *regs,
unsigned int i, unsigned int n,
const unsigned long *args)
{
struct uml_pt_regs *r = &regs->regs;

switch (i) {
case 0:
if (!n--)
break;
UPT_SYSCALL_ARG1(r) = *args++;
case 1:
if (!n--)
break;
UPT_SYSCALL_ARG2(r) = *args++;
case 2:
if (!n--)
break;
UPT_SYSCALL_ARG3(r) = *args++;
case 3:
if (!n--)
break;
UPT_SYSCALL_ARG4(r) = *args++;
case 4:
if (!n--)
break;
UPT_SYSCALL_ARG5(r) = *args++;
case 5:
if (!n--)
break;
UPT_SYSCALL_ARG6(r) = *args++;
case 6:
if (!n--)
break;
default:
BUG();
break;
}
}

/* See arch/x86/um/asm/syscall.h for syscall_get_arch() definition. */

#endif /* __UM_SYSCALL_GENERIC_H */
2 changes: 2 additions & 0 deletions arch/um/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,13 @@ static inline struct thread_info *current_thread_info(void)
#define TIF_SYSCALL_AUDIT 6
#define TIF_RESTORE_SIGMASK 7
#define TIF_NOTIFY_RESUME 8
#define TIF_SECCOMP 9 /* secure computing */

#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
#define _TIF_MEMDIE (1 << TIF_MEMDIE)
#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP (1 << TIF_SECCOMP)

#endif
3 changes: 2 additions & 1 deletion arch/um/include/shared/os.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ extern int os_read_file(int fd, void *buf, int len);
extern int os_write_file(int fd, const void *buf, int count);
extern int os_sync_file(int fd);
extern int os_file_size(const char *file, unsigned long long *size_out);
extern int os_pread_file(int fd, void *buf, int len, unsigned long long offset);
extern int os_pwrite_file(int fd, const void *buf, int count, unsigned long long offset);
extern int os_file_modtime(const char *file, unsigned long *modtime);
extern int os_pipe(int *fd, int stream, int close_on_exec);
extern int os_set_fd_async(int fd);
Expand Down Expand Up @@ -282,7 +284,6 @@ extern void initial_thread_cb_skas(void (*proc)(void *),
void *arg);
extern void halt_skas(void);
extern void reboot_skas(void);
extern int get_syscall(struct uml_pt_regs *regs);

/* irq.c */
extern int os_waiting_for_events(struct irq_fd *active_fds);
Expand Down
31 changes: 19 additions & 12 deletions arch/um/kernel/skas/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,38 @@

#include <linux/kernel.h>
#include <linux/ptrace.h>
#include <linux/seccomp.h>
#include <kern_util.h>
#include <sysdep/ptrace.h>
#include <sysdep/ptrace_user.h>
#include <sysdep/syscalls.h>
#include <os.h>

void handle_syscall(struct uml_pt_regs *r)
{
struct pt_regs *regs = container_of(r, struct pt_regs, regs);
long result;
int syscall;

if (syscall_trace_enter(regs)) {
result = -ENOSYS;
/* Initialize the syscall number and default return value. */
UPT_SYSCALL_NR(r) = PT_SYSCALL_NR(r->gp);
PT_REGS_SET_SYSCALL_RETURN(regs, -ENOSYS);

/* Do the secure computing check first; failures should be fast. */
if (secure_computing() == -1)
return;

if (syscall_trace_enter(regs))
goto out;
}

syscall = get_syscall(r);
/* Update the syscall number after orig_ax has potentially been updated
* with ptrace.
*/
UPT_SYSCALL_NR(r) = PT_SYSCALL_NR(r->gp);
syscall = UPT_SYSCALL_NR(r);

if ((syscall > __NR_syscall_max) || syscall < 0)
result = -ENOSYS;
else
result = EXECUTE_SYSCALL(syscall, regs);
if (syscall >= 0 && syscall <= __NR_syscall_max)
PT_REGS_SET_SYSCALL_RETURN(regs,
EXECUTE_SYSCALL(syscall, regs));

out:
PT_REGS_SET_SYSCALL_RETURN(regs, result);

syscall_trace_leave(regs);
}
19 changes: 19 additions & 0 deletions arch/um/os-Linux/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,15 @@ int os_read_file(int fd, void *buf, int len)
return n;
}

int os_pread_file(int fd, void *buf, int len, unsigned long long offset)
{
int n = pread(fd, buf, len, offset);

if (n < 0)
return -errno;
return n;
}

int os_write_file(int fd, const void *buf, int len)
{
int n = write(fd, (void *) buf, len);
Expand All @@ -282,6 +291,16 @@ int os_sync_file(int fd)
return n;
}

int os_pwrite_file(int fd, const void *buf, int len, unsigned long long offset)
{
int n = pwrite(fd, (void *) buf, len, offset);

if (n < 0)
return -errno;
return n;
}


int os_file_size(const char *file, unsigned long long *size_out)
{
struct uml_stat buf;
Expand Down
Loading

0 comments on commit 4f31d77

Please sign in to comment.