On Wed, Aug 28, 2019 at 02:06:50PM +0200, David Sterba wrote: > On Thu, Aug 15, 2019 at 02:04:06PM -0700, Omar Sandoval wrote: > > #define BTRFS_IOC_SEND_32 _IOW(BTRFS_IOCTL_MAGIC, 38, \ > > struct btrfs_ioctl_send_args_32) > > + > > +struct btrfs_ioctl_compressed_pwrite_args_32 { > > + __u64 offset; /* in */ > > + __u32 compressed_len; /* in */ > > + __u32 orig_len; /* in */ > > + __u32 compress_type; /* in */ > > + __u32 reserved[9]; > > + compat_uptr_t buf; /* in */ > > +} __attribute__ ((__packed__)); > > + > > +#define BTRFS_IOC_COMPRESSED_PWRITE_32 _IOW(BTRFS_IOCTL_MAGIC, 63, \ > > + struct btrfs_ioctl_compressed_pwrite_args_32) > > Note that the _32 is a workaround for a mistake in the send ioctl > definitions that slipped trhough. Any pointer in the structure changes > the ioctl number on 32bit and 64bit. > > But as the raw data ioctl is new there's point to copy the mistake. The > alignment and width can be forced eg. like > > > + void __user *buf; /* in */ > > union { > void __user *buf; > __u64 __buf_alignment; > }; > > This allows to user buf as a buffer without casts to a intermediate > type.
I don't think this works on big-endian architectures. Let's say a 32-bit application does: struct btrfs_ioctl_compressed_pwrite_args_32 { .buf = 0x12345678, }; The pointer will be in the first 4 bytes of the 8-byte union: 0 1 2 3 4 5 6 7 0x12 0x34 0x56 0x78 0x00 0x00 0x00 0x00 But, the 64-bit kernel will read buf as 0x1234567800000000. Let me know if I messed up my analysis, but I think we need the compat stuff.