Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 30 Jul 1997 12:52:18 +0930 (CST)
From:      Michael Smith <msmith@atrad.adelaide.edu.au>
To:        dg@root.com
Cc:        msmith@atrad.adelaide.edu.au, freebsd-hackers@FreeBSD.ORG
Subject:   Re: Location of copyin() and copyout()..
Message-ID:  <199707300322.MAA17715@genesis.atrad.adelaide.edu.au>
In-Reply-To: <199707300310.UAA12221@implode.root.com> from David Greenman at "Jul 29, 97 08:10:28 pm"

next in thread | previous in thread | raw e-mail | index | archive | help
David Greenman stands accused of saying:
>>> I don't understand the distinction you're making. copyout *always* runs in
>>>the (kernel) context of a user process and the destination is always process
>>>(as opposed to kernel) memory. Please explain.
> >
> >If I am writing an ABI emulation function that exchanges data with the
> >emulated binary in one format, but need to pass the data in a
> >different format to/from the function(s) in the kernel which provide
> >the required functionality, I have to perform the format translation
> >in buffers in kernel space.
> >
> >If the kernel function(s) use copyin/copyout, they cannot access these
> >buffers, and thus the emulation cannot be performed.
> 
> I still don't understand. copyin/out is only for copying between the kernel
> and user memory. If this is what you're doing and you don't need the extra
> features of uiomove (which is designed to do piecemeal copies by keeping track
> of offsets/lengths in a struct uio), then copyin/out is the function to use.
> If on the other hand you're copying from kernel<->kernel, then you can just
> use bcopy. I'm afraid that I started reading this thread rather late into it
> and don't have the original context...so what are we talking about? :-)

AAARGH!  8) 8) 8)

How about a specific example, the one that bloodied my nose a little
while back.

The FreeBSD kernel function i386_set_ldt() uses copyin() to retrieve
its arguments from the user process.

Linux uses the i386_modify_ldt syscall to perform the same
functionality.  It has a different set of arguments, which convey
essentially the same information.

So, I write a function linux_i386_modify_ldt(), which lives in the
linux emulation module.  It takes the Linux i386_modify_ldt() syscall,
converts the arguments to the right format, and tries to call
i386_set_ldt().

Only it _can't_, because the latter is using copyin(), and cannot access
the argument structure in kernel space.

If i386_set_ldt() used uiomove, I could construct a uio structure in
linux_i386_modify_ldt() that told uimove that the source address was 
in kernel space, and i386_set_ldt() wouldn't have to care.

So, what I am _begging_ is : do *not* use copyin()/copyout() unless you
are absolutely, utterly, 110% certain that you will only _ever_ be
talking directly to user memory.  

This boils down to not ever using copyin/out to handle data in device
drivers, syscall handlers, protocol stacks, etc., ie. basically not at
all.

-- 
]] Mike Smith, Software Engineer        msmith@gsoft.com.au             [[
]] Genesis Software                     genesis@gsoft.com.au            [[
]] High-speed data acquisition and      (GSM mobile)     0411-222-496   [[
]] realtime instrument control.         (ph)          +61-8-8267-3493   [[
]] Unix hardware collector.             "Where are your PEZ?" The Tick  [[



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