Reputation: 139
I recently coded a LKM which has the ability to hide itself. All works just fine when I hide the module but when I restore it and look at it in the lsmod the value of the Used By
column suddenly is -2
Module Size Used by
my_module 13324 -2
vboxsf 43798 1
dm_crypt 23177 0
nfsd 284396 2
auth_rpcgss 59309 1 nfsd
nfs_acl 12837 1 nfsd
nfs 240815 0
and when I remove it i get the error saying rmmod: ERROR: Module my_module is builtin.
I know that it is a refcount for the kobject
associated with the module and the module can only be removed when it is 0
. I am almost certain that it happens because when I hide the module I delete all of its files in the /sys/modules
.(holders
, parameters
, sections
, srcversion
etc.). Can someone help me with the remove operation or restore the files back?(I don't get any errors in the dmesg
)
Here is the code: `
void module_hide(void) {
if(module_hidden) //is hidden
return;
module_prev = THIS_MODULE->list.prev;
kobject_prev = &THIS_MODULE->mkobj.kobj;
kobject_parent_prev = THIS_MODULE->mkobj.kobj.parent;
sect_attrs_bkp = THIS_MODULE->sect_attrs;
notes_attrs_bkp = THIS_MODULE->notes_attrs;
list_del(&THIS_MODULE->list); //remove from procfs
//kobject_del(THIS_MODULE->holders_dir);
kobject_del(&THIS_MODULE->mkobj.kobj); //remove from sysfs
THIS_MODULE->sect_attrs = NULL;
THIS_MODULE->notes_attrs = NULL;
module_hidden = (unsigned int)0x1;
}
void module_show(void) {
int result, result2;
if(!module_hidden) //is not hidden
return;
list_add(&THIS_MODULE->list, module_prev); //add to procfs
result = kobject_add(&THIS_MODULE->mkobj.kobj, kobject_parent_prev, "my_module"); //add the module to sysfs
if(result<0) {
printk(KERN_ALERT "Error to restore the old kobject\n");
}
result2 = kobject_add(THIS_MODULE->holders_dir, &THIS_MODULE->mkobj.kobj, "holders"); //add the holders dir to the module folder
if(!THIS_MODULE->holders_dir) {
printk(KERN_ALERT "Error to restore the old holders_dir\n");
}
THIS_MODULE->sect_attrs = sect_attrs_bkp;
THIS_MODULE->notes_attrs = notes_attrs_bkp;
//kobject_get(&THIS_MODULE->mkobj.kobj);
//tried using THIS_MODULE->refcnt = 0; and kobject_get(&THIS_MODULE->mkobj.kob) with no luck
module_hidden = (unsigned int)0x0;
}
Thanks
Upvotes: 2
Views: 1858
Reputation: 1
static void show_mod(void) {
static int i;
// add to the modules linked list the current module after the one it already had been attached
list_add(&THIS_MODULE->list, prev_module);
// add the kobjects to sysfs again
kobject_add(kobject_prev, kobject_parent_prev, mod_fmt);
THIS_MODULE->holders_dir = kobject_create_and_add("holders", &THIS_MODULE->mkobj.kobj);
for (i=0;(THIS_MODULE->modinfo_attrs[i].attr.name) != NULL;i++){
pr_info("Creating %s\n", THIS_MODULE->modinfo_attrs[i].attr.name);
if (sysfs_create_file(&THIS_MODULE->mkobj.kobj,&THIS_MODULE->modinfo_attrs[i].attr)!=0)
pr_err("couldn't create %s\n", THIS_MODULE->modinfo_attrs[i].attr.name);
}
notes_attrs_prev->dir = kobject_create_and_add("notes", &THIS_MODULE->mkobj.kobj);
for (i=0; i < notes_attrs_prev->notes; i++){
sysfs_create_bin_file(notes_attrs_prev->dir,
¬es_attrs_prev->attrs[i]);
}
sysfs_create_group(&THIS_MODULE->mkobj.kobj, §_attrs_prev->grp);
THIS_MODULE->notes_attrs = notes_attrs_prev;
THIS_MODULE->sect_attrs = sect_attrs_prev;
}
This code does in fact generate all the files and subdirectories. Thing is it does not populate those subdirectories. The holders directory which is required by rmmod is empty theres the issue.
Upvotes: 0
Reputation: 1
I could restore all of the files and sub-directories, but still rmmod is stuck when trying to unload the module, working on a fix but might try another way like @TomerSamara Said.
Here's how I recovered it:
static void show_mod(void) {
static int i;
// add to the modules linked list the current module after the one it already had been attached
list_add(&THIS_MODULE->list, prev_module);
// add the kobjects to sysfs again
kobject_add(kobject_prev, kobject_parent_prev, mod_fmt);
THIS_MODULE->holders_dir = kobject_create_and_add("holders", &THIS_MODULE->mkobj.kobj);
for (i=0;(THIS_MODULE->modinfo_attrs[i].attr.name) != NULL;i++){
pr_info("Creating %s\n", THIS_MODULE->modinfo_attrs[i].attr.name);
if (sysfs_create_file(&THIS_MODULE->mkobj.kobj,&THIS_MODULE->modinfo_attrs[i].attr)!=0)
pr_err("couldn't create %s\n", THIS_MODULE->modinfo_attrs[i].attr.name);
}
notes_attrs_prev->dir = kobject_create_and_add("notes", &THIS_MODULE->mkobj.kobj);
for (i=0; i < notes_attrs_prev->notes; i++){
sysfs_create_bin_file(notes_attrs_prev->dir,
¬es_attrs_prev->attrs[i]);
}
sysfs_create_group(&THIS_MODULE->mkobj.kobj, §_attrs_prev->grp);
THIS_MODULE->notes_attrs = notes_attrs_prev;
THIS_MODULE->sect_attrs = sect_attrs_prev;
}
Upvotes: 0
Reputation: 1
I solved it
static void populate_sysfs(void)
{
int i;
THIS_MODULE->holders_dir=kobject_create_and_add("holders",&THIS_MODULE->mkobj.kobj);
for (i=0;(THIS_MODULE->modinfo_attrs[i].attr.name) != NULL;i++){
if (sysfs_create_file(&THIS_MODULE->mkobj.kobj,&THIS_MODULE->modinfo_attrs[i].attr)!=0)
break;
}
}
Upvotes: 0
Reputation: 76
Using kobject_add will only add the directory as you already know, while using kobject_dell will remove the direcotry and all subdirectories. Hence as you mention you need to add all of the subdires needed.
To understand what is the way of adding the subdirs, you read the source code of sys_init_module carefully at module.c or read kobject_del->sys_remove_dir
which remove all attributes(files) and subdirs when clear recursively kobj->kernfs_nodes
.
Thus, you need create the struct recursivly with all his attrs using the functions
sysfs_add_file_mode_ns
sysfs_create_dir_ns
or:
__kernfs_create_file
kernfs_create_empty_dir
for example to add the sections file use the follwoing line:
sysfs_create_group(&THIS_MODULE->mkobj.kobj, §_attrs_bkp->grp))
You need you change more values in order to fix the problem but to restore the directories this will be enough.
But other solution and perherp easier one would be just to make you module directory unvisible by hijacking getdents_t and getdents64_t as done at Diamorphine.
Upvotes: 1