Bug 4910

Summary: __IPC_64 bit is not expected by Kernel's SYSV *ctl fuctions
Product: uClibc Reporter: Sergey Koulik <skoulik>
Component: Standard ComplianceAssignee: unassigned
Status: NEW ---    
Severity: normal CC: skoulik, uclibc-cvs
Priority: P5    
Version: 0.9.32   
Target Milestone: ---   
Hardware: All   
OS: Linux   
Host: Target:
Build:

Description Sergey Koulik 2012-03-13 00:32:39 UTC
The following define in libc/misc/sysvipc/ipc.h effectively makes uclibc wrappers OR user's *ctl commands with 0x100 before passing to kernel. However this flag is not expected and not decoded on kernel side. The latter causes all user's commands passed to *ctl fuctions fail with EINVAL result.

#if __WORDSIZE == 32 || defined __alpha__ || defined __mips__
# define __IPC_64	0x100
#else
# define __IPC_64	0x0
#endif

The problem affects the following SYSV fuctions: semctl(), msgctl(), shmctl().
ipc/sem.c:
SYSCALL_DEFINE(semctl)(int semid, int semnum, int cmd, union semun arg)
{
[...]
   switch(cmd) { <-- 0x100 is not removed, goes directly to default case and returns -EINVAL

ipc/shm.c:
SYSCALL_DEFINE3(shmctl, int, shmid, int, cmd, struct shmid_ds __user *, buf)
{
[...]
   version = ipc_parse_version(&cmd); <-- 0x100 is removed iff __ARCH_WANT_IPC_PARSE_VERSION is defined (which is not always the case)

ipc/msg.c:
SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
{
[...]
   version = ipc_parse_version(&cmd); <-- 0x100 is removed iff __ARCH_WANT_IPC_PARSE_VERSION is defined (which is not always the case)

A quick and dirty fix is to define __IPC_64 0x0 unconditionally as modern kernels do not seem to use old 32 bit structures internally any more (checked 2.6 and 3.x trunk). So does user space.

A better solution is to look at kernel's version to check if 0x100 is actually needed.
Comment 1 Bernhard Reutner-Fischer 2015-04-29 10:50:44 UTC
It seems we have a __ASSUME_IPC64 in kernel-features.h
Can you please cook a patch perusing / tweaking this?