Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GID, PID, and UID targeting #15

Merged
merged 7 commits into from
Jun 11, 2019
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/module/config.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
#include "config.h"

unsigned int krf_rng_state = 0;
unsigned int krf_personality = 0x001c;
unsigned int krf_probability = 1000;
unsigned int krf_targeted_uid = 1002;
unsigned int krf_log_faults = 0;

krf_target_options_t krf_target_options = {0};
21 changes: 21 additions & 0 deletions src/module/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define KRF_PROBABILITY_FILENAME "probability"
#define KRF_CONTROL_FILENAME "control"
#define KRF_LOG_FAULTS_FILENAME "log_faults"
#define KRF_TARGETING_FILENAME "targeting"

/* All of our options are unsigned ints,
* so 32 bytes should be more than enough for their string reps
Expand All @@ -17,3 +18,23 @@ extern unsigned int krf_rng_state;
extern unsigned int krf_personality;
extern unsigned int krf_probability;
extern unsigned int krf_log_faults;
extern unsigned int krf_targeting;

#define KRF_T_MODE_MAX 31
#define KRF_T_MODE_MAX_MASK (1 << KRF_T_MODE_MAX)

typedef enum {
KRF_T_MODE_PERSONALITY = 0,
KRF_T_MODE_PID,
KRF_T_MODE_UID,
KRF_T_MODE_GID,
// Insert new modes here
KRF_T_NUM_MODES
} krf_target_mode_t;
woodruffw marked this conversation as resolved.
Show resolved Hide resolved

typedef struct {
unsigned int mode_mask;
unsigned int target_data[KRF_T_MODE_MAX];
} krf_target_options_t;

extern krf_target_options_t krf_target_options;
72 changes: 71 additions & 1 deletion src/module/krf.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <linux/kallsyms.h>
#include <linux/unistd.h>
#include <linux/proc_fs.h>
#include <linux/string.h>

#include "config.h"
#include "syscalls.h"
Expand All @@ -25,6 +26,8 @@ static ssize_t probability_file_write(struct file *, const char __user *, size_t
static ssize_t control_file_write(struct file *, const char __user *, size_t, loff_t *);
static ssize_t log_faults_file_read(struct file *, char __user *, size_t, loff_t *);
static ssize_t log_faults_file_write(struct file *, const char __user *, size_t, loff_t *);
static ssize_t targeting_file_read(struct file *, char __user *, size_t, loff_t *);
static ssize_t targeting_file_write(struct file *, const char __user *, size_t, loff_t *);

static struct proc_dir_entry *krf_dir;

Expand Down Expand Up @@ -57,6 +60,12 @@ static const struct file_operations log_faults_file_ops = {
.write = log_faults_file_write,
};

static const struct file_operations targeting_file_ops = {
.owner = THIS_MODULE,
.read = targeting_file_read,
.write = targeting_file_write,
};

int init_module(void) {
int ret;

Expand Down Expand Up @@ -101,7 +110,8 @@ static int krf_init(void) {
proc_create(KRF_PERSONALITY_FILENAME, 644, krf_dir, &personality_file_ops) == NULL ||
proc_create(KRF_PROBABILITY_FILENAME, 644, krf_dir, &probability_file_ops) == NULL ||
proc_create(KRF_CONTROL_FILENAME, 644, krf_dir, &control_file_ops) == NULL ||
proc_create(KRF_LOG_FAULTS_FILENAME, 644, krf_dir, &log_faults_file_ops) == NULL) {
proc_create(KRF_LOG_FAULTS_FILENAME, 644, krf_dir, &log_faults_file_ops) == NULL ||
proc_create(KRF_TARGETING_FILENAME, 644, krf_dir, &targeting_file_ops) == NULL) {
printk(KERN_ERR "krf couldn't create /proc entries\n");
return -3;
}
Expand Down Expand Up @@ -330,3 +340,63 @@ static ssize_t log_faults_file_write(struct file *f, const char __user *ubuf, si
*off = buflen;
return buflen;
}

static ssize_t targeting_file_read(struct file *f, char __user *ubuf, size_t size, loff_t *off) {
char buf[KRF_PROCFS_MAX_SIZE + 1] = {0};
size_t buflen = 0;
size_t offset = 0;
size_t current_mode;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use unsigned int for current_mode here, just for consistency with the actual structure.

for (current_mode = 0; current_mode < KRF_T_NUM_MODES; current_mode++) {
if ((krf_target_options.mode_mask & (1 << current_mode)) && (offset < KRF_PROCFS_MAX_SIZE)) {
woodruffw marked this conversation as resolved.
Show resolved Hide resolved
offset += sprintf(buf + offset, "%lu %u\n", current_mode,
krf_target_options.target_data[current_mode]);
}
}
buflen = strnlen(buf, KRF_PROCFS_MAX_SIZE);

if (*off > 0 || size < buflen) {
return 0;
}

if (copy_to_user(ubuf, buf, buflen)) {
return -EFAULT;
}

*off = buflen;
return buflen;
}

static ssize_t targeting_file_write(struct file *f, const char __user *ubuf, size_t size,
loff_t *off) {
char buf[KRF_PROCFS_MAX_SIZE + 1] = {0};
size_t buflen = 0;
krf_target_mode_t mode;
unsigned int data;

if (size > KRF_PROCFS_MAX_SIZE) {
size = KRF_PROCFS_MAX_SIZE;
}

if (copy_from_user(buf, ubuf, size)) {
return -EFAULT;
}

if (sscanf(buf, "%u %u", &mode, &data) != 2) {
return -EINVAL;
}

if ((mode == 0) && (data == 0)) { // If both arguments are zero, remove all targeting
woodruffw marked this conversation as resolved.
Show resolved Hide resolved
krf_target_options.mode_mask = 0;
} else {
if (mode >= KRF_T_NUM_MODES) {
return -EINVAL;
}
krf_target_options.mode_mask |= (1 << mode);
krf_target_options.target_data[mode] = data;
}

buflen = strnlen(buf, KRF_PROCFS_MAX_SIZE);

*off = buflen;
return buflen;
}
40 changes: 39 additions & 1 deletion src/module/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,45 @@

#define KRF_DEFINE(sys) asmlinkage krf_sys_##sys

#define KRF_TARGETED() ((current->personality & krf_personality) != 0)
#define KRF_TARGETED() \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's go ahead and make this an inline function, below the externs:

static __always_inline int KRF_TARGETED(void) {
  // ...
}

Might also be worth updating module/codegen/codegen so that we can make it krf_targeted instead of all caps.

({ \
int targeted = 1; \
size_t i = 0; \
for (; i < KRF_T_NUM_MODES; i++) { \
if (targeted == 0) \
break; \
\
if (krf_target_options.mode_mask & (1 << i)) { \
switch (i) { \
case KRF_T_MODE_PERSONALITY: \
if ((current->personality & krf_target_options.target_data[i]) != 0) \
targeted++; \
else \
targeted = 0; \
break; \
case KRF_T_MODE_PID: \
if (current->pid == krf_target_options.target_data[i]) \
targeted++; \
else \
targeted = 0; \
break; \
case KRF_T_MODE_UID: \
if (current->cred->uid.val == krf_target_options.target_data[i]) \
targeted++; \
else \
targeted = 0; \
break; \
case KRF_T_MODE_GID: \
if (current->cred->gid.val == krf_target_options.target_data[i]) \
targeted++; \
else \
targeted = 0; \
break; \
} \
} \
} \
(targeted & (~1)); \
})

/* A table of pointers to faulty syscalls.
*/
Expand Down