Issue
I want to use parameter inside a kernel (3.x) module:
static unsigned short param = 0xff;
module_param(param, ushort, S_IRUGO | S_IWUGO);
MODULE_PARM_DESC(param, "a parameter");
Is there any possibility to detect changes on this parameter? Is there a signal which can use to call a service routine?
Here a full code example:
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alex");
MODULE_DESCRIPTION("test module.");
MODULE_VERSION("0.1");
static int param = 1;
module_param(param, int, S_IRUGO|S_IWUSR);
static int __init mod_init(void){
printk(KERN_INFO "param %d\n", param);
return 0;
}
static void __exit mod_exit(void){
printk(KERN_INFO "Goodbye!\n");
}
module_init(mod_init);
module_exit(mod_exit);
Now you can find the parameter under /sys/module/<modulename>/parameters
and you can change the parameter like this (with root privileges):
echo 2 > /sys/module/ebb/parameters/param
I want to be notified about that change.
next step regarding to @Tsyvarev
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alex");
MODULE_DESCRIPTION("test module.");
MODULE_VERSION("0.1");
// int (*set)(const char *val, const struct kernel_param *kp);
// int (*get)(char *buffer, const struct kernel_param *kp);
int my_param_set_ushort(const char *val, const struct kernel_param *kp)
{
unsigned short* pvalue = kp->arg; // Pointer to actual parameter variable.
int res = param_set_ushort(val, kp); // Use helper for write variable
printk(KERN_INFO "setter talks\n");
if( res==0 )
{
// Here you may execute additional actions when you write parameter.
printk(KERN_INFO "set param %d\n", *pvalue);
}
return res;
}
const struct kernel_param_ops my_param_ops_ushort =
{
.set = &my_param_set_ushort, // Use our setter ...
.get = ¶m_get_ushort, // .. and standard getter
};
unsigned short param = 0xff;
module_param_cb(param, /*filename*/
&my_param_ops_ushort, /*operations*/
¶m, /* pointer to variable, contained parameter's value */
S_IRUGO | S_IWUSR /*permissions on file*/
);
static int __init mod_init(void){
printk(KERN_INFO "param %d\n", param);
return 0;
}
static void __exit mod_exit(void){
printk(KERN_INFO "Goodbye! (%d)\n",param);
}
module_init(mod_init);
module_exit(mod_exit);
as root I give this commands:
# insmod par.ko
# echo 146 > /sys/module/par/parameters/param
# rmmod par
and the kernel log /var/log/kernel.log says:
Jan 23 14:27:37 alex-XMG kernel: [ 8332.492912] param 255
Jan 23 14:27:39 alex-XMG kernel: [ 8334.520044] setter talks
Jan 23 14:27:39 alex-XMG kernel: [ 8334.520052] set param 146
Jan 23 14:27:40 alex-XMG kernel: [ 8335.804338] Goodbye! (146)
Works like a charme!
Solution
Generic way for create kernel module parameter is using macro module_param_cb:
/**
* module_param_cb - general callback for a module/cmdline parameter
* @name: a valid C identifier which is the parameter name.
* @ops: the set & get operations for this parameter.
* @perm: visibility in sysfs.
*
* The ops can have NULL set or get functions.
*/
#define module_param_cb(name, ops, arg, perm)
Parameter ops
is a pointer to structure struct kernel_param_ops
, which contains operations for given parameter. Functions called when parameter is written and read have followed definition in this structure:
int (*set)(const char *val, const struct kernel_param *kp);
int (*get)(char *buffer, const struct kernel_param *kp);
Here char*
parameter is a NULL-terminated string, which is written to/read from the sysfs file, denoted given parameter. And kp
is a pointer to parameter descriptor, where the most interested field is .arg
: it is a 3rd argument to macro module_param_cb
call. Using this field, setter and getter can be implemented per-type of the module parameter, that is having 5 int
parameters for module doesn't require to write setters and getters for each of them.
Moreover, getters and setters for standard parameter types are already implemented, and they are actually used when you call module_param
macro. So, if you want to add some functionality for the parameter's setter, you may reuse existed helpers:
int my_param_set_ushort(const char *val, const struct kernel_param *kp)
{
unsigned short* pvalue = kp->arg; // Pointer to actual parameter variable.
int res = param_set_ushort(val, kp); // Use helper for write variable
if(!res)
{
// Here you may execute additional actions when you write parameter.
printk(KERN_INFO "set param %d\n", *pvalue);
}
return res;
}
const struct kernel_param_ops my_param_ops_ushort =
{
.set = &my_param_set_ushort, // Use our setter ...
.get = ¶m_get_ushort, // .. and standard getter
};
// Usage
unsigned short param = 0xff;
module_param_cb(param, /*filename*/
&my_param_ops_ushort, /*operations*/
¶m, /* pointer to variable, contained parameter's value */
S_IRUGO | S_IWUSR /*permissions on file*/
);
Having module parameter's writable by non-priveledged user normally is not good for security reasons. And kernel macros, which create module parameters, check that. That is why you have cryptic error in your module parameter's definition. Note, that in the example above S_IWUSR
is used instead of S_IWUGO
.
Answered By - Tsyvarev Answer Checked By - Mary Flores (WPSolving Volunteer)