rustam Shirinov
rustam Shirinov

Reputation: 139

Restore or remove the Linux Kernel Module from sysfs

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

Answers (4)

Skelly
Skelly

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,
                  &notes_attrs_prev->attrs[i]);
    }
    sysfs_create_group(&THIS_MODULE->mkobj.kobj, &sect_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

NondairyDig
NondairyDig

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,
                  &notes_attrs_prev->attrs[i]);
    }
    sysfs_create_group(&THIS_MODULE->mkobj.kobj, &sect_attrs_prev->grp);
    THIS_MODULE->notes_attrs = notes_attrs_prev;
    THIS_MODULE->sect_attrs = sect_attrs_prev;
}

Upvotes: 0

abalabanov
abalabanov

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

TomerSamara
TomerSamara

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, &sect_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

Related Questions