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..
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 >>>> >>> >>> >> >