3 * Copyright (C) 1992 Krishna Balasubramanian
5 * Sep 1997 - Call suser() last after "normal" permission checks so we
6 * get BSD style process accounting right.
7 * Occurs in several places in the IPC code.
8 * Chris Evans, <chris@ferret.lmh.ox.ac.uk>
9 * Nov 1999 - ipc helper functions, unified SMP locking
10 * Manfred Spraul <manfreds@colorfullife.com>
13 #include <linux/config.h>
15 #include <linux/shm.h>
16 #include <linux/init.h>
17 #include <linux/msg.h>
18 #include <linux/smp_lock.h>
19 #include <linux/vmalloc.h>
20 #include <linux/malloc.h>
21 #include <linux/highuid.h>
23 #if defined(CONFIG_SYSVIPC)
27 void __init
ipc_init (void)
35 void __init
ipc_init_ids(struct ipc_ids
* ids
, int size
)
38 sema_init(&ids
->sem
,1);
47 int seq_limit
= INT_MAX
/SEQ_MULTIPLIER
;
48 if(seq_limit
> USHRT_MAX
)
49 ids
->seq_max
= USHRT_MAX
;
51 ids
->seq_max
= seq_limit
;
54 ids
->entries
= ipc_alloc(sizeof(struct ipc_id
)*size
);
56 if(ids
->entries
== NULL
) {
57 printk(KERN_ERR
"ipc_init_ids() failed, ipc service disabled.\n");
60 ids
->ary
= SPIN_LOCK_UNLOCKED
;
62 ids
->entries
[i
].p
= NULL
;
65 int ipc_findkey(struct ipc_ids
* ids
, key_t key
)
68 struct kern_ipc_perm
* p
;
70 for (id
= 0; id
<= ids
->max_id
; id
++) {
71 p
= ids
->entries
[id
].p
;
80 static int grow_ary(struct ipc_ids
* ids
, int newsize
)
88 if(newsize
<= ids
->size
)
91 new = ipc_alloc(sizeof(struct ipc_id
)*newsize
);
94 memcpy(new, ids
->entries
, sizeof(struct ipc_id
)*ids
->size
);
95 for(i
=ids
->size
;i
<newsize
;i
++) {
104 spin_unlock(&ids
->ary
);
105 ipc_free(old
, sizeof(struct ipc_id
)*i
);
109 int ipc_addid(struct ipc_ids
* ids
, struct kern_ipc_perm
* new, int size
)
113 size
= grow_ary(ids
,size
);
114 for (id
= 0; id
< size
; id
++) {
115 if(ids
->entries
[id
].p
== NULL
)
121 if (id
> ids
->max_id
)
124 new->cuid
= new->uid
= current
->euid
;
125 new->gid
= new->cgid
= current
->egid
;
127 new->seq
= ids
->seq
++;
128 if(ids
->seq
> ids
->seq_max
)
131 spin_lock(&ids
->ary
);
132 ids
->entries
[id
].p
= new;
136 struct kern_ipc_perm
* ipc_rmid(struct ipc_ids
* ids
, int id
)
138 struct kern_ipc_perm
* p
;
139 int lid
= id
% SEQ_MULTIPLIER
;
142 p
= ids
->entries
[lid
].p
;
143 ids
->entries
[lid
].p
= NULL
;
148 if (lid
== ids
->max_id
) {
153 } while (ids
->entries
[lid
].p
== NULL
);
159 void* ipc_alloc(int size
)
162 if(size
> PAGE_SIZE
) {
167 out
= kmalloc(size
, GFP_KERNEL
);
172 void ipc_free(void* ptr
, int size
)
174 if(size
> PAGE_SIZE
) {
184 * Check user, group, other permissions for access
185 * to ipc resources. return 0 if allowed
187 int ipcperms (struct kern_ipc_perm
*ipcp
, short flag
)
188 { /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */
189 int requested_mode
, granted_mode
;
191 requested_mode
= (flag
>> 6) | (flag
>> 3) | flag
;
192 granted_mode
= ipcp
->mode
;
193 if (current
->euid
== ipcp
->cuid
|| current
->euid
== ipcp
->uid
)
195 else if (in_group_p(ipcp
->cgid
) || in_group_p(ipcp
->gid
))
197 /* is there some bit set in requested_mode but not in granted_mode? */
198 if ((requested_mode
& ~granted_mode
& 0007) &&
199 !capable(CAP_IPC_OWNER
))
206 * Functions to convert between the kern_ipc_perm structure and the
207 * old/new ipc_perm structures
210 void kernel_to_ipc64_perm (struct kern_ipc_perm
*in
, struct ipc64_perm
*out
)
215 out
->cuid
= in
->cuid
;
216 out
->cgid
= in
->cgid
;
217 out
->mode
= in
->mode
;
221 void ipc64_perm_to_ipc_perm (struct ipc64_perm
*in
, struct ipc_perm
*out
)
224 out
->uid
= NEW_TO_OLD_UID(in
->uid
);
225 out
->gid
= NEW_TO_OLD_GID(in
->gid
);
226 out
->cuid
= NEW_TO_OLD_UID(in
->cuid
);
227 out
->cgid
= NEW_TO_OLD_GID(in
->cgid
);
228 out
->mode
= in
->mode
;
232 int ipc_parse_version (int *cmd
)
244 * Dummy functions when SYSV IPC isn't configured
252 int shm_swap (int prio
, int gfp_mask
)
257 asmlinkage
long sys_semget (key_t key
, int nsems
, int semflg
)
262 asmlinkage
long sys_semop (int semid
, struct sembuf
*sops
, unsigned nsops
)
267 asmlinkage
long sys_semctl (int semid
, int semnum
, int cmd
, union semun arg
)
272 asmlinkage
long sys_msgget (key_t key
, int msgflg
)
277 asmlinkage
long sys_msgsnd (int msqid
, struct msgbuf
*msgp
, size_t msgsz
, int msgflg
)
282 asmlinkage
long sys_msgrcv (int msqid
, struct msgbuf
*msgp
, size_t msgsz
, long msgtyp
,
288 asmlinkage
long sys_msgctl (int msqid
, int cmd
, struct msqid_ds
*buf
)
293 asmlinkage
long sys_shmget (key_t key
, size_t size
, int shmflag
)
298 asmlinkage
long sys_shmat (int shmid
, char *shmaddr
, int shmflg
, ulong
*addr
)
303 asmlinkage
long sys_shmdt (char *shmaddr
)
308 asmlinkage
long sys_shmctl (int shmid
, int cmd
, struct shmid_ds
*buf
)
313 void shm_unuse(swp_entry_t entry
, struct page
*page
)
317 int map_zero_setup(struct vm_area_struct
*vma
)
322 #endif /* CONFIG_SYSVIPC */