Structure mapping

Marty Jack martyj19 at
Sun Feb 6 14:41:09 PST 2011

Okay, small digression to explain the problem and then we're back to doing a window system.

>>> struct drm_version {
>>>        int version_major;        /**< Major version */
>>>        int version_minor;        /**< Minor version */
>>>        int version_patchlevel;   /**< Patch level */
>>>        size_t name_len;          /**< Length of name buffer */
>>>        char *name;       /**< Name of driver */
>>>        size_t date_len;          /**< Length of date buffer */
>>>        char *date;       /**< User-space buffer to hold date */
>>>        size_t desc_len;          /**< Length of desc buffer */
>>>        char *desc;       /**< User-space buffer to hold desc */
>>> };

We have int, which will probably be 32 bits on a 32 bit machine and probably 32 or maybe 64 bits on a 64 bit machine, but C doesn't define how big any type is other than char.

Then we have size_t, which is the input to malloc and the result of strlen, so large enough to hold the size of anything, so will be the same size as a pointer: 32 bits on 32-bit machine, 64 bits on 64-bit machine.

So mapping this on the two architectures, we get all 32's on the 32 bit machine, and quite a few 64s on the 64 bit machine.  Maybe the 64s only have to be 32 bit aligned, maybe they have to be 64 bit aligned.  The hardware manual will tell us.  So we may have unused space in the structure in addition to different sizes.

Now if this is going into an ioctl, we have to either read or write the buffers.  So the ioctl has to be totally correct about what offset in the structure "desc_len" and "desc" are going to be at and their size.  Therefore it has to know if the calling process has 32 bit structure mapping or 64 bit structure mapping, in the case where you allow both a 32 bit program and a 64 bit program on the same machine to call into a 64 bit kernel.  Moreover, it is in kernel mode.  So it has to probe the ioctl argument itself and the buffers it is going to read and write to make sure they are accessible.  Otherwise, it may take a segment violation in kernel mode and crash the system, or it may write memory that the user mode program didn't have access to and be a security hole.  If "desc_len" is 50, we check up to 50 bytes starting at the value of "desc" to see if it is writable in user mode before we return the value there.

The same is true of a system call like write(2), but there you have all the values in the argument list, so there's no structure mapping issue.

More information about the wayland-devel mailing list