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

Reply via email to