Hello,
I am working on a network packet capturing module, and need to use sysctl to provide an easy mechanism for changing the settings.
With some code digging and the very limited information provided about registering new keys with sysctl, I was able to add few of my settings to the sysctl. The process involves creating arrays of ctl_table structs, and properly nesting them (parent/child).
However, the structure I want to achieve is:
net
+-my_module
--+--eth0
-----+--setting1
-----+--setting2
--+--eth1
-----+--setting1
-----+--setting2
--+--ethXX
-----+--setting1
-----+--setting2
where the user can specify which interface will be controlled using sysctl (since there might be eth3, eth4, eth12, eth13; and I don't want to have dummy sysctl for eth0-ethXX)
To do this, I wrote a function that will be called (and passed the interface name), and will register the directory/settings with sysctl. Part of the ctl_tables that I have is:
static ctl_table interface_table[] = {
{
.ctl_name = 0,
.procname = "setting1",
.data = &my_data,
.maxlen = sizeof(int),
.mode = 0644,
.proc_handler = &proc_dointvec
},{ .ctl_name = 0 }
};
static ctl_table iface_parent_table[] = {
{
.ctl_name = 0,
.mode = 0555,
.child = interface_table
},{ .ctl_name = 0 }
};
racetrack_table[0].procname = procname;
// ... more tables like these follow ...
Now, this works fine, when this function is called only once. Since the ctl_tables are defined to be static, this isn't unexpected.
However, when I remove the static keyword, the kernel crashes when I try to access/ls my directory in /proc/sys/. I attempted to explicitly allocate memory in this function by doing something like this:
tt = (ctl_table *)kmalloc(2 * sizeof(ctl_table), GFP_KERNEL);
tt[0].ctl_name = 0;
tt[0].procname = "setting1";
tt[0].data = &my_data;
tt[0].maxlen = sizeof(int);
tt[0].mode = 0644;
tt[0].proc_handler = &proc_dointvec;
tt[1].ctl_name = 0;
// ... more of these follow ...but this resulted in the same behaviour.
So my question/s are why is this happening; what am I doing wrong; and how do I go about dynamically registering with the sysctl.
Thanks,
i.b.
Zero the memory
1. I don't think you understand what the static keyword actually does. One of the thing it does is give you memory initialized to all zeroes.
http://en.wikipedia.org/wiki/Static_variable
2. You're not zeroing the memory you allocate with kmalloc, which (judging by your code) leaves a number of struct member variables uninitialized. This is most likely why your code causes the kernel to crash. Either zero it with memset, or use kcalloc.
3. Why are you casting the return value from kmalloc to (ctl_table *)? sizeof(ctl_table)? What is ctl_table -- a typedef? 0 instead of NULL? Just a reminder: You're coding C, not C++.
resolved
Thanks for the response.
Clearing the memory prior to using it was the problem. I actually attempted to clear it, too, but only for length
sizeof(ctl_table)rather thann * sizeof(ctl_table).Oh, and yes,
ctl_tableis atypedef.Again, thanks. I'll have to keep reminding myself that I'm playing with C now :).
Cheers,
ib