.. | .. |
---|
15 | 15 | #include <linux/err.h> |
---|
16 | 16 | #include <linux/ipc_namespace.h> |
---|
17 | 17 | |
---|
18 | | -#define IPCMNI 32768 /* <= MAX_INT limit for ipc arrays (including sysctl changes) */ |
---|
19 | | -#define SEQ_MULTIPLIER (IPCMNI) |
---|
| 18 | +/* |
---|
| 19 | + * The IPC ID contains 2 separate numbers - index and sequence number. |
---|
| 20 | + * By default, |
---|
| 21 | + * bits 0-14: index (32k, 15 bits) |
---|
| 22 | + * bits 15-30: sequence number (64k, 16 bits) |
---|
| 23 | + * |
---|
| 24 | + * When IPCMNI extension mode is turned on, the composition changes: |
---|
| 25 | + * bits 0-23: index (16M, 24 bits) |
---|
| 26 | + * bits 24-30: sequence number (128, 7 bits) |
---|
| 27 | + */ |
---|
| 28 | +#define IPCMNI_SHIFT 15 |
---|
| 29 | +#define IPCMNI_EXTEND_SHIFT 24 |
---|
| 30 | +#define IPCMNI_EXTEND_MIN_CYCLE (RADIX_TREE_MAP_SIZE * RADIX_TREE_MAP_SIZE) |
---|
| 31 | +#define IPCMNI (1 << IPCMNI_SHIFT) |
---|
| 32 | +#define IPCMNI_EXTEND (1 << IPCMNI_EXTEND_SHIFT) |
---|
| 33 | + |
---|
| 34 | +#ifdef CONFIG_SYSVIPC_SYSCTL |
---|
| 35 | +extern int ipc_mni; |
---|
| 36 | +extern int ipc_mni_shift; |
---|
| 37 | +extern int ipc_min_cycle; |
---|
| 38 | + |
---|
| 39 | +#define ipcmni_seq_shift() ipc_mni_shift |
---|
| 40 | +#define IPCMNI_IDX_MASK ((1 << ipc_mni_shift) - 1) |
---|
| 41 | + |
---|
| 42 | +#else /* CONFIG_SYSVIPC_SYSCTL */ |
---|
| 43 | + |
---|
| 44 | +#define ipc_mni IPCMNI |
---|
| 45 | +#define ipc_min_cycle ((int)RADIX_TREE_MAP_SIZE) |
---|
| 46 | +#define ipcmni_seq_shift() IPCMNI_SHIFT |
---|
| 47 | +#define IPCMNI_IDX_MASK ((1 << IPCMNI_SHIFT) - 1) |
---|
| 48 | +#endif /* CONFIG_SYSVIPC_SYSCTL */ |
---|
20 | 49 | |
---|
21 | 50 | void sem_init(void); |
---|
22 | 51 | void msg_init(void); |
---|
.. | .. |
---|
96 | 125 | #define IPC_MSG_IDS 1 |
---|
97 | 126 | #define IPC_SHM_IDS 2 |
---|
98 | 127 | |
---|
99 | | -#define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER) |
---|
100 | | -#define ipcid_to_seqx(id) ((id) / SEQ_MULTIPLIER) |
---|
101 | | -#define IPCID_SEQ_MAX min_t(int, INT_MAX/SEQ_MULTIPLIER, USHRT_MAX) |
---|
| 128 | +#define ipcid_to_idx(id) ((id) & IPCMNI_IDX_MASK) |
---|
| 129 | +#define ipcid_to_seqx(id) ((id) >> ipcmni_seq_shift()) |
---|
| 130 | +#define ipcid_seq_max() (INT_MAX >> ipcmni_seq_shift()) |
---|
102 | 131 | |
---|
103 | 132 | /* must be called with ids->rwsem acquired for writing */ |
---|
104 | 133 | int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int); |
---|
.. | .. |
---|
123 | 152 | if (ids->in_use == 0) |
---|
124 | 153 | return -1; |
---|
125 | 154 | |
---|
126 | | - if (ids->in_use == IPCMNI) |
---|
127 | | - return IPCMNI - 1; |
---|
| 155 | + if (ids->in_use == ipc_mni) |
---|
| 156 | + return ipc_mni - 1; |
---|
128 | 157 | |
---|
129 | 158 | return ids->max_idx; |
---|
130 | 159 | } |
---|
.. | .. |
---|
160 | 189 | } |
---|
161 | 190 | } |
---|
162 | 191 | |
---|
163 | | -#ifndef CONFIG_ARCH_WANT_IPC_PARSE_VERSION |
---|
164 | | -/* On IA-64, we always use the "64-bit version" of the IPC structures. */ |
---|
165 | | -# define ipc_parse_version(cmd) IPC_64 |
---|
166 | | -#else |
---|
| 192 | +#ifdef CONFIG_ARCH_WANT_IPC_PARSE_VERSION |
---|
167 | 193 | int ipc_parse_version(int *cmd); |
---|
168 | 194 | #endif |
---|
169 | 195 | |
---|
.. | .. |
---|
217 | 243 | void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids, |
---|
218 | 244 | void (*free)(struct ipc_namespace *, struct kern_ipc_perm *)); |
---|
219 | 245 | |
---|
| 246 | +static inline int sem_check_semmni(struct ipc_namespace *ns) { |
---|
| 247 | + /* |
---|
| 248 | + * Check semmni range [0, ipc_mni] |
---|
| 249 | + * semmni is the last element of sem_ctls[4] array |
---|
| 250 | + */ |
---|
| 251 | + return ((ns->sem_ctls[3] < 0) || (ns->sem_ctls[3] > ipc_mni)) |
---|
| 252 | + ? -ERANGE : 0; |
---|
| 253 | +} |
---|
| 254 | + |
---|
220 | 255 | #ifdef CONFIG_COMPAT |
---|
221 | 256 | #include <linux/compat.h> |
---|
222 | 257 | struct compat_ipc_perm { |
---|
.. | .. |
---|
237 | 272 | |
---|
238 | 273 | static inline int compat_ipc_parse_version(int *cmd) |
---|
239 | 274 | { |
---|
240 | | -#ifdef CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION |
---|
241 | 275 | int version = *cmd & IPC_64; |
---|
242 | 276 | *cmd &= ~IPC_64; |
---|
243 | 277 | return version; |
---|
244 | | -#else |
---|
245 | | - return IPC_64; |
---|
246 | | -#endif |
---|
247 | 278 | } |
---|
248 | | -#endif |
---|
249 | 279 | |
---|
250 | | -/* for __ARCH_WANT_SYS_IPC */ |
---|
251 | | -long ksys_semtimedop(int semid, struct sembuf __user *tsops, |
---|
252 | | - unsigned int nsops, |
---|
253 | | - const struct __kernel_timespec __user *timeout); |
---|
254 | | -long ksys_semget(key_t key, int nsems, int semflg); |
---|
255 | | -long ksys_semctl(int semid, int semnum, int cmd, unsigned long arg); |
---|
256 | | -long ksys_msgget(key_t key, int msgflg); |
---|
257 | | -long ksys_msgctl(int msqid, int cmd, struct msqid_ds __user *buf); |
---|
258 | | -long ksys_msgrcv(int msqid, struct msgbuf __user *msgp, size_t msgsz, |
---|
259 | | - long msgtyp, int msgflg); |
---|
260 | | -long ksys_msgsnd(int msqid, struct msgbuf __user *msgp, size_t msgsz, |
---|
261 | | - int msgflg); |
---|
262 | | -long ksys_shmget(key_t key, size_t size, int shmflg); |
---|
263 | | -long ksys_shmdt(char __user *shmaddr); |
---|
264 | | -long ksys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf); |
---|
265 | | - |
---|
266 | | -/* for CONFIG_ARCH_WANT_OLD_COMPAT_IPC */ |
---|
267 | | -long compat_ksys_semtimedop(int semid, struct sembuf __user *tsems, |
---|
268 | | - unsigned int nsops, |
---|
269 | | - const struct compat_timespec __user *timeout); |
---|
270 | | -#ifdef CONFIG_COMPAT |
---|
271 | | -long compat_ksys_semctl(int semid, int semnum, int cmd, int arg); |
---|
272 | | -long compat_ksys_msgctl(int msqid, int cmd, void __user *uptr); |
---|
| 280 | +long compat_ksys_old_semctl(int semid, int semnum, int cmd, int arg); |
---|
| 281 | +long compat_ksys_old_msgctl(int msqid, int cmd, void __user *uptr); |
---|
273 | 282 | long compat_ksys_msgrcv(int msqid, compat_uptr_t msgp, compat_ssize_t msgsz, |
---|
274 | 283 | compat_long_t msgtyp, int msgflg); |
---|
275 | 284 | long compat_ksys_msgsnd(int msqid, compat_uptr_t msgp, |
---|
276 | 285 | compat_ssize_t msgsz, int msgflg); |
---|
277 | | -long compat_ksys_shmctl(int shmid, int cmd, void __user *uptr); |
---|
278 | | -#endif /* CONFIG_COMPAT */ |
---|
| 286 | +long compat_ksys_old_shmctl(int shmid, int cmd, void __user *uptr); |
---|
| 287 | + |
---|
| 288 | +#endif |
---|
279 | 289 | |
---|
280 | 290 | #endif |
---|