From owner-freebsd-hackers Fri Aug 10 6:20:34 2001 Delivered-To: freebsd-hackers@freebsd.org Received: from bugz.infotecs.ru (bugz.infotecs.ru [195.210.139.22]) by hub.freebsd.org (Postfix) with ESMTP id BE62237B406 for ; Fri, 10 Aug 2001 06:20:27 -0700 (PDT) (envelope-from vel@bugz.infotecs.ru) Received: (from root@localhost) by bugz.infotecs.ru (8.11.5/8.11.4) id f7ADKEq11115; Fri, 10 Aug 2001 17:20:14 +0400 (MSD) (envelope-from vel) From: "Eugene L. Vorokov" Message-Id: <200108101320.f7ADKEq11115@bugz.infotecs.ru> Subject: Re: Doing file operations on syscalls handler To: lorenzo@linuxbe.org (Sansonetti Laurent) Date: Fri, 10 Aug 2001 17:20:14 +0400 (MSD) Cc: freebsd-hackers@freebsd.org In-Reply-To: from "Sansonetti Laurent" at Aug 10, 2001 02:08:57 PM X-Mailer: ELM [version 2.5 PL5] MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG > 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