Unix Programming - Problem with syscall(2)

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > July 2007 > Problem with syscall(2)





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author Problem with syscall(2)
Daniel Rudy

2007-07-09, 7:18 am


Hello Group,

I am attempting to write a KLD that runs under FreeBSD 6.x. I have the
function, and the code written, but when I call it from the test
program, the passed parameters are getting clobbered with garbage. I've
been looking at this for a couple of hours now, and I'm not finding the
problem. Could someone take a look and see what I'm doing wrong?


**** excerpt from header file:

I copied the padding verbatim from /usr/include/sys/sysproto.h. It
didn't work with or without the padding. I left out the padding
definitions.

typedef struct mod_syscall_cmd_disp_tag__ mod_syscmdisp_t;
struct mod_syscall_cmd_disp_tag__
{
/* command id from user */
char command_l_[PADL_(int)]; int command; char command_r_[PADR_(int)];
/* ptr to aux param block in user space */
char pargs_l_[PADL_(void *)]; void *pargs; char pargs_r_[PADR_(void *)];
};


/* aux param: get/set parameter */
typedef struct mod_param_tag__ mod_param_t;
struct mod_param_tag__
{
int param; /* parameter id */
int value; /* parameter value */
};



**** excerpt from module source file:


/* command function table (read only) */
static const mod_cmdft_t cmd_func_tab[] = {
{MOD_CMD_SETPARAM, sizeof(mod_param_t), &mod_setparam},
{MOD_CMD_GETPARAM, sizeof(mod_param_t), &mod_getparam},
{MOD_CMD_HKGETDIRENT, 0, &mod_hook_getdirent},
{MOD_CMD_RLGETDIRENT, 0, &mod_unhook_getdirent}
};


/* **** SYSCALL FUNCTION HANDLER */

/* implementation of control syscall */
static int mod_syscall(struct thread *td, void *syscall_args)
{
int i;
int sz;
int cidx;
int error;
void *ptr;
mod_syscmdisp_t *uap;


uap = (mod_syscmdisp_t *)syscall_args;
uprintf("pargs %p\n", uap->pargs);

/* locate the command record */
i = 0;
cidx = -1;
sz = sizeof(cmd_func_tab) / sizeof(mod_cmdft_t);
while (i < sz)
{
uprintf("i %d; sz %d; ucmd %d; tcmd %d\n", i, sz, uap->command,
cmd_func_tab[i].command);
if (uap->command == cmd_func_tab[i].command)
{
cidx = i;
break;
}
i++;
}
uprintf("cidx %d\n", cidx);
if (cidx == -1) return(ENOENT); <--- not found error

<snip>

return(0);
}


**** test program:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/module.h>
#include <errno.h>
#include <unistd.h>


#include "security.h"


void ferr(int ec)
{
printf("error: %s\n", strerror(ec));
exit(1);
}


int main(int argc, char *argv[])
{
int syscall_num;
int result;
struct module_stat stat;
mod_syscmdisp_t cpm;

/* determine module's offset value */
stat.version = sizeof(stat);
modstat(modfind("security"), &stat);
syscall_num = stat.data.intval;
printf("syscall found at %d\n", syscall_num);

cpm.command = MOD_CMD_HKGETDIRENT; <--- the command parameters
cpm.pargs = NULL;

result = syscall(syscall_num, &cpm);
if (result != 0) ferr(errno);

return(0);
}

MOD_CMD_HKGETDIRENT is defined at 0x80. Here's what I'm getting for output:

strata:/home/dr2867/c/modules/kernel/security 1056 ### ->kldload
../security.ko
Security module loaded at syscall offset 210.
strata:/home/dr2867/c/modules/kernel/security 1057 ### ->./test
syscall found at 210
pargs 0x2805173b
i 0; sz 4; ucmd -1077941208; tcmd 0
i 1; sz 4; ucmd -1077941208; tcmd 1
i 2; sz 4; ucmd -1077941208; tcmd 128
i 3; sz 4; ucmd -1077941208; tcmd 129
cidx -1
error: No such file or directory
strata:/home/dr2867/c/modules/kernel/security 1058 ### ->kldunload
security.ko
Security module unloaded from syscall offset 210.
strata:/home/dr2867/c/modules/kernel/security 1059 ### ->

The table command entry (tcmd) correctly says 128 (0x80), but the
command parameter from user space (ucmd) has garbage in it. Even the
pargs pointer is garbage as it should be NULL.



--
Daniel Rudy

Email address has been base64 encoded to reduce spam
Decode email address using b64decode or uudecode -m

Why geeks like computers: look chat date touch grep make unzip
strip view finger mount fsck more fsck yes spray umount sleep
Scott Lurndal

2007-07-09, 1:26 pm

Daniel Rudy <spamthis@spamthis.net> writes:
>
>Hello Group,
>
>I am attempting to write a KLD that runs under FreeBSD 6.x. I have the
>function, and the code written, but when I call it from the test
>program, the passed parameters are getting clobbered with garbage. I've
>been looking at this for a couple of hours now, and I'm not finding the
>problem. Could someone take a look and see what I'm doing wrong?


I'm not a bsd expert, but don't you have to 'copyin' the argument from
usermode before accessing it in your system call?

scott
Daniel Rudy

2007-07-09, 7:20 pm

At about the time of 7/9/2007 11:22 AM, Scott Lurndal stated the following:
> Daniel Rudy <spamthis@spamthis.net> writes:
>
> I'm not a bsd expert, but don't you have to 'copyin' the argument from
> usermode before accessing it in your system call?
>
> scott


That's what I did initially, but the call would abort with EFAULT. As
it turns out, *syscall_args is already pointing to kernel space, so
using copyin on it doesn't work.

You know....I just thought of something...I have the number of args set
to 3 in the module definition....I'm only sending 2...Let me fix that
and get back to you.


--
Daniel Rudy

Email address has been base64 encoded to reduce spam
Decode email address using b64decode or uudecode -m

Why geeks like computers: look chat date touch grep make unzip
strip view finger mount fsck more fsck yes spray umount sleep
Daniel Rudy

2007-07-09, 7:20 pm

At about the time of 7/9/2007 1:22 PM, Daniel Rudy stated the following:
> At about the time of 7/9/2007 11:22 AM, Scott Lurndal stated the following:
>
> That's what I did initially, but the call would abort with EFAULT. As
> it turns out, *syscall_args is already pointing to kernel space, so
> using copyin on it doesn't work.
>
> You know....I just thought of something...I have the number of args set
> to 3 in the module definition....I'm only sending 2...Let me fix that
> and get back to you.
>
>


Didn't work. I'm still getting garbage in the parameters.

--
Daniel Rudy

Email address has been base64 encoded to reduce spam
Decode email address using b64decode or uudecode -m

Why geeks like computers: look chat date touch grep make unzip
strip view finger mount fsck more fsck yes spray umount sleep
Scott Lurndal

2007-07-09, 7:20 pm

Daniel Rudy <spamthis@spamthis.net> writes:
>At about the time of 7/9/2007 1:22 PM, Daniel Rudy stated the following:
>
>Didn't work. I'm still getting garbage in the parameters.
>


It's possible, I suppose, that BSD's syscall dispatcher will do the copyin
for you, but seems unlikely. How did you determine that *syscall_args
is pointing to kernel space?

scott
tedu

2007-07-09, 7:20 pm

On Jul 9, 1:33 am, Daniel Rudy <spamt...@spamthis.net> wrote:
> Hello Group,
>
> I am attempting to write a KLD that runs under FreeBSD 6.x. I have the
> function, and the code written, but when I call it from the test
> program, the passed parameters are getting clobbered with garbage. I've
> been looking at this for a couple of hours now, and I'm not finding the
> problem. Could someone take a look and see what I'm doing wrong?
>
>
> /* implementation of control syscall */
> static int mod_syscall(struct thread *td, void *syscall_args)
> {
> int i;
> int sz;
> int cidx;
> int error;
> void *ptr;
> mod_syscmdisp_t *uap;
>
> uap = (mod_syscmdisp_t *)syscall_args;


syscall_args is not a pointer to mod_syscmdisp_t. it's more likely a
pointer to a pointer of one, based on the usage in your example.

Daniel Rudy

2007-07-10, 7:20 am

In-Reply-To: <70yki.4602$rL1.339@newssvr19.news.prodigy.net>
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
Lines: 45
Message-ID: <prHki.1585$m%.361@newssvr17.news.prodigy.net>
NNTP-Posting-Host: 71.146.37.62
X-Complaints-To: abuse@prodigy.net
X-Trace: newssvr17.news.prodigy.net 1184056149 ST000 71.146.37.62 (Tue, 10 Jul 2007 04:29:09 EDT)
NNTP-Posting-Date: Tue, 10 Jul 2007 04:29:09 EDT
X-UserInfo1: TSU& #91;@SVEVRRYCTLZNCOF_W\@PJ_^PBQLGPQRZ\YI
JYWZUYICD^RAQBKZQTZTX\_I[^G_KGFNON[ZOE_AZNVO^\XGGNTCIRPIJH& #91;@RQKBXLRZ@CD^HKANYVW@RLGEZEJN@\_WZJB
NZYYKVIOR]T]MNMG_Z[YVWSCH_Q[GPC_A@CARQVXDSDA^M]@DRVUM@RBM
Date: Tue, 10 Jul 2007 01:29:14 -0700
Bytes: 3492
Xref: number1.nntp.dca.giganews.com comp.unix.programmer:179240

At about the time of 7/9/2007 2:45 PM, Scott Lurndal stated the following:
> Daniel Rudy <spamthis@spamthis.net> writes:
>
> It's possible, I suppose, that BSD's syscall dispatcher will do the copyin
> for you, but seems unlikely. How did you determine that *syscall_args
> is pointing to kernel space?
>
> scott


Because, the addresses involved when I tried to copy the args to a stack
buffer, were very close...the args were also on the stack.

--
Daniel Rudy

Email address has been base64 encoded to reduce spam
Decode email address using b64decode or uudecode -m

Why geeks like computers: look chat date touch grep make unzip
strip view finger mount fsck more fsck yes spray umount sleep
Daniel Rudy

2007-07-10, 7:20 am

At about the time of 7/9/2007 3:02 PM, tedu stated the following:
> On Jul 9, 1:33 am, Daniel Rudy <spamt...@spamthis.net> wrote:
>
> syscall_args is not a pointer to mod_syscmdisp_t. it's more likely a
> pointer to a pointer of one, based on the usage in your example.
>


I don't agree....here's why:

/usr/src/sys/kern/sys_generic.c:LINE#96-START
/*
* Read system call.
*/
#ifndef _SYS_SYSPROTO_H_
struct read_args {
int fd;
void *buf;
size_t nbyte;
};
#endif
/*
* MPSAFE
*/
int
read(td, uap)
struct thread *td;
struct read_args *uap;
{
struct uio auio;
struct iovec aiov;
int error;

if (uap->nbyte > INT_MAX)
return (EINVAL);
aiov.iov_base = uap->buf;
aiov.iov_len = uap->nbyte;
auio.uio_iov = &aiov;
auio.uio_iovcnt = 1;
auio.uio_resid = uap->nbyte;
auio.uio_segflg = UIO_USERSPACE;
error = kern_readv(td, uap->fd, &auio);
return(error);
}
/usr/src/sys/kern/sys_generic.c:LINE#118-END

This code is the kernel read syscall. I don't see anything in there
where it's doing a copyin for any of the uap parameters. It looks
normal to me, and obviously it correct, because if it wasn't the
computer wouldn't work. This is from FreeBSD 6.2-RELEASE.


--
Daniel Rudy

Email address has been base64 encoded to reduce spam
Decode email address using b64decode or uudecode -m

Why geeks like computers: look chat date touch grep make unzip
strip view finger mount fsck more fsck yes spray umount sleep
tedu

2007-07-10, 1:23 pm

On Jul 10, 1:41 am, Daniel Rudy <spamt...@spamthis.net> wrote:
> At about the time of 7/9/2007 3:02 PM, tedu stated the following:
>
>
>
>
>
>
>
>
> I don't agree....here's why:
>
> /usr/src/sys/kern/sys_generic.c:LINE#96-START
> /*
> * Read system call.
> */
> #ifndef _SYS_SYSPROTO_H_
> struct read_args {
> int fd;
> void *buf;
> size_t nbyte;};
>
> #endif
>
> This code is the kernel read syscall. I don't see anything in there
> where it's doing a copyin for any of the uap parameters. It looks
> normal to me, and obviously it correct, because if it wasn't the
> computer wouldn't work. This is from FreeBSD 6.2-RELEASE.


what does syscall args look like for your syscall?

Daniel Rudy

2007-07-11, 7:21 am

At about the time of 7/10/2007 10:45 AM, tedu stated the following:
> On Jul 10, 1:41 am, Daniel Rudy <spamt...@spamthis.net> wrote:
>
> what does syscall args look like for your syscall?
>


This is the test program:

int main(int argc, char *argv[])
{
int syscall_num;
int result;
struct module_stat stat;
mod_syscmdisp_t cpm;

/*
if (argc != 2) usage(argv[0]);
*/

/* determine module's offset value */
stat.version = sizeof(stat);
modstat(modfind("security"), &stat);
syscall_num = stat.data.intval;
printf("syscall found at %d\n", syscall_num);

printf("mod_syscmdisp_t %d\n", sizeof(mod_syscmdisp_t));
cpm.command = MOD_CMD_HKGETDIRENT;
cpm.pargs = NULL;

result = syscall(syscall_num, &cpm); <---- Call Here
if (result != 0) ferr(errno);

return(0);
}

But, as someone else pointed out, you are correct in your initial
statement. It does seem it's a pointer to a pointer issue. The value
in the command variable is actually a pointer to the actual parameters
on the user stack. Since it's a pointer to a pointer, I think I know
what to do now. I'm going to make some code changes and try them out.
I'll post the results here. Should be interesting.

Furthermore, I wish to extend a big thank you to everyone who has
responded so far. I'm suprized that I have not yet caused a system
panic with my faulty code. I have a book on the FreeBSD kernel by one
of the original core developers. It's a great book if you are looking
though the source to see how it works. But it doesn't teach you the ins
and outs of kernel mode programming, which is what I need.

--
Daniel Rudy

Email address has been base64 encoded to reduce spam
Decode email address using b64decode or uudecode -m

Why geeks like computers: look chat date touch grep make unzip
strip view finger mount fsck more fsck yes spray umount sleep
Daniel Rudy

2007-07-11, 1:22 pm

At about the time of 7/11/2007 2:09 AM, Daniel Rudy stated the following:
> At about the time of 7/10/2007 10:45 AM, tedu stated the following:
>
> This is the test program:
>
> int main(int argc, char *argv[])
> {
> int syscall_num;
> int result;
> struct module_stat stat;
> mod_syscmdisp_t cpm;
>
> /*
> if (argc != 2) usage(argv[0]);
> */
>
> /* determine module's offset value */
> stat.version = sizeof(stat);
> modstat(modfind("security"), &stat);
> syscall_num = stat.data.intval;
> printf("syscall found at %d\n", syscall_num);
>
> printf("mod_syscmdisp_t %d\n", sizeof(mod_syscmdisp_t));
> cpm.command = MOD_CMD_HKGETDIRENT;
> cpm.pargs = NULL;
>
> result = syscall(syscall_num, &cpm); <---- Call Here
> if (result != 0) ferr(errno);
>
> return(0);
> }
>
> But, as someone else pointed out, you are correct in your initial
> statement. It does seem it's a pointer to a pointer issue. The value
> in the command variable is actually a pointer to the actual parameters
> on the user stack. Since it's a pointer to a pointer, I think I know
> what to do now. I'm going to make some code changes and try them out.
> I'll post the results here. Should be interesting.
>
> Furthermore, I wish to extend a big thank you to everyone who has
> responded so far. I'm suprized that I have not yet caused a system
> panic with my faulty code. I have a book on the FreeBSD kernel by one
> of the original core developers. It's a great book if you are looking
> though the source to see how it works. But it doesn't teach you the ins
> and outs of kernel mode programming, which is what I need.
>


I tried the new code and it now works. I have it accepting 2
parameters, and I'm calling it with 2 parameters.

--
Daniel Rudy

Email address has been base64 encoded to reduce spam
Decode email address using b64decode or uudecode -m

Why geeks like computers: look chat date touch grep make unzip
strip view finger mount fsck more fsck yes spray umount sleep
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com