C link_elf_obj: symbol mkdir undefined

Hello,
I am a total beginner with freeBSD.

So far, I'm reading a book called: Designing BSD rootkit by Joseph Kong.
As I mentioned, I barely know what I am doing, but I'm doing it and kind of manage to understand a little.

However, I am currently stuck on an error when I load the module in the kernel.
kldload ./mkdirHook.ko
gives me the following error:
Code:
link_elf_obj: symbole mkdir undefined
linker_load_file: Unupported file type
kldload: an error occurend while loading the module. Please check dmesg(8) for more detail.

The closest thing I've found related to my problem come from this post, however, I do not see how it applies to me.

Here is the full code.

Code:
#include <sys/types.h>
#include <machine/endian.h>
#include <sys/param.h>
#include <sys/sysproto.h>
#include <sys/proc.h>
#include <sys/module.h>
#include <sys/sysent.h>
#include <sys/kernel.h>
#include <sys/systm.h>
#include <sys/sysproto.h>
#include <sys/stat.h>
#include <sys/syscall.h>


/* mkdir header */
int mkdir(const char *pathname,mode_t *mode);

/* mkdir hooker */
static int mkdirHooker(struct thread *td, void *syscall_args){
    struct mkdir_args *uap;
    uap = (struct mkdir_args *)syscall_args;
    char path[255];
    size_t done;
    int error;

    error = copyinstr(uap->path, path, 255, &done);
    if(error != 0)
        return(error);

    /*small debug message */
    uprintf("DIR will be with PERMS: %o\n", uap->mode);
   
    return(mkdir(path, syscall_args));
   
}

static int load(struct module *module, int cmd, void *arg){
   int error = 0;
   switch (cmd){
      case MOD_LOAD:
    //replace mkdire with mkdir hook
    sysent[SYS_mkdir].sy_call = (sy_call_t *)mkdirHooker;
    break;
      case MOD_UNLOAD:
    // PUT EVERYTHING BACK TO NORMAL
    sysent[SYS_mkdir].sy_call = (sy_call_t *)mkdir;
    break;
      default:
    error = EOPNOTSUPP;
    break;
   }

   return(error);
}

static moduledata_t mkdir_hook_mod = {"mkdirHooker", load, NULL};

DECLARE_MODULE(mkdirHooker, mkdir_hook_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);

Thank you for your time
 
You can't use C library functions inside the kernel. You can't use any library actually.
 
That book, while good, might be a bit obsolete now. As said in its prologue it was tested on FreeBSD 6.0-STABLE. Few moons have passed since then :) It seems back then syscall functions were read(), mkdir(), now they are sys_read(), sys_mkdir().

Quick patch of your code:

Code:
$ cat fixme.patch
--- a/mkdirHook.c    2019-07-30 23:16:23.792722000 +0200
+++ b/mkdirHook.c    2019-07-30 23:16:28.401860000 +0200
@@ -13,7 +13,7 @@


/* mkdir header */
-int mkdir(const char *pathname,mode_t *mode);
+//int mkdir(const char *pathname,mode_t *mode);

/* mkdir hooker */
static int mkdirHooker(struct thread *td, void *syscall_args){
@@ -30,7 +30,7 @@
     /*small debug message */
     uprintf("DIR will be with PERMS: %o\n", uap->mode);

-    return(mkdir(path, syscall_args));
+    return(sys_mkdir(td, uap));

}

@@ -43,7 +43,7 @@
     break;
       case MOD_UNLOAD:
     // PUT EVERYTHING BACK TO NORMAL
-    sysent[SYS_mkdir].sy_call = (sy_call_t *)mkdir;
+    sysent[SYS_mkdir].sy_call = (sy_call_t *)sys_mkdir;
     break;
       default:
     error = EOPNOTSUPP;
$

Save to the directory where your mkdirHook.c is (assumed you named it that way) and do: patch -p1 < fixme.patch. Compile, load and test.
 
Back
Top