aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2018-11-23 03:41:11 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2018-11-23 18:27:19 +0100
commit3564c6dcc370d3d1e43913db45b2ea16e8c26662 (patch)
tree51f07d54f2c8ab4b923598fa11d3f14cdd7587f2
parentWrite below stack pointer instead of mmapping (diff)
downloadkernel-assisted-superuser-3564c6dcc370d3d1e43913db45b2ea16e8c26662.tar.xz
kernel-assisted-superuser-3564c6dcc370d3d1e43913db45b2ea16e8c26662.zip
Use sys_write instead of kernel_write
This is mostly worse in all ways, except that we don't have to worry about the API of kernel_write changing between kernels, which has happened before.
-rw-r--r--superuser.c23
1 files changed, 11 insertions, 12 deletions
diff --git a/superuser.c b/superuser.c
index 895c5e6..efc0fd7 100644
--- a/superuser.c
+++ b/superuser.c
@@ -14,10 +14,10 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <linux/uaccess.h>
#include <linux/module.h>
-#include <linux/file.h>
#include <linux/fs.h>
#include <linux/mman.h>
#include <linux/ptrace.h>
+#include <linux/syscalls.h>
static bool is_su(const char __user *filename)
{
@@ -27,14 +27,19 @@ static bool is_su(const char __user *filename)
return likely(!copy_from_user(ufn, filename, sizeof(ufn))) && unlikely(!memcmp(ufn, su_path, sizeof(ufn)));
}
-static char __user *sh_user_path(void)
+static void __user *userspace_stack_buffer(const void *d, size_t len)
{
- static const char sh_path[] = "/system/bin/sh";
/* To avoid having to mmap a page in userspace, just write below the stack pointer. */
- char __user *p = (void __user *)current_user_stack_pointer() - sizeof(sh_path);
+ char __user *p = (void __user *)current_user_stack_pointer() - len;
+
+ return copy_to_user(p, d, len) ? NULL : p;
+}
- return copy_to_user(p, sh_path, sizeof(sh_path)) ? NULL : p;
+static char __user *sh_user_path(void)
+{
+ static const char sh_path[] = "/system/bin/sh";
+ return userspace_stack_buffer(sh_path, sizeof(sh_path));
}
static long(*old_newfstatat)(int dfd, const char __user *filename, struct stat *statbuf, int flag);
@@ -58,7 +63,6 @@ static long (*old_execve)(const char __user *filename, const char __user *const
static long new_execve(const char __user *filename, const char __user *const __user *argv, const char __user *const __user *envp)
{
static const char now_root[] = "You are now root.\n";
- struct file *stderr;
struct cred *cred;
if (!is_su(filename))
@@ -88,12 +92,7 @@ static long new_execve(const char __user *filename, const char __user *const __u
memset(&cred->cap_bset, 0xff, sizeof(cred->cap_bset));
memset(&cred->cap_ambient, 0xff, sizeof(cred->cap_ambient));
- stderr = fget(2);
- if (stderr) {
- kernel_write(stderr, now_root, sizeof(now_root) - 1, 0);
- fput(stderr);
- }
-
+ sys_write(2, userspace_stack_buffer(now_root, sizeof(now_root)), sizeof(now_root) - 1);
return old_execve(sh_user_path(), argv, envp);
}