| .. | .. |
|---|
| 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 |
|---|