Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 26 Sep 2000 13:59:31 -0700
From:      Alfred Perlstein <bright@wintelcom.net>
To:        "Yonny Cardenas B." <ycardena@yahoo.com>
Cc:        questions@FreeBSD.ORG
Subject:   Re: Add a system call
Message-ID:  <20000926135931.B9141@fw.wintelcom.net>
In-Reply-To: <39D10614.9ECD8635@yahoo.com>; from ycardena@yahoo.com on Tue, Sep 26, 2000 at 03:24:52PM -0500
References:  <39D10614.9ECD8635@yahoo.com>

next in thread | previous in thread | raw e-mail | index | archive | help
* Yonny Cardenas B. <ycardena@yahoo.com> [000926 13:22] wrote:
> Hi, 
> 
> I have been trying to insert a new system call (very simple),
> I have used the steps in the bottom without problems, 
> but I don't understand the behavior of the program:
> 
> ::::::::::::::
> mysyscall.c
> ::::::::::::::
> int mysyscall( int *n ) {
>    printf("In the kernel!\n");
>    *n = ( *n + 1000);
>    return 0;
> }
> 
> ::::::::::::::
> myprog.c
> ::::::::::::::
> int mysyscall (int * );
> 
> int main (void){
>    int x = 500;
>    mysyscall(&x);
>    printf("x= %i\n",x);
> }
> 
> The kernel syscall apparently run but it doesn't modify the variable.
> 
> $cc -o miprog miprog.c
> $ ./miprog 
> x= 500
> 
> In the kernel! <--- is showed in the console.
> 
> If I compile with the function (syscall), it works apparently correctly.
> 
> $cc -o miprog miprog.c mysyscall.c 
> $ ./miprog 
> In the kernel!
> x= 1500

You can't do that, the kernel and userland address spaces are sorta
seperate, you must use copyin/copyout (there's some other stuff like 
suword and SCARG).

Here's what mysyscall needs to look like:

int
mysyscall(struct proc *p, struct mysyscall_args *uap)
{
	int	x;

	printf("In the kernel!\n");
	/*
	 * copy the value from userspace, SCARG just pulls the
	 * field out of the struct pointer (same as uap->x)
	 */
	error = copyin(SCARG(uap, x), &x, sizeof(x));
	/*
	 * did they give us a messed up pointer that caused us to fail
	 * the copy? (maybe NULL? or just invalid?)
	 */
	if (error)
		return (error);

	printf("Incrementing!\n");
	/* ok they didn't increment what we just got */
	x++;

	printf("Copying back to userland!\n");
	/* now try to write it back over the int they gave us */
	error = copyout(&x, SCARG(uap, x), sizeof(x));
	/* not likely, same thing as copyin, but you never know. */
        if (error)
		return (error);
	printf("We made it!\n");
	/* ok, we're good! */
	return (0);
}

You need to make sure your entry in syscalls.master looks like this:
172 STD BSD { int mysyscall(int *x); }

Btw, your code allows the user to specify an arbitrary kernel address
that's going to be incremented, if you want to blow the machine up,
have your application pass in a NULL pointer and watch the kernel
panic.. :)

-- 
-Alfred Perlstein - [bright@wintelcom.net|alfred@freebsd.org]
"I have the heart of a child; I keep it in a jar on my desk."


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-questions" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20000926135931.B9141>