1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
| /*
| * sys_ipc() is the old de-multiplexer for the SysV IPC calls.
| *
| * This is really horribly ugly, and new architectures should just wire up
| * the individual syscalls instead.
| */
| #include <linux/unistd.h>
|
| #ifdef __ARCH_WANT_SYS_IPC
| #include <linux/errno.h>
| #include <linux/ipc.h>
| #include <linux/shm.h>
| #include <linux/syscalls.h>
| #include <linux/uaccess.h>
|
| SYSCALL_DEFINE6(ipc, unsigned int, call, int, first, unsigned long, second,
| unsigned long, third, void __user *, ptr, long, fifth)
| {
| int version, ret;
|
| version = call >> 16; /* hack for backward compatibility */
| call &= 0xffff;
|
| switch (call) {
| case SEMOP:
| return sys_semtimedop(first, (struct sembuf __user *)ptr,
| second, NULL);
| case SEMTIMEDOP:
| return sys_semtimedop(first, (struct sembuf __user *)ptr,
| second,
| (const struct timespec __user *)fifth);
|
| case SEMGET:
| return sys_semget(first, second, third);
| case SEMCTL: {
| unsigned long arg;
| if (!ptr)
| return -EINVAL;
| if (get_user(arg, (unsigned long __user *) ptr))
| return -EFAULT;
| return sys_semctl(first, second, third, arg);
| }
|
| case MSGSND:
| return sys_msgsnd(first, (struct msgbuf __user *) ptr,
| second, third);
| case MSGRCV:
| switch (version) {
| case 0: {
| struct ipc_kludge tmp;
| if (!ptr)
| return -EINVAL;
|
| if (copy_from_user(&tmp,
| (struct ipc_kludge __user *) ptr,
| sizeof(tmp)))
| return -EFAULT;
| return sys_msgrcv(first, tmp.msgp, second,
| tmp.msgtyp, third);
| }
| default:
| return sys_msgrcv(first,
| (struct msgbuf __user *) ptr,
| second, fifth, third);
| }
| case MSGGET:
| return sys_msgget((key_t) first, second);
| case MSGCTL:
| return sys_msgctl(first, second, (struct msqid_ds __user *)ptr);
|
| case SHMAT:
| switch (version) {
| default: {
| unsigned long raddr;
| ret = do_shmat(first, (char __user *)ptr,
| second, &raddr, SHMLBA);
| if (ret)
| return ret;
| return put_user(raddr, (unsigned long __user *) third);
| }
| case 1:
| /*
| * This was the entry point for kernel-originating calls
| * from iBCS2 in 2.2 days.
| */
| return -EINVAL;
| }
| case SHMDT:
| return sys_shmdt((char __user *)ptr);
| case SHMGET:
| return sys_shmget(first, second, third);
| case SHMCTL:
| return sys_shmctl(first, second,
| (struct shmid_ds __user *) ptr);
| default:
| return -ENOSYS;
| }
| }
| #endif
|
|