On Fri, May 17, 2019 at 7:44 AM Matt Layher <mdlay...@gmail.com> 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 golang-nuts+unsubscr...@googlegroups.com. > 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/CAOyqgcW119LG1Puzwkz9hZjyXKrDQBGO498HuHW-got%3D2ZisUw%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.