Thanks for the insight, this is very useful information. Perhaps I'll look 
into the mmap route.

- Matt

On Friday, May 17, 2019 at 12:54:28 PM UTC-4, Ian Lance Taylor wrote:
>
> On Fri, May 17, 2019 at 7:44 AM Matt Layher <mdla...@gmail.com 
> <javascript:>> wrote: 
> > 
> >> Pointers passed to unix.Syscall or syscall.Syscall are always safe. 
> >> They will be treated as live for the duration of the call to Syscall, 
> >> and they will not be moved.  This is a special exception for functions 
> >> written in assembly, documented at 
> >> https://golang.org/pkg/unsafe/#Pointer.  I don't see any obvious 
> >> problem with your code. 
> > 
> > 
> > Right. I'm passing a pointer to a structure as usual to ioctl, but that 
> structure also stores the memory address of an array in a union (which is 
> [n]byte in Go), and then the kernel code interprets both the structure's 
> address and the union's stored address as pointers again. That is where my 
> concern about the slice potentially being moved comes from. I'm not sure 
> this would fall under the rule you mention above, because the memory 
> address stored in the union just appears to be random bytes, unless the Go 
> compiler is keeping track of it internally. 
>
> Ah, sorry, I missed that.  If you are storing a Go pointer (a pointer 
> to memory allocated by Go) in a [N]byte, that is unsafe.  The cases in 
> which a pointer may be safely converted to a value of non-pointer type 
> are enumerated at https://golang.org/pkg/unsafe, and that is not one 
> of them.  As you say, in some cases the memory might be moved, but the 
> runtime won't update the pointer value hidden in the [N]byte. 
>
> It would be OK to pass a pointer to a struct to ioctl if the struct 
> contains a pointer to other Go memory, but the struct field must have 
> pointer type. 
>
>
> >> Note that things would be different if you were using cgo, which 
> >> follows different and more complicated rules.  But at least in this 
> >> example, you aren't. 
> > 
> > 
> > I made a patch which allocates memory using Cgo instead of Go to 
> potentially alleviate my above concern: 
> https://github.com/WireGuard/wgctrl-go/pull/49/commits/05d446d3d7b2e376424e57a5167205a325d61781,
>  
> so I am using a bit of Cgo at this point. Although I'd rather not if it 
> were deemed safe to go with my original pure Go approach. 
>
> Allocating the memory with cgo is safe.  It would also be safe to 
> allocate the memory in some way other than using Go's memory 
> allocator, such as by using syscall.Mmap. 
>
> Ian 
>
>
> > On Friday, May 17, 2019 at 10:32:44 AM UTC-4, Ian Lance Taylor wrote: 
> >> 
> >> On Thu, May 16, 2019 at 5:24 AM Matt Layher <mdla...@gmail.com> wrote: 
> >> > 
> >> > I'm working on a project that involves an ioctl API on OpenBSD. The 
> idea is that you store a memory address in a union within another 
> structure, and then invoke the ioctl. When it returns, both the structure 
> itself and the memory pointed at by the address in the union are filled 
> with data by the kernel. 
> >> > 
> >> > I originally wrote a pure Go version of this code that seems to work, 
> but after a conversation in #darkarts on Gophers Slack (starting at 
> https://gophers.slack.com/archives/C1C1YSQBT/p1557956939402700), several 
> of us were unsure if this version was actually safe. See the body of this 
> function: 
> >> > 
> >> > 
> https://github.com/WireGuard/wgctrl-go/blob/7e04c64d5b80f1991b52c6025d6f59e6aa3a3939/internal/wgopenbsd/client_openbsd.go#L59
>  
> >> > 
> >> > The concern was as follows: 
> >> > 
> >> > > i think the usage of `ifgrs` is unsafe... 
> >> > > maybe it's alright because it'll always be heap allocated due to 
> the dynamic size of it, but afaict, the compiler could deduce that it 
> doesn't escape and then the call to ioctl could move it during a stack 
> realloc.. 
> >> > 
> >> > After thinking it over and having a further discussion, I decided to 
> try passing a pointer to memory allocated with C.malloc instead, and this 
> also seems to work. 
> >> > 
> >> > 
> https://github.com/WireGuard/wgctrl-go/pull/49/commits/05d446d3d7b2e376424e57a5167205a325d61781
>  
> >> > 
> >> > My question is: is this necessary, and if so, have I implemented it 
> correctly? I've typically just passed pointers to structures with no other 
> pointers directly with Linux APIs; never a pointer to a structure that also 
> contains other pointers to other memory. I'm a little shaky on Cgo since 
> I've mostly gotten by without it during my time writing Go. 
> >> 
> >> Pointers passed to unix.Syscall or syscall.Syscall are always safe. 
> >> They will be treated as live for the duration of the call to Syscall, 
> >> and they will not be moved.  This is a special exception for functions 
> >> written in assembly, documented at 
> >> https://golang.org/pkg/unsafe/#Pointer.  I don't see any obvious 
> >> problem with your code. 
> >> 
> >> Note that things would be different if you were using cgo, which 
> >> follows different and more complicated rules.  But at least in this 
> >> example, you aren't. 
> >> 
> >> Ian 
> > 
> > -- 
> > You received this message because you are subscribed to the Google 
> Groups "golang-nuts" group. 
> > To unsubscribe from this group and stop receiving emails from it, send 
> an email to golan...@googlegroups.com <javascript:>. 
> > To view this discussion on the web visit 
> https://groups.google.com/d/msgid/golang-nuts/8c5a3a65-2891-4c4a-bd79-71e910571ac2%40googlegroups.com.
>  
>
> > For more options, visit https://groups.google.com/d/optout. 
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/12735651-345e-45f9-9137-62b35cdeb1f9%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to