Skip to content

Commit

Permalink
GID, PID, and UID targeting (#15)
Browse files Browse the repository at this point in the history
* module: Add single PID targeting

* module: Add single UID targeting

* module: Add single GID targeting

* module: formatting fixes for targeting commits

* module: targeting proc file

* module: add printk, static_assert, and correct types

* module: enlarge KRF_PROCFS_MAX_SIZE
  • Loading branch information
hmwildermuth authored and woodruffw committed Jun 11, 2019
1 parent fd72733 commit 8d49c71
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 4 deletions.
2 changes: 1 addition & 1 deletion src/module/codegen/codegen
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ SYSCALLS.each do |call, spec|
long KRF_DEFINE(#{call})(#{spec["proto"]}) {
typeof(sys_#{call}) *real_#{call} = (void *)krf_sys_call_table[__NR_#{nr}];
if (KRF_TARGETED() && (KRF_RNG_NEXT() % krf_probability) == 0) {
if (krf_targeted() && (KRF_RNG_NEXT() % krf_probability) == 0) {
return KRF_SYS_INTERNAL(#{call})(#{spec["parms"]});
} else {
return real_#{call}(#{spec["parms"]});
Expand Down
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};
25 changes: 24 additions & 1 deletion src/module/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,37 @@
#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
* plus a trailing newline.
*/
#define KRF_PROCFS_MAX_SIZE 32
#define KRF_PROCFS_MAX_SIZE 255

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;

_Static_assert(((KRF_T_NUM_MODES) <= (KRF_T_MODE_MAX)), "Too many modes");

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;
73 changes: 72 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,64 @@ 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;
unsigned int current_mode;
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)) {
offset += sprintf(buf + offset, "%u %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
krf_target_options.mode_mask = 0;
printk(KERN_INFO "krf: flushing all targeting options\n");
} 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;
}
39 changes: 38 additions & 1 deletion src/module/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,44 @@

#define KRF_DEFINE(sys) asmlinkage krf_sys_##sys

#define KRF_TARGETED() ((current->personality & krf_personality) != 0)
static __always_inline int krf_targeted(void) {
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;
}
}
}
return (targeted & (~1));
}

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

0 comments on commit 8d49c71

Please sign in to comment.