nix icon indicating copy to clipboard operation
nix copied to clipboard

ioctl_write_int! wrong data size call

Open oletf opened this issue 4 months ago • 4 comments

Greetings,

here's my setup :

  • aarch64-unknown-linux-gnu rust 1.88.0
  • gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
  • ldd (Ubuntu GLIBC 2.35-0ubuntu3.10) 2.35

The C IOCTL is defined with _IOW(IOCTL_MAGIC, 3, ulong) I'm using ioctl_write_int!, docs specifies that nix::sys::ioctl::ioctl_param_type on linux is libc::c_ulong, which is 8 bytes.

I have checked that

  • on rust side with size_of::<nix::sys::ioctl::ioctl_param_type>(), reports 8 bytes
  • on C side with sizeof(ulong), 8 bytes as well

However the ioctl cmd call I receive in my c driver is 0x4004f003 which decodes to dir=1 type=240 nr=3 size=4.

I couldn't figure where this could be coming from... My current workaround is to set IOCTL to _IOW(IOCTL_MAGIC, 3, uint) as I'm ok with this type, but I'm confused by the mismatch.

Please let me know if I can bring more info to help !

oletf avatar Jul 30 '25 10:07 oletf

I think this is the correct behavior for ioctl_write_int!, but there is a documentation bug, introduced by dc41be48a7 . I'm not sure why that commit introduced that change. Perhaps a merge conflict of some sort?

asomers avatar Jul 30 '25 15:07 asomers

Ok I think I got the source of the problem :

so ultimately the confusion comes from the fact that for cfg(linux), the rust type is documented and generated as using ioctl_param_type (which is c_ulong), BUT does not use sizeof::<ioctl_param_type> (uses c_int), so there's a clear mismatch between all the hints given to user of the lib (fn type and doc), and what the actual generated function passes to the kernel call.

I think this is the correct behavior for ioctl_write_int!

It is indeed the correct behavior for BSD, but the _IOWINT doesn't exist on linux, hence this macro being adapted for it

As making a change on the generated ioctl call would be probably more breaking on the C side than changing the ioctl_param_type on rust side (would only need to add as _, and check over/underflow consequences), changing back ioctl_param_type to c_int and updating the doc accordingly would seem like the most reasonable change to reduce confusion of lib users.

I can close the issue as my confusion is now cleared. I don't know if this change is even needed, as it's working without problem, but other people might stumble on this later as well.

oletf avatar Jul 31 '25 08:07 oletf

I also ran into this issue. Was this determined to strictly be a documentation issue?

tkoeppl avatar Nov 13 '25 15:11 tkoeppl

I had completely forgotten about this issue !

In the end I've just changed my C driver code to _IOW(IOCTL_MAGIC, NR_IO, u32) to keep using ioctl_write_int!() and to be sure that they're both using 4 bytes type. If I need u64 in the future I'll just use the more generic ioctl_write_ptr!().

I haven't got any more info nor feedback from this repo since my last message here, so still no confirmation if it was strictly documentation issue, or something else. I assume there were more important things to focus on, and the workaround is pretty easy to figure out.

oletf avatar Nov 13 '25 17:11 oletf