Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 10 Aug 2001 17:20:14 +0400 (MSD)
From:      "Eugene L. Vorokov" <vel@bugz.infotecs.ru>
To:        lorenzo@linuxbe.org (Sansonetti Laurent)
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: Doing file operations on syscalls handler
Message-ID:  <200108101320.f7ADKEq11115@bugz.infotecs.ru>
In-Reply-To: <no.id> from "Sansonetti Laurent" at Aug 10, 2001 02:08:57 PM

next in thread | previous in thread | raw e-mail | index | archive | help
> Hello hackers,
> 
> I'm new on FreeBSD modules programming, and I've a little question...
> How can I do file operations (like open(), read()..) on a syscall handler of
> a syscall module ?
> In fact I've met the problem since my module must open a file which contains
> some informations for the hacked syscall (in this case, it's
> getdirentries())..
> I've tried to malloc a open_args struct, filled-it and use [sys] open, but
> it doesn't work...
> Is there a way to call user syscalls ?
> 
> Thanks you for your answer.. I don't have many informations on FreeBSD
> modules programming.. forgive-me ;)

I think I should put this onto some webpage or something, as I had to post
this several times already :). Guys, please please please search mailing
list archives prior to asking.

In most cases, when you "need" to read files from kernel modules, it means
that you should rethink your problem and the way you go to solve it.
I don't have much information about what you're trying to do, but according
to what you say, you can pretty well have some userland program which will
read the file and pass the information to your module (for instance, your
module can create a device and your userland program can open() it and
write() to it, or you can add new syscall, or whatever). This is how for
instance ipfw and ipf work, modules theirselves don't read configuration
files. Think about speed, too: imagine your system getting numerous
getdirentries() syscalls in a short time - reading from the file each time
would slow down your system a lot.

However, there are some cases when you still need to read from a file from
your module. For istance, I have a module which must read it's config
file on startup itself, because it contains information about which programs
are allowed to use it's device i/o interface later. In most circumstances
it can be done, however I think it will not work when you are in the interrupt
handler or other state where disk i/o isn't surely possible. If you intercept
getdirentries(), I think it will pretty well work, but I can only say that
my method works for me in MOD_LOAD event handler.

Basicly, the problem is that all syscalls expect their arguments to be
pointers to the userland memory and not kernel. As you probably know, these
are totally separated. All syscalls use copyin() to copy arguments from
userland, and this function makes sure that argument is located in userland,
and returns error if it isn't. This is done like that to avoid userland
programs passing kernel addresses to syscalls and thus manipulating kernel
structures in a manner they never should. Thus, if you want to use syscalls
from kernel, you must put arguments in the userland memory of current
process and then pass them to the syscall handler. The least dangerous
method of getting some piece of userland memory (as seems to me) is using
mmap() (or, preferably, vm_mmap() directly) with fd == -1 and MAP_ANON
flag. mmap() doesn't require anything to be in userland, you can build
your own mmap_args as needed and call mmap(), passing curproc as the first
argument. Don't forget that mmap() will only return error code; actuall
address of memory allocated, if call was successful, is in the
curproc->p_retval[0], which you should rather save before you do syscall
and restore later. Once you have buffer allocated, you can copyout()
your filename to it and pass that address to open() syscall, then
allocate another buffer the same way, call read() on it, then use copyin()
to transfer the buffer to kernel space. Do note that you must never use
memory allocated by mmap() in the regular manner (C operations, string
functions, etc); it may work, and will most probably work currently
on i386 machines; but don't be fooled as I was at first, it's not supposed
to work, because in general case kernelspace and userspace can have totally
different address spaces, and access from one to another would require
context switching. You can only use copyin(), copyout(), fubyte(), subyte()
and other functions from that family; read manual pages.

Of course, don't forget to call close() and munmap() once you're done.
Do not try using processes other than curproc for mmap() allocation -
it will not work. Avoid defining buffers in kernel as local variables
of some functions - kernel stack is very small, and you will most likely
end up with a double fault panic; use MALLOC() instead.

And, as I always did before, I'll add that all this technology looks like
a very ugly hack for me, it's really not a good example of what kernel
module should do. Still it works for me.

Regards,
Eugene


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




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