Yup perfect and understood.. Thanks, -Pradeep
On Tue, Sep 14, 2010 at 7:32 PM, Venkatram Tummala <venkatram...@gmail.com>wrote: > On Tue, Sep 14, 2010 at 4:24 PM, Pradeep Shetty > <pradeepjshe...@gmail.com>wrote: > >> Once I have initialized crypt_sys with crypt while loading the module, >> isn't that my user code should call sys_crypt_sys and not any of crypt_sys >> or crypt? Just got confused with your last statement.. >> > > Oh yeah. I am sorry. I meant to say that you have to call the function > pointer crypt_sys from other modules. From user code, you have to "call > sys_crypt_sys". That is, the normal way to call a system call. That is put > on system call number in EAX & so on & so on. > > Venkatram Tummala > >> >> Thanks & Regards, >> -Pradeep >> >> >> On Tue, Sep 14, 2010 at 7:14 PM, Venkatram Tummala < >> venkatram...@gmail.com> wrote: >> >>> On Tue, Sep 14, 2010 at 4:04 PM, Pradeep Shetty < >>> pradeepjshe...@gmail.com> wrote: >>> >>>> Thanks Venkatram... >>>> >>>> I'll probably use the first one as I had similar approach in my mind but >>>> didn't know whether it was possible though its not the best approach. >>>> >>>> So, basically I need to add 2 things in kernel.. A wrapper function with >>>> a null function pointer and a system call which ends up calling my >>>> implementation part of LKM thro that function pointer. right? >>>> >>> >>> You can declare & export your null function pointer globally and the >>> system call processing routing will check that function pointer for a >>> non-null value. If it is non-null, then it means that the loadable module >>> must have initialized the function pointer to the function in the loadable >>> module (crypt), and hence the system call processing function can call the >>> crypt function in the LKM. O'wise -ENOSYS is returned. >>> >>> Keep in mind that you have to call the "system call" by the function >>> pointer (crypt_sys(...)) from the user code to invoke the system call, NOT >>> by calling crypt( ). >>> >>> Regards, >>> Venkatram Tummala >>> >>>> >>>> This was really helpful.. Thanks again.. >>>> >>>> Regards, >>>> -Pradeep >>>> >>>> On Tue, Sep 14, 2010 at 6:49 PM, Venkatram Tummala < >>>> venkatram...@gmail.com> wrote: >>>> >>>>> On Tue, Sep 14, 2010 at 2:40 PM, Pradeep Shetty < >>>>> pradeepjshe...@gmail.com> wrote: >>>>> >>>>>> Hello, >>>>>> >>>>>> I learnt that the sys_call_table is no longer is exportable in 2.6+. >>>>>> I'm using 2.6.35.4 and trying to implement it in a LKM. I read the >>>>>> virtual >>>>>> addr of sys_call_table from the system map and made its physical page >>>>>> writable and added my syscall in place of Andrew Filesystem syscall and >>>>>> then >>>>>> made the page readonly again. But when I call my system call it is still >>>>>> calling AFS syscall and hence getting back ENOSYS error. I printed the >>>>>> sys_call_table at AFS syscall index after making the change and it seems >>>>>> to >>>>>> have the addr of my syscall. I'm not understanding where did it go wrong. >>>>>> Any help on figuring this out would be appreciated. Below is my code... >>>>>> >>>>>> I haven't yet implemented the sytem call. Its about encrypting and >>>>>> decrypting user specified files. I would do that later once have this >>>>>> infrastructure set. Now I'm just printing that "I was here!". >>>>>> >>>>>> And is there a better way of implementing this? Like creating a system >>>>>> call stub in the kernel that calls my function which would be part of an >>>>>> LKM? I would really want a generic solution to this. >>>>>> >>>>> >>>>> You cannot add a new system call dynamically just in the kernel >>>>> loadable modules. >>>>> >>>>> There are 2 ways to overcome this. >>>>> >>>>> (1) Creating a Wrapper which is statically compiled into the kernel >>>>> image. >>>>> >>>>> Include the following code in the kernel source : >>>>> >>>>> // Creates a NULL function pointer which will be used to point to your >>>>> processing routine in the loadable kernel module. >>>>> long (*crypt_sys) (args....) = NULL; >>>>> >>>>> //Export This Function Pointer so that you can use it in LKM. >>>>> EXPORT_SYMBOL(crypt_sys); >>>>> >>>>> // This is the hook >>>>> asmlinkage long sys_crypt_sys(args...) >>>>> { >>>>> return crypt_sys ? crypt_sys(args) : -ENOSYS; >>>>> } >>>>> >>>>> Now, in your loadable module init function sys_crypt_init(), assign >>>>> crypt to the function pointer crypt_sys exported from the kernel. >>>>> >>>>> crypt_sys = crypt >>>>> >>>>> And define crypt(.....) function as a normal function. >>>>> >>>>> Now, when you call crypt_sys(args) from anywhere, your crypt() function >>>>> in the loadable module will be executed. >>>>> >>>>> But, the problem is technically, you still added code builtin to the >>>>> kernel code. This is just a hackish way to implement a system call from >>>>> the >>>>> kernel module. This will speed up for development time as you dont have to >>>>> reboot every time you make a change to the system call implementation ( >>>>> unless you want to change the system call signature ). But this still is >>>>> considered adding a system call in the kernel which is statically compiled >>>>> into the kernel image. For a better method, look at solution (2) >>>>> >>>>> (2) Create & Open a miscdevice in your kernel module. That is, a dummy >>>>> device ( /dev/crypt for example). Now, a system call can be implemented as >>>>> operations on this device in the form of ioctls. Skeleton code is provided >>>>> here. >>>>> >>>>> const struct file_operations crypt_fops = { >>>>> .owner = THIS_MODULE, >>>>> .ioctl = crypt_ioctl, >>>>> }; >>>>> >>>>> struct miscdevice crypt_dev = { >>>>> MISC_DYNAMIC_MINOR, >>>>> "crypt_dev", >>>>> &crypt_fops >>>>> }; >>>>> >>>>> static int crypt_ioctl(struct inode *inode, struct file *file, unsigned >>>>> int cmd, unsigned long arg) >>>>> { >>>>> // cmd is magic cookie of the ioctl call that was passed in >>>>> from user-space. >>>>> >>>>> // You can pack all your "system call" arguments into a >>>>> structure and then pass the object from the user-space if you have >>>>> multiple >>>>> arguments. >>>>> >>>>> // Use copy_from_user(...) to get the object and hence the >>>>> arguments and do the processing here. >>>>> >>>>> } >>>>> >>>>> You can use different magic cookies to implement distinct "system >>>>> calls". crypt_ioctl is the dispatcher function here. It will look at the >>>>> magic cookie, copy_from_user(...) the arguments accordingly, then do the >>>>> processing. >>>>> >>>>> The beauty of this approach is that everything can done in the kernel >>>>> module. >>>>> >>>>> Hope this helps. >>>>> >>>>> Regards, >>>>> Venkatram Tummala >>>>> >>>>> >>>>> >>>>>> >>>>>> [root]# grep sys_call_table System.map >>>>>> c12ba180 R sys_call_table >>>>>> >>>>>> ----------------------------------------------------------------------------------------- >>>>>> #include <linux/kernel.h> >>>>>> #include <linux/module.h> >>>>>> #include <linux/moduleparam.h> >>>>>> #include <linux/unistd.h> >>>>>> #include <linux/mman.h> >>>>>> #include <linux/sched.h> >>>>>> #include <asm/uaccess.h> >>>>>> #include <asm/pgtable.h> >>>>>> #include <asm/processor.h> >>>>>> #include <asm/atomic.h> >>>>>> #include <asm/mman.h> >>>>>> #include <linux/init.h> >>>>>> #include <linux/mm.h> >>>>>> #include <linux/syscalls.h> >>>>>> #include <asm/cacheflush.h> >>>>>> #include <asm/page.h> >>>>>> #include <linux/linkage.h> >>>>>> >>>>>> MODULE_LICENSE("GPL"); >>>>>> MODULE_AUTHOR("shetty"); >>>>>> MODULE_DESCRIPTION("sys_crypt implementation"); >>>>>> >>>>>> unsigned long *sys_call_table = (unsigned long *)0xc12ba180; >>>>>> static asmlinkage int (*original_call) (); >>>>>> >>>>>> >>>>>> #define __NR_afs_syscall 137 >>>>>> >>>>>> SYSCALL_DEFINE5(crypt,const char __user *, infile, const char __user >>>>>> *, outfile, >>>>>> const char __user *, keybuf, int, keylen, >>>>>> char, flags) >>>>>> { >>>>>> >>>>>> printk(KERN_ALERT "I was here!\n"); >>>>>> return keylen; >>>>>> >>>>>> } >>>>>> EXPORT_SYMBOL(sys_crypt); >>>>>> >>>>>> static int __init sys_crypt_init(void) >>>>>> { >>>>>> >>>>>> unsigned long addr; >>>>>> struct page *page; >>>>>> printk(KERN_ALERT "Inserting hw1-module...\n"); >>>>>> >>>>>> page_sys_call_table = virt_to_page(sys_call_table); >>>>>> addr = (unsigned long)page_address(page); >>>>>> set_memory_rw(addr, 1); >>>>>> original_call = sys_call_table[__NR_afs_syscall]; >>>>>> sys_call_table[__NR_afs_syscall] = sys_crypt; >>>>>> >>>>>> printk(KERN_ALERT "sys_crypt = %X\n", sys_crypt); >>>>>> printk(KERN_ALERT "sys_call_table:sys_crypt = >>>>>> %X",sys_call_table[__NR_new_syscall]); >>>>>> printk(KERN_ALERT "sys_call_table = %X\n", sys_call_table); >>>>>> printk(KERN_ALERT "&sys_call_table:sys_crypt = >>>>>> %X",&sys_call_table[__NR_new_syscall]); >>>>>> >>>>>> set_memory_ro(addr, 1); >>>>>> >>>>>> >>>>>> printk(KERN_ALERT "sys_call_table is exported\n"); >>>>>> return 0; >>>>>> >>>>>> >>>>>> } >>>>>> >>>>>> static void __exit sys_crypt_exit(void) >>>>>> { >>>>>> unsigned long addr; >>>>>> struct page *page; >>>>>> page_sys_call_table = virt_to_page(sys_call_table); >>>>>> addr = (unsigned long)page_address(page); >>>>>> >>>>>> set_memory_rw(addr, 1); >>>>>> sys_call_table[__NR_afs_syscall] = original_call; >>>>>> set_memory_ro(addr, 1); >>>>>> >>>>>> printk(KERN_ALERT "Removing hw1-module\n"); >>>>>> } >>>>>> >>>>>> module_init(sys_crypt_init); >>>>>> module_exit(sys_crypt_exit); >>>>>> >>>>>> EXPORT_SYMBOL(sys_call_table); >>>>>> >>>>>> ----------------------------------------------------------------------------------- >>>>>> >>>>>> /var/log/messages: >>>>>> >>>>>> Sep 13 19:11:11 d136 kernel: Inserting hw1-module... >>>>>> Sep 13 19:11:11 d136 kernel: sys_crypt = >>>>>> D084B000 <<<<< >>>>>> Sep 13 19:11:11 d136 kernel: sys_call_table:sys_crypt = D084B000 >>>>>> <<<<< >>>>>> Sep 13 19:11:11 d136 kernel: original_call = X >>>>>> Sep 13 19:11:11 d136 kernel: sys_call_table = C12BA180 >>>>>> Sep 13 19:11:11 d136 kernel: &sys_call_table:sys_crypt = C12BA38C >>>>>> Sep 13 19:11:11 d136 kernel: sys_call_table is exported >>>>>> >>>>>> ***************From strace***************************** >>>>>> >>>>>> afs_syscall(0x8049708, 0xbf8a5828, 0x8048462, 0x9d0ff4, 0x9cf208) = -1 >>>>>> ENOSYS (Function not implemented) >>>>>> fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0 >>>>>> mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, >>>>>> 0) = 0xb7813000 >>>>>> write(1, "-1Error: 38, Function not implem"..., 38) = 38 >>>>>> exit_group(36) >>>>>> *********************************************************** >>>>>> >>>>>> >>>>>> Thanks.. >>>>>> -Pradeep >>>>>> >>>>> >>>>> >>>> >>> >> >