Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 311917
b: refs/heads/master
c: 5651721
h: refs/heads/master
i:
  311915: 96c6f92
v: v3
  • Loading branch information
Will Drewry authored and Linus Torvalds committed Jul 13, 2012
1 parent 458b805 commit d219be7
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ac7d181e323a888015e19e2e4d776095a0433787
refs/heads/master: 5651721edec25bf73cee060150e684044eac42dc
35 changes: 31 additions & 4 deletions trunk/arch/x86/kernel/vsyscall_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,15 @@ static int addr_to_vsyscall_nr(unsigned long addr)
return nr;
}

static int vsyscall_seccomp(struct task_struct *tsk, int syscall_nr)
{
if (!seccomp_mode(&tsk->seccomp))
return 0;
task_pt_regs(tsk)->orig_ax = syscall_nr;
task_pt_regs(tsk)->ax = syscall_nr;
return __secure_computing(syscall_nr);
}

static bool write_ok_or_segv(unsigned long ptr, size_t size)
{
/*
Expand Down Expand Up @@ -174,6 +183,7 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
int vsyscall_nr;
int prev_sig_on_uaccess_error;
long ret;
int skip;

/*
* No point in checking CS -- the only way to get here is a user mode
Expand Down Expand Up @@ -205,9 +215,6 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
}

tsk = current;
if (seccomp_mode(&tsk->seccomp))
do_exit(SIGKILL);

/*
* With a real vsyscall, page faults cause SIGSEGV. We want to
* preserve that behavior to make writing exploits harder.
Expand All @@ -222,8 +229,13 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
* address 0".
*/
ret = -EFAULT;
skip = 0;
switch (vsyscall_nr) {
case 0:
skip = vsyscall_seccomp(tsk, __NR_gettimeofday);
if (skip)
break;

if (!write_ok_or_segv(regs->di, sizeof(struct timeval)) ||
!write_ok_or_segv(regs->si, sizeof(struct timezone)))
break;
Expand All @@ -234,13 +246,21 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
break;

case 1:
skip = vsyscall_seccomp(tsk, __NR_time);
if (skip)
break;

if (!write_ok_or_segv(regs->di, sizeof(time_t)))
break;

ret = sys_time((time_t __user *)regs->di);
break;

case 2:
skip = vsyscall_seccomp(tsk, __NR_getcpu);
if (skip)
break;

if (!write_ok_or_segv(regs->di, sizeof(unsigned)) ||
!write_ok_or_segv(regs->si, sizeof(unsigned)))
break;
Expand All @@ -253,6 +273,12 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)

current_thread_info()->sig_on_uaccess_error = prev_sig_on_uaccess_error;

if (skip) {
if ((long)regs->ax <= 0L) /* seccomp errno emulation */
goto do_ret;
goto done; /* seccomp trace/trap */
}

if (ret == -EFAULT) {
/* Bad news -- userspace fed a bad pointer to a vsyscall. */
warn_bad_vsyscall(KERN_INFO, regs,
Expand All @@ -271,10 +297,11 @@ bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)

regs->ax = ret;

do_ret:
/* Emulate a ret instruction. */
regs->ip = caller;
regs->sp += 8;

done:
return true;

sigsegv:
Expand Down

0 comments on commit d219be7

Please sign in to comment.