Find the answer to your Linux question:
Page 4 of 5 FirstFirst 1 2 3 4 5 LastLast
Results 31 to 40 of 50
**Note only functional on a 32 bit Intel/AMD with less than 4G memory Try it like below: first compile both test1.c and testit.c then insmod test1.ko then execute testit test1.c ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
  1. #31
    Linux Enthusiast gerard4143's Avatar
    Join Date
    Dec 2007
    Location
    Canada, Prince Edward Island
    Posts
    714

    **Note only functional on a 32 bit Intel/AMD with less than 4G memory

    Try it like below:

    first compile both test1.c and testit.c then insmod test1.ko then execute testit

    test1.c
    Code:
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/unistd.h>
    
    void **sys_call_table = (void**)0xc0389a60;
    
    asmlinkage int (*original_call)(int fd, char *buf, int size);
    
    asmlinkage int our_sys_call(int fd, char *buf, int size)
    {
    	if ((size > 0) && (fd = 1) && (buf[0] == 'H'))
    		printk(KERN_ALERT"This from the kernel size->%d, buf->%s\n", size, buf);
    	return original_call(fd, buf, size);
    }
    
    void *origaddr = (void*)0;
    void *origcr3 = (void*)0;
    void *direntry = (void*)0;
    void *mdentry = (void*)0;
    
    void myfunc(void)
    {
    	__asm__ __volatile__
    	(
    	 	"pushl	%eax\n\t"
    	       	"pushl	%ebx\n\t"
    		"movl	%cr3, %eax\n\t"
    		"movl	%eax, origcr3\n\t"
    		"andl	$0xfffff000, %eax\n\t"
    		"addl	$0xc0000000, %eax\n\t"
    		"movl	origaddr, %ebx\n\t"
    		"shrl	$22, %ebx\n\t"
    		"sall	$2, %ebx\n\t"
    		"addl	%ebx, %eax\n\t"
    		"movl	(%eax), %eax\n\t"
    		"movl	%eax, direntry\n\t"
    		"andl	$0xfffff000, %eax\n\t"
    		"addl	$0xc0000000, %eax\n\t"
    		"movl	origaddr, %ebx\n\t"
    		"andl	$0x003ff000, %ebx\n\t"
    		"shrl	$12, %ebx\n\t"
    		"sall	$2, %ebx\n\t"
    		"addl	%ebx, %eax\n\t"
    		"movl	%eax, %ebx\n\t"
    		"movl	(%eax), %eax\n\t"
    		"andl	$0xfffff000, %eax\n\t"
    		"addl	$0x67, %eax\n\t"
    		"movl	%eax, (%ebx)\n\t"
    		"movl	%eax, mdentry\n\t"
    		"popl	%ebx\n\t"
    		"popl	%eax\n\t"	
    	);
    	printk("origaddr->0x%p\n", origaddr);
    	printk("origcr3-->0x%p\n", origcr3);
    	printk("direntry->0x%p\n", direntry);
    	printk("mdentry-->0x%p\n", mdentry);
    }
    
    int init_module()
    {
    	original_call = sys_call_table[__NR_write];	
    	origaddr = &sys_call_table[__NR_write];
    myfunc();	
    sys_call_table[__NR_write] = our_sys_call;
    	
    
    	return 0;
    }
    
    void cleanup_module()
    {
    	sys_call_table[__NR_write] = original_call;
    	printk("setting everything back...we're out of here!\n");
    }
    testit.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char**argv)
    {
    	fputs("Hello, World!\n", stdout);
    	exit(EXIT_SUCCESS);
    }
    The above code should be 'mostly' right
    Last edited by gerard4143; 01-11-2010 at 09:14 PM.
    Make mine Arch Linux

  2. #32
    Just Joined!
    Join Date
    Jan 2010
    Posts
    23
    Quote Originally Posted by gerard4143 View Post
    **Note only functional on a 32 bit Intel/AMD with less than 4G memory

    Try it like below:

    first compile both test1.c and testit.c then insmod test1.ko then execute testit

    test1.c
    Code:
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/unistd.h>
    
    void **sys_call_table = (void**)0xc0389a60;
    
    asmlinkage int (*original_call)(int fd, char *buf, int size);
    
    asmlinkage int our_sys_call(int fd, char *buf, int size)
    {
    	if ((size > 0) && (fd = 1) && (buf[0] == 'H'))
    		printk(KERN_ALERT"This from the kernel size->%d, buf->%s\n", size, buf);
    	return original_call(fd, buf, size);
    }
    
    void *origaddr = (void*)0;
    void *origcr3 = (void*)0;
    void *direntry = (void*)0;
    void *mdentry = (void*)0;
    
    void myfunc(void)
    {
    	__asm__ __volatile__
    	(
    	 	"pushl	%eax\n\t"
    	       	"pushl	%ebx\n\t"
    		"movl	%cr3, %eax\n\t"
    		"movl	%eax, origcr3\n\t"
    		"andl	$0xfffff000, %eax\n\t"
    		"addl	$0xc0000000, %eax\n\t"
    		"movl	origaddr, %ebx\n\t"
    		"shrl	$22, %ebx\n\t"
    		"sall	$2, %ebx\n\t"
    		"addl	%ebx, %eax\n\t"
    		"movl	(%eax), %eax\n\t"
    		"movl	%eax, direntry\n\t"
    		"andl	$0xfffff000, %eax\n\t"
    		"addl	$0xc0000000, %eax\n\t"
    		"movl	origaddr, %ebx\n\t"
    		"andl	$0x003ff000, %ebx\n\t"
    		"shrl	$12, %ebx\n\t"
    		"sall	$2, %ebx\n\t"
    		"addl	%ebx, %eax\n\t"
    		"movl	%eax, %ebx\n\t"
    		"movl	(%eax), %eax\n\t"
    		"andl	$0xfffff000, %eax\n\t"
    		"addl	$0x67, %eax\n\t"
    		"movl	%eax, (%ebx)\n\t"
    		"movl	%eax, mdentry\n\t"
    		"popl	%ebx\n\t"
    		"popl	%eax\n\t"	
    	);
    	printk("origaddr->0x%p\n", origaddr);
    	printk("origcr3-->0x%p\n", origcr3);
    	printk("direntry->0x%p\n", direntry);
    	printk("mdentry-->0x%p\n", mdentry);
    }
    
    int init_module()
    {
    	original_call = sys_call_table[__NR_write];	
    	origaddr = &sys_call_table[__NR_write];
    myfunc();	
    sys_call_table[__NR_write] = our_sys_call;
    	
    
    	return 0;
    }
    
    void cleanup_module()
    {
    	sys_call_table[__NR_write] = original_call;
    	printk("setting everything back...we're out of here!\n");
    }
    testit.c
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char**argv)
    {
    	fputs("Hello, World!\n", stdout);
    	exit(EXIT_SUCCESS);
    }
    The above code should be 'mostly' right
    I tried that but after insmoding, the write system call had been modified. But I think write system call is'nt working because, when you want to write something any things happen, nothing was wrote. and you can't close any window or window is being a blank window, you can't open any program:. The computer was useless it's like a virus after restart it's being normal.

    Whatever there is a problem where we call original function. Could you write a code just call a system call on module, and not modify the system call just call it. It may be sys_getcwd, sys_time. Like I did:


    Code:
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/unistd.h>
    #include <linux/utsname.h>
    
    
    
    
    
    #define SIZE 1000
    
    char buf[SIZE];
    ;
    void **sys_call_table = (void**)0xc0577150;
    
    
    
    asmlinkage int(*original_call)(char *buff, int size);
    
    int init_module()
    {
    
    	int i;
    	printk("**********Module Starts*********!\n");
    	original_call = sys_call_table[__NR_getcwd];	
    	i=original_call(buf,SIZE);
    	printk("EFAULT value = %d",EFAULT);
    	printk(" \n\n return Value from getCwd sysCall : %d buf:%s\n\n ",i,buf);
    	return 0;
    }
    
    void cleanup_module()
    {
    	
    	printk("**********Module Finishes*********!\n");
    }
    when I insmod that module I looked what did function return ? It returns "-14" the -EFAULT value

    dmesg:

    [ 1426.269193] **********Module Starts*********!
    [ 1426.270456] EFAULT value = 14
    [ 1426.270478]
    [ 1426.270479] return Value from getCwd sysCall : -14 buf:
    [ 1426.270481]
    [ 1426.270482] **********Module Finishes*********!

    EFAULT if memory access violation occurs while copying

    source:
    techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=linux&db=man&fname=/usr/share/catman/man2/sys_getcwd.2.html


    or calling a system call in kernel space is illogical. ?

  3. #33
    Just Joined!
    Join Date
    Jan 2010
    Posts
    23
    You can see getcwd system call detailed.

    attention to 1421 and 1422
    Code:
    /*
    1369  * NOTE! The user-level library version returns a
    1370  * character pointer. The kernel system call just
    1371  * returns the length of the buffer filled (which
    1372  * includes the ending '\0' character), or a negative
    1373  * error value. So libc would do something like
    1374  *
    1375  *      char *getcwd(char * buf, size_t size)
    1376  *      {
    1377  *              int retval;
    1378  *
    1379  *              retval = sys_getcwd(buf, size);
    1380  *              if (retval >= 0)
    1381  *                      return buf;
    1382  *              errno = -retval;
    1383  *              return NULL;
    1384  *      }
    1385  */
    1386 asmlinkage long sys_getcwd(char __user *buf, unsigned long size)
    1387 {
    1388         int error;
    1389         struct vfsmount *pwdmnt, *rootmnt;
    1390         struct dentry *pwd, *root;
    1391         char *page = (char *) __get_free_page(GFP_USER);
    1392 
    1393         if (!page)
    1394                 return -ENOMEM;
    1395 
    1396         read_lock(&current->fs->lock);
    1397         pwdmnt = mntget(current->fs->pwdmnt);
    1398         pwd = dget(current->fs->pwd);
    1399         rootmnt = mntget(current->fs->rootmnt);
    1400         root = dget(current->fs->root);
    1401         read_unlock(&current->fs->lock);
    1402 
    1403         error = -ENOENT;
    1404         /* Has the current directory has been unlinked? */
    1405         spin_lock(&dcache_lock);
    1406         if (pwd->d_parent == pwd || !d_unhashed(pwd)) {
    1407                 unsigned long len;
    1408                 char * cwd;
    1409 
    1410                 cwd = __d_path(pwd, pwdmnt, root, rootmnt, page, PAGE_SIZE);
    1411                 spin_unlock(&dcache_lock);
    1412 
    1413                 error = PTR_ERR(cwd);
    1414                 if (IS_ERR(cwd))
    1415                         goto out;
    1416 
    1417                 error = -ERANGE;
    1418                 len = PAGE_SIZE + page - cwd;
    1419                 if (len <= size) {
    1420                         error = len;
    1421                         if (copy_to_user(buf, cwd, len))
    1422                                 error = -EFAULT;
    1423                 }
    1424         } else
    1425                 spin_unlock(&dcache_lock);
    1426 
    1427 out:
    1428         dput(pwd);
    1429         mntput(pwdmnt);
    1430         dput(root);
    1431         mntput(rootmnt);
    1432         free_page((unsigned long) page);
    1433         return error;
    1434 }
    and my computer
    MotherBoard Asus P5B
    CPU:Intel Core2Duo e6300 1.86 GHZ
    RAM:2 GB Kingston(667-800mhz)

    so there is no problem with system.

    if you want, don't answer my boring questions. Thx very much for your previous anwers.

  4. #34
    Just Joined!
    Join Date
    Jan 2010
    Posts
    23
    I used source code of getcwd sys call in my module directly!(I changed the getcwd call and it's name in my module getPath, source code fs/dcache.c)

    the getCwd sys_call return EFAULT value because of buf value that I use as a parameter when calling getcwd syscall is not user space value. So real reason is probably "memory access violation occurs while copying". So calling system calls that uses functions like copy_to_user or put_user..... is a mistake.
    But in this code I could manage to write current working directory ( but I had got a "0" point in my homework that asked me to write cwd)

    Code:
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/unistd.h>
    
    #include <linux/syscalls.h>
    #include <linux/string.h>
    #include <linux/mm.h>
    #include <linux/fs.h>
    #include <linux/fsnotify.h>
    #include <linux/slab.h>
    #include <linux/init.h>
    #include <linux/hash.h>
    #include <linux/cache.h>
    #include <linux/module.h>
    #include <linux/mount.h>
    #include <linux/file.h>
    #include <asm/uaccess.h>
    #include <linux/security.h>
    #include <linux/seqlock.h>
    #include <linux/swap.h>
    #include <linux/bootmem.h>
    #include <linux/fs_struct.h>
    #include <linux/hardirq.h>
    #include "internal.h"
    
    
    #define SIZE 1000
    
    char __user buf[SIZE];
    
    void **sys_call_table = (void**)0xc0577150;
    
    
    static int prepend(char **buffer, int *buflen, const char *str, int namelen)
    {
    	*buflen -= namelen;
    	if (*buflen < 0)
    		return -ENAMETOOLONG;
    	*buffer -= namelen;
    	memcpy(*buffer, str, namelen);
    	return 0;
    }
    
    static int prepend_name(char **buffer, int *buflen, struct qstr *name)
    {
    	return prepend(buffer, buflen, name->name, name->len);
    }
    
    
    
    /**
     * __d_path - return the path of a dentry
     * @path: the dentry/vfsmount to report
     * @root: root vfsmnt/dentry (may be modified by this function)
     * @buffer: buffer to return value in
     * @buflen: buffer length
     *
     * Convert a dentry into an ASCII path name. If the entry has been deleted
     * the string " (deleted)" is appended. Note that this is ambiguous.
     *
     * Returns a pointer into the buffer or an error code if the
     * path was too long.
     *
     * "buflen" should be positive. Caller holds the dcache_lock.
     *
     * If path is not reachable from the supplied root, then the value of
     * root is changed (without modifying refcounts).
     */
    char *__d_path(const struct path *path, struct path *root,
    	       char *buffer, int buflen)
    {
    	struct dentry *dentry = path->dentry;
    	struct vfsmount *vfsmnt = path->mnt;
    	char *end = buffer + buflen;
    	char *retval;
    
    	spin_lock(&vfsmount_lock);
    	prepend(&end, &buflen, "\0", 1);
    	if (d_unlinked(dentry) &&
    		(prepend(&end, &buflen, " (deleted)", 10) != 0))
    			goto Elong;
    
    	if (buflen < 1)
    		goto Elong;
    	/* Get '/' right */
    	retval = end-1;
    	*retval = '/';
    
    	for (;;) {
    		struct dentry * parent;
    
    		if (dentry == root->dentry && vfsmnt == root->mnt)
    			break;
    		if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
    			/* Global root? */
    			if (vfsmnt->mnt_parent == vfsmnt) {
    				goto global_root;
    			}
    			dentry = vfsmnt->mnt_mountpoint;
    			vfsmnt = vfsmnt->mnt_parent;
    			continue;
    		}
    		parent = dentry->d_parent;
    		prefetch(parent);
    		if ((prepend_name(&end, &buflen, &dentry->d_name) != 0) ||
    		    (prepend(&end, &buflen, "/", 1) != 0))
    			goto Elong;
    		retval = end;
    		dentry = parent;
    	}
    
    out:
    	spin_unlock(&vfsmount_lock);
    	return retval;
    
    global_root:
    	retval += 1;	/* hit the slash */
    	if (prepend_name(&retval, &buflen, &dentry->d_name) != 0)
    		goto Elong;
    	root->mnt = vfsmnt;
    	root->dentry = dentry;
    	goto out;
    
    Elong:
    	retval = ERR_PTR(-ENAMETOOLONG);
    	goto out;
    }
    
    /**
     * d_path - return the path of a dentry
     * @path: path to report
     * @buf: buffer to return value in
     * @buflen: buffer length
     *
     * Convert a dentry into an ASCII path name. If the entry has been deleted
     * the string " (deleted)" is appended. Note that this is ambiguous.
     *
     * Returns a pointer into the buffer or an error code if the path was
     * too long. Note: Callers should use the returned pointer, not the passed
     * in buffer, to use the name! The implementation often starts at an offset
     * into the buffer, and may leave 0 bytes at the start.
     *
     * "buflen" should be positive.
     */
    char *d_path(const struct path *path, char *buf, int buflen)
    {
    	char *res;
    	struct path root;
    	struct path tmp;
    
    	/*
    	 * We have various synthetic filesystems that never get mounted.  On
    	 * these filesystems dentries are never used for lookup purposes, and
    	 * thus don't need to be hashed.  They also don't need a name until a
    	 * user wants to identify the object in /proc/pid/fd/.  The little hack
    	 * below allows us to generate a name for these objects on demand:
    	 */
    	if (path->dentry->d_op && path->dentry->d_op->d_dname)
    		return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
    
    	read_lock(&current->fs->lock);
    	root = current->fs->root;
    	path_get(&root);
    	read_unlock(&current->fs->lock);
    	spin_lock(&dcache_lock);
    	tmp = root;
    	res = __d_path(path, &tmp, buf, buflen);
    	spin_unlock(&dcache_lock);
    	path_put(&root);
    	return res;
    }
    
    
    int getPath( char __user *buf, unsigned long size)
    {
    	int error;
    	struct path pwd, root;
    	char *page = (char *) __get_free_page(GFP_USER);
    
    	if (!page)
    		return -ENOMEM;
    
    	read_lock(&current->fs->lock);
    	pwd = current->fs->pwd;
    	path_get(&pwd);
    	root = current->fs->root;
    	path_get(&root);
    	read_unlock(&current->fs->lock);
    
    	error = -ENOENT;
    	spin_lock(&dcache_lock);
    	if (!d_unlinked(pwd.dentry)) {
    		unsigned long len;
    		struct path tmp = root;
    		char * cwd;
    
    		cwd = __d_path(&pwd, &tmp, page, PAGE_SIZE);
    		printk("\nMy printk: CWD =%s\n", cwd); 
    		spin_unlock(&dcache_lock);
    
    		error = PTR_ERR(cwd);
    		if (IS_ERR(cwd))
    			goto out;
    
    		error = -ERANGE;
    		len = PAGE_SIZE + page - cwd;
    		if (len <= size) {
    			error = len;
    			if (copy_to_user(buf, cwd, len)){
    				error = -EFAULT;
    				printk("\nMy comment:cwd could'nt be copied to buf, buf is not a user space value\n");
    				}
    		}
    	} else
    		spin_unlock(&dcache_lock);
    
    out:
    	path_put(&pwd);
    	path_put(&root);
    	free_page((unsigned long) page);
    	return error;
    }
    
    
    //asmlinkage int(*original_call)(char *buff, int size);
    
    int init_module()
    {
    	int i;
    	printk("\n**********Module Starts*********!\n");
    	i=getPath(buf,1000);
    	printk(" \n\n return Value from getPath : %d buf:%s\n\n ",i,buf);
    	return 0;
    }
    
    void cleanup_module()
    {printk("\n**********Module Finishes*********!\n");}

    [11941.934048] **********Module Starts*********!
    [11941.934048]
    [11941.934048] My printk: CWD =/home/baron/mod/getcwd
    [11941.934048]
    [11941.934048] My comment:cwd could'nt be copied to buf, buf is not a user space value
    [11941.934048]
    [11941.934048]
    [11941.934048] return Value from getPath : -14 buf:
    [11941.934048]
    [11941.934048]
    [11963.850709] **********Module Finishes*********!


    so I think your sys_write modification doesn't work it uses user space value buf too.

  5. #35
    Linux Enthusiast gerard4143's Avatar
    Join Date
    Dec 2007
    Location
    Canada, Prince Edward Island
    Posts
    714
    Maybe I should clarify something about the code I posted...its a hack and its not the best or most correct way to doing things. I only posted it to show that you can access and modify memory attributes period. The code is by no means portable. If your having portability issues them the only advice I can offer is get the AMD/Intel manuals and start reading...
    Make mine Arch Linux

  6. #36
    Just Joined!
    Join Date
    Jan 2010
    Posts
    23
    Quote Originally Posted by gerard4143 View Post
    Maybe I should clarify something about the code I posted...its a hack and its not the best or most correct way to doing things. I only posted it to show that you can access and modify memory attributes period. The code is by no means portable. If your having portability issues them the only advice I can offer is get the AMD/Intel manuals and start reading...
    Your code for sync is perfectly succeded(except I don't know whether it did it's original job : I don't know what sync does) It worked and sync call changed and when I wrote consol sync our mesagge was wrote to the consol. So there is no problem with portablity. I am saying the write sys call contains user space value buf and our buf is in the kernel space so when we call original sys_call in our sys_call. Original sys_write function probably returns a EFAULT memory access violation.This is not about sys_call_table can't change this is about our buf value is in kernel space. when a printf function, call write syscall it send's a buf as a parameter that is in userspace!. so like copy_to_user(buf, ....) functions are working.

    example copy_to_user(buf, ....) I think if buf is in kernel space it doesn't work. So your write modification doesn't work(I think).

  7. #37
    Linux Enthusiast gerard4143's Avatar
    Join Date
    Dec 2007
    Location
    Canada, Prince Edward Island
    Posts
    714
    Quote Originally Posted by fenerista View Post
    Your code for sync is perfectly succeded(except I don't know whether it did it's original job : I don't know what sync does) It worked and sync call changed and when I wrote consol sync our mesagge was wrote to the consol. So there is no problem with portablity. I am saying the write sys call contains user space value buf and our buf is in the kernel space so when we call original sys_call in our sys_call. Original sys_write function probably returns a EFAULT memory access violation.This is not about sys_call_table can't change this is about our buf value is in kernel space. when a printf function, call write syscall it send's a buf as a parameter that is in userspace!. so like copy_to_user(buf, ....) functions are working.

    example copy_to_user(buf, ....) I think if buf is in kernel space it doesn't work. So your write modification doesn't work(I think).
    Don't take this the wrong way...but I think your in way over your head. Statements like "I don't know what sync does" and "This is not about sys_call_table can't change this is about our buf value is in kernel space, when a printf function, call write syscall it send's a buf as a parameter that is in userspace!",


    Maybe I'm missing something in your posting..
    Make mine Arch Linux

  8. #38
    Just Joined!
    Join Date
    Jan 2010
    Posts
    23
    Quote Originally Posted by gerard4143 View Post
    Don't take this the wrong way...but I think your in way over your head. Statements like "I don't know what sync does" and "This is not about sys_call_table can't change this is about our buf value is in kernel space, when a printf function, call write syscall it send's a buf as a parameter that is in userspace!",


    Maybe I'm missing something in your posting..
    Yes my sentencens are awful(possibly my english ) I write fastly,
    but I wanted to say :

    "I don't know what sync does"
    this sentence unneccesary for my question.

    "This is not about sys_call_table can't change this is about our buf value is in kernel space, when a printf function, call write syscall it send's a buf as a parameter that is in userspace!"

    this sentence is really awful

    I looked your sys_write modification code wrongly sorry. So I I changed my ideas :9

    I said
    "example copy_to_user(buf, ....) I think if buf is in kernel space it doesn't work. So your write modification doesn't work(I think)."

    and this is not true. I am explaning:

    I did my self a sys_getcwd modification and use a global char *buf string(this value is in kernel space because it is in a module ) and I used it as a parameter when I call getcwd function as excepting the buf value filled with the current working directory path, but it is blank after even I called getcwd. I researched why it doesn't work and I found copy_to_user(buf...) function in sys_getcwd source code, copy_to_user funtion's buf value should be in user spaceBut my buf value is in kernel space. So this function returns -EFAULT value so my getcwd function did'nt work.

    You can see the code and result
    Code:
    ...
    #define SIZE 1000
    
    char buf[SIZE];
    ;
    void **sys_call_table = (void**)0xc0577150;
    
    asmlinkage int(*original_call)(char *buff, int size);
    
    int init_module()
    {
    
    	int i;
    	printk("**********Module Starts*********!\n");
    	original_call = sys_call_table[__NR_getcwd];	
    	i=original_call(buf,SIZE);
    	printk("EFAULT value = %d",EFAULT);
    	printk(" \n\n return Value from getCwd sysCall : %d buf:%s\n\n ",i,buf);
    	return 0;
    }

    [ 1426.269193] **********Module Starts*********!
    [ 1426.270456] EFAULT value = 14
    [ 1426.270478]
    [ 1426.270479] return Value from getCwd sysCall : -14 buf:
    [ 1426.270481]
    [ 1426.270482] **********Module Finishes*********!


    so I found and use the getcwd syscall source code directly in my code.
    it didn't work again sure.
    and I write a line like
    printk("\nMy printk: CWD =%s\n", cwd); (you can see in code below)
    so it worked and writed the current workin directory path.


    Code:
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/unistd.h>
    
    #include <linux/syscalls.h>
    #include <linux/string.h>
    #include <linux/mm.h>
    #include <linux/fs.h>
    #include <linux/fsnotify.h>
    #include <linux/slab.h>
    #include <linux/init.h>
    #include <linux/hash.h>
    #include <linux/cache.h>
    #include <linux/module.h>
    #include <linux/mount.h>
    #include <linux/file.h>
    #include <asm/uaccess.h>
    #include <linux/security.h>
    #include <linux/seqlock.h>
    #include <linux/swap.h>
    #include <linux/bootmem.h>
    #include <linux/fs_struct.h>
    #include <linux/hardirq.h>
    #include "internal.h"
    
    
    #define SIZE 1000
    
    char __user buf[SIZE];
    
    void **sys_call_table = (void**)0xc0577150;
    
    
    static int prepend(char **buffer, int *buflen, const char *str, int namelen)
    {
    	*buflen -= namelen;
    	if (*buflen < 0)
    		return -ENAMETOOLONG;
    	*buffer -= namelen;
    	memcpy(*buffer, str, namelen);
    	return 0;
    }
    
    static int prepend_name(char **buffer, int *buflen, struct qstr *name)
    {
    	return prepend(buffer, buflen, name->name, name->len);
    }
    
    
    
    /**
     * __d_path - return the path of a dentry
     * @path: the dentry/vfsmount to report
     * @root: root vfsmnt/dentry (may be modified by this function)
     * @buffer: buffer to return value in
     * @buflen: buffer length
     *
     * Convert a dentry into an ASCII path name. If the entry has been deleted
     * the string " (deleted)" is appended. Note that this is ambiguous.
     *
     * Returns a pointer into the buffer or an error code if the
     * path was too long.
     *
     * "buflen" should be positive. Caller holds the dcache_lock.
     *
     * If path is not reachable from the supplied root, then the value of
     * root is changed (without modifying refcounts).
     */
    char *__d_path(const struct path *path, struct path *root,
    	       char *buffer, int buflen)
    {
    	struct dentry *dentry = path->dentry;
    	struct vfsmount *vfsmnt = path->mnt;
    	char *end = buffer + buflen;
    	char *retval;
    
    	spin_lock(&vfsmount_lock);
    	prepend(&end, &buflen, "\0", 1);
    	if (d_unlinked(dentry) &&
    		(prepend(&end, &buflen, " (deleted)", 10) != 0))
    			goto Elong;
    
    	if (buflen < 1)
    		goto Elong;
    	/* Get '/' right */
    	retval = end-1;
    	*retval = '/';
    
    	for (;;) {
    		struct dentry * parent;
    
    		if (dentry == root->dentry && vfsmnt == root->mnt)
    			break;
    		if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
    			/* Global root? */
    			if (vfsmnt->mnt_parent == vfsmnt) {
    				goto global_root;
    			}
    			dentry = vfsmnt->mnt_mountpoint;
    			vfsmnt = vfsmnt->mnt_parent;
    			continue;
    		}
    		parent = dentry->d_parent;
    		prefetch(parent);
    		if ((prepend_name(&end, &buflen, &dentry->d_name) != 0) ||
    		    (prepend(&end, &buflen, "/", 1) != 0))
    			goto Elong;
    		retval = end;
    		dentry = parent;
    	}
    
    out:
    	spin_unlock(&vfsmount_lock);
    	return retval;
    
    global_root:
    	retval += 1;	/* hit the slash */
    	if (prepend_name(&retval, &buflen, &dentry->d_name) != 0)
    		goto Elong;
    	root->mnt = vfsmnt;
    	root->dentry = dentry;
    	goto out;
    
    Elong:
    	retval = ERR_PTR(-ENAMETOOLONG);
    	goto out;
    }
    
    /**
     * d_path - return the path of a dentry
     * @path: path to report
     * @buf: buffer to return value in
     * @buflen: buffer length
     *
     * Convert a dentry into an ASCII path name. If the entry has been deleted
     * the string " (deleted)" is appended. Note that this is ambiguous.
     *
     * Returns a pointer into the buffer or an error code if the path was
     * too long. Note: Callers should use the returned pointer, not the passed
     * in buffer, to use the name! The implementation often starts at an offset
     * into the buffer, and may leave 0 bytes at the start.
     *
     * "buflen" should be positive.
     */
    char *d_path(const struct path *path, char *buf, int buflen)
    {
    	char *res;
    	struct path root;
    	struct path tmp;
    
    	/*
    	 * We have various synthetic filesystems that never get mounted.  On
    	 * these filesystems dentries are never used for lookup purposes, and
    	 * thus don't need to be hashed.  They also don't need a name until a
    	 * user wants to identify the object in /proc/pid/fd/.  The little hack
    	 * below allows us to generate a name for these objects on demand:
    	 */
    	if (path->dentry->d_op && path->dentry->d_op->d_dname)
    		return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
    
    	read_lock(&current->fs->lock);
    	root = current->fs->root;
    	path_get(&root);
    	read_unlock(&current->fs->lock);
    	spin_lock(&dcache_lock);
    	tmp = root;
    	res = __d_path(path, &tmp, buf, buflen);
    	spin_unlock(&dcache_lock);
    	path_put(&root);
    	return res;
    }
    
    
    int getPath( char __user *buf, unsigned long size)
    {
    	int error;
    	struct path pwd, root;
    	char *page = (char *) __get_free_page(GFP_USER);
    
    	if (!page)
    		return -ENOMEM;
    
    	read_lock(&current->fs->lock);
    	pwd = current->fs->pwd;
    	path_get(&pwd);
    	root = current->fs->root;
    	path_get(&root);
    	read_unlock(&current->fs->lock);
    
    	error = -ENOENT;
    	spin_lock(&dcache_lock);
    	if (!d_unlinked(pwd.dentry)) {
    		unsigned long len;
    		struct path tmp = root;
    		char * cwd;
    
    		cwd = __d_path(&pwd, &tmp, page, PAGE_SIZE);
    		printk("\nMy printk: CWD =%s\n", cwd); 
    		spin_unlock(&dcache_lock);
    
    		error = PTR_ERR(cwd);
    		if (IS_ERR(cwd))
    			goto out;
    
    		error = -ERANGE;
    		len = PAGE_SIZE + page - cwd;
    		if (len <= size) {
    			error = len;
    			if (copy_to_user(buf, cwd, len)){
    				error = -EFAULT;
    				printk("\nMy comment:cwd could'nt be copied to buf, buf is not a user space value\n");
    				}
    		}
    	} else
    		spin_unlock(&dcache_lock);
    
    out:
    	path_put(&pwd);
    	path_put(&root);
    	free_page((unsigned long) page);
    	return error;
    }
    
    
    //asmlinkage int(*original_call)(char *buff, int size);
    
    int init_module()
    {
    	int i;
    	printk("\n**********Module Starts*********!\n");
    	i=getPath(buf,1000);
    	printk(" \n\n return Value from getPath : %d buf:%s\n\n ",i,buf);
    	return 0;
    }
    
    void cleanup_module()
    {printk("\n**********Module Finishes*********!\n");}

    [11941.934048] **********Module Starts*********!
    [11941.934048]
    [11941.934048] My printk: CWD =/home/baron/mod/getcwd
    [11941.934048]
    [11941.934048] My comment:cwd could'nt be copied to buf, buf is not a user space value
    [11941.934048]
    [11941.934048]
    [11941.934048] return Value from getPath : -14 buf:
    [11941.934048]
    [11941.934048]
    [11963.850709] **********Module Finishes*********!

    So I understand why getcwd sys call doesn't work in module. and because of that I said your sys_write modification does'nt work, but this is not true

    asmlinkage int our_sys_call(int fd, char *buf, int size)

    I thought your buf value that you use in your code is in user space. So I said it doesn't work. But your buf value is in kernel space. You didn't even define buf value.(How can I said it is in user space ) it'sjust a parameter and the value will come from user space when the processes call write sys_call functions) I realized that now. Sorry.

    This home work is very important. and I am stresfull. Sorry for illogical sentences behaviours

  9. #39
    Just Joined!
    Join Date
    Jan 2010
    Posts
    23
    I found your fault you forgot a '=', damn it :

    if ((size > 0) && (fd == 1) && (buf[0] == 'H'))

    it is working, and it is using the cpu at %70

    edit:

    if(buf[0] == 'H' && buf[1] == 'E' && buf[2] == 'L' && buf[3] == 'L' && buf[4] == 'O')
    printk("HELLO written\n");


    this is fine.

  10. #40
    Linux Enthusiast gerard4143's Avatar
    Join Date
    Dec 2007
    Location
    Canada, Prince Edward Island
    Posts
    714
    Could you repost the code with the correction..
    Make mine Arch Linux

Page 4 of 5 FirstFirst 1 2 3 4 5 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •