The following sections discuss system call issues.
The EOVERFLOW return value is returned from a system call whenever one or more fields of the data structure used to pass information out of the kernel is too small to hold the value.
A number of 32-bit system calls now return EOVERFLOW when faced with large objects on the 64-bit kernel. While this was already true when dealing with large files, the fact that daddr_t, dev_t, time_t, and its derivative types struct timeval and timespec_t now contain 64-bit quantities might mean more EOVERFLOW return values are observed by 32-bit applications.
Some ioctl(2) calls have been rather poorly specified in the past. Unfortunately, ioctl() is completely devoid of compile-time type checking; therefore, it can be a source of bugs that are difficult to track down.
Consider two ioctl() calls – one that manipulates a pointer to a 32-bit quantity (IOP32), the other that manipulates a pointer to a long quantity (IOPLONG).
The following code sample works as part of a 32-bit application when it is compiled:
int a, d; long b; ... if (ioctl(d, IOP32, &b) == -1) return (errno); if (ioctl(d, IOPLONG, &a) == -1) return (errno);
In a 64-bit application, the preceding ioctl() calls succeed but do not work correctly:
The first ioctl() call passes a container that is too big, and on a big-endian implementation, the kernel will copy in or copy out from the wrong part of the 64-bit word. Even on a little-endian implementation, the container probably contains stack garbage in the upper 32 bits.
The second ioctl() call will copy in or copy out too much, either reading an incorrect value, or corrupting adjacent variables on the user stack.