Skip to content

x/sys: invalid use of unsafe.Pointer in ioctl arg parameters #44834

Closed

Description

@brunnre8

From the documentation of unsafe.Pointer:

(4) Conversion of a Pointer to a uintptr when calling syscall.Syscall.

The Syscall functions in package syscall pass their uintptr arguments
directly to the operating system, which then may, depending on the details
of the call, reinterpret some of them as pointers.
That is, the system call implementation is implicitly converting certain
arguments back from uintptr to pointer.

If a pointer argument must be converted to uintptr for use as an argument,
that conversion must appear in the call expression itself

Now, as far as I can tell this forces packages to adhere to exactly that.

The code in x/sys clearly violates that rule.

in unix/ioctl.go there's

// IoctlSetPointerInt performs an ioctl operation which sets an
// integer value on fd, using the specified request number. The ioctl
// argument is called with a pointer to the integer value, rather than
// passing the integer value directly.
func IoctlSetPointerInt(fd int, req uint, value int) error {
        v := int32(value)
        return ioctl(fd, req, uintptr(unsafe.Pointer(&v)))
}

and the declaration of ioctl in zsyskall_linux.go:

func ioctl(fd int, req uint, arg uintptr) (err error) {
        _, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
        if e1 != 0 {
                err = errnoErr(e1)
        }
        return
}

I've asked on the mailing list if that's valid usage of unsafe, @ianlancetaylor wasn't sure and told me to open an issue here for further discussion. (https://groups.google.com/g/golang-nuts/c/Ocpy8CKs7ZI/m/3ym8gnuBFgAJ)

Activity

  1. added this to the Unreleased milestone on Mar 6, 2021
  2. added
    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.
    on Mar 8, 2021
  3. cuonglm commented on Apr 30, 2021

    @cuonglm
    Member

    This is safe.

    • v will be kept alive through ioctl call.
    • The rule is only applied for pointer must be converted to uintptr, ioctl does uintptr(arg) where arg is an uintptr, not a pointer.
  4. cuonglm commented on May 3, 2021

    @cuonglm
    Member
  5. mdempsky commented on May 3, 2021

    @mdempsky
    Contributor

    I don't think that code is safe.

    The ioctl function does not have any pragmas to mark it as a syscall function, so the compiler won't know to do anything special for it. So the call to ioctl could potentially grow the stack, and then the arg pointer would be stale pointing to old memory.

  6. cuonglm commented on May 3, 2021

    @cuonglm
    Member

    I don't think that code is safe.

    The ioctl function does not have any pragmas to mark it as a syscall function, so the compiler won't know to do anything special for it. So the call to ioctl could potentially grow the stack, and then the arg pointer would be stale pointing to old memory.

    Hmm, so, whether it violates unsafe pointer rule?

    Maybe the right fix is passing in an unsafe.Pointer instead of an uintptr 🤔

  7. cuonglm commented on May 3, 2021

    @cuonglm
    Member

    Maybe the right fix is passing in an unsafe.Pointer instead of an uintptr 🤔

    or using go:nosplit

  8. mdempsky commented on May 3, 2021

    @mdempsky
    Contributor

    Maybe the right fix is passing in an unsafe.Pointer instead of an uintptr

    I think so. The Linux ioctl man page at least says that the third argument is always a pointer. (If there are any ioctls that do actually pass a scalar value directly instead of a pointer, they'll need a separate utility wrapper.)

  9. ianlancetaylor commented on May 3, 2021

    @ianlancetaylor
    Contributor

    @mdlayher added IoctlSetInt for Linux in https://golang.org/cl/44009 for #20474. That suggests that Linux has some ioctls that don't take a pointer value for the third argument, although off hand I do not know what they are.

  10. lhl2617 commented on May 9, 2021

    @lhl2617

    @mdlayher added IoctlSetInt for Linux in https://golang.org/cl/44009 for #20474. That suggests that Linux has some ioctls that don't take a pointer value for the third argument, although off hand I do not know what they are.

    From https://man7.org/linux/man-pages/man2/ioctl.2.html:

    The third argument is an untyped pointer to memory

    From https://docs.oracle.com/cd/E23824_01/html/821-1463/ioctl-2.html

    The arg argument represents a third argument that has additional information that is needed by this specific device to perform the requested function. The data type of arg depends upon the particular control request, but it is either an int or a pointer to a device-specific data structure.

    It thus seems like IoctlSetInt was made for solaris consistent with the description in #20474. It should never be used for linux.

  11. lhl2617 commented on May 9, 2021

    @lhl2617

    Relevant issue: #34684

  12. gopherbot commented on Aug 9, 2021

    @gopherbot
    Contributor

    Change https://golang.org/cl/340915 mentions this issue: unix: generate ioctlNew on Linux with unsafe.Pointer arg

  13. changed the title [-]x/sys: potential invalid use of unsafe[/-] [+]x/sys: invalid use of unsafe.Pointer in ioctl arg parameters[/+] on Aug 10, 2021
  14. bcmills commented on Feb 7, 2023

    @bcmills
    Contributor

    @mdempsky, @ianlancetaylor, @mdlayher: was this fixed by CL 340915, or is there more to do here?

  15. 2 remaining items

  16. thediveo commented on Feb 7, 2023

    @thediveo
    Contributor

    @mdlayher added IoctlSetInt for Linux in https://golang.org/cl/44009 for #20474. That suggests that Linux has some ioctls that don't take a pointer value for the third argument, although off hand I do not know what they are.

    Here we are, FICLONE https://man7.org/linux/man-pages/man2/ioctl_ficlonerange.2.html ... which I didn't knew existed a few moments ago 😁

  17. gopherbot commented on Feb 17, 2023

    @gopherbot
    Contributor

    Change https://go.dev/cl/469315 mentions this issue: unix: add ioctlPtr with unsafe.Pointer arg on other unices

  18. gopherbot commented on Feb 20, 2023

    @gopherbot
    Contributor

    Change https://go.dev/cl/469675 mentions this issue: syscall: avoid passing Go pointers as uintptr in exec tests

  19. gopherbot commented on Feb 21, 2023

    @gopherbot
    Contributor

    Change https://go.dev/cl/469835 mentions this issue: unix: add ptracePtr that accepts pointer arg as unsafe.Pointer

  20. gopherbot commented on Feb 24, 2023

    @gopherbot
    Contributor

    Change https://go.dev/cl/471119 mentions this issue: unix: add ioctlPtr with unsafe.Pointer arg on other unices (cont)

  21. bcmills commented on May 3, 2023

    @bcmills
    Contributor

    @dmgk, can this issue be closed now, or is there more work remaining for it?

  22. dmgk commented on May 3, 2023

    @dmgk
    Member

    I believe this is done, closing.

  23. brunnre8 commented on May 4, 2023

    @brunnre8
    Author

    Thanks a lot to everyone involved

  24. locked and limited conversation to collaborators on May 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.help wanted

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions