4
votes

Within a Linux kernel module, I need to disable rp_filter in some way. This would typically be possible from user-space via a couple of simple sysctl calls :

sysctl net.ipv4.conf.all.rp_filter=0
sysctl net.ipv4.conf.[ifname].rp_filter=0

How can I achieve the same result from kernel space? My first idea is that I probably need to write into the relative proc files. If so, what is the proper way to do this?

Thanks. R

1
Can you change the implementation of net/ipv4/devinet.c ? - stdcall
Nope. I believe there should be some API somewhere to do this without hacking.. Basically I'd just need to know where the rp_filter flag is intercepted within the kernel, and from there follow the calls path - Riccardo Manfrin
I've checked. you can't access it directly, as it's defined static in the module. it's not exported. There are few exported functions, you can check if they allow access to that. - stdcall

1 Answers

0
votes

I'm looking at the implementation of sysctl in the kernel, and I've found that doing a sysctl is just the same as writing a value to a file in the /proc filesystem.

In your case you just want to do the equivalent of:

echo 0 >/proc/sys/net/ipv4/conf/all/rp_filter

Here is a rough code sample, based on what I see in the kernel code I am reading just now:

struct vfsmount *mnt;
struct file *file;
ssize_t result;
char *pathname = "sys/net/ipv4/conf/all/rp_filter";
int flags = O_WRONLY;

mnt = task_active_pid_ns(current)->proc_mnt;
file = file_open_root(mnt->mnt_root, mnt, pathname, flags);
result = PTR_ERR(file);
if (IS_ERR(file)) {
  // oops, something bad happened
} else {
  char *buffer = "\0";
  result = kernel_write(file, buffer, 1, 0); // last 2 args are 'count' and 'pos'
  if (result < 0) {
    // oops, something else bad happened
  }
}
fput(file);

This is just a rough sample, so you will have to do your own research and testing to get it working. Good luck!