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.