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
)
165 out
= kmalloc(size
, GFP_KERNEL
);
169 void ipc_free(void* ptr
, int size
)
178 * Check user, group, other permissions for access
179 * to ipc resources. return 0 if allowed
181 int ipcperms (struct kern_ipc_perm
*ipcp
, short flag
)
182 { /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */
183 int requested_mode
, granted_mode
;
185 requested_mode
= (flag
>> 6) | (flag
>> 3) | flag
;
186 granted_mode
= ipcp
->mode
;
187 if (current
->euid
== ipcp
->cuid
|| current
->euid
== ipcp
->uid
)
189 else if (in_group_p(ipcp
->cgid
) || in_group_p(ipcp
->gid
))
191 /* is there some bit set in requested_mode but not in granted_mode? */
192 if ((requested_mode
& ~granted_mode
& 0007) &&
193 !capable(CAP_IPC_OWNER
))
200 * Functions to convert between the kern_ipc_perm structure and the
201 * old/new ipc_perm structures
204 void kernel_to_ipc64_perm (struct kern_ipc_perm
*in
, struct ipc64_perm
*out
)
209 out
->cuid
= in
->cuid
;
210 out
->cgid
= in
->cgid
;
211 out
->mode
= in
->mode
;
215 void ipc64_perm_to_ipc_perm (struct ipc64_perm
*in
, struct ipc_perm
*out
)
218 out
->uid
= NEW_TO_OLD_UID(in
->uid
);
219 out
->gid
= NEW_TO_OLD_GID(in
->gid
);
220 out
->cuid
= NEW_TO_OLD_UID(in
->cuid
);
221 out
->cgid
= NEW_TO_OLD_GID(in
->cgid
);
222 out
->mode
= in
->mode
;
226 int ipc_parse_version (int *cmd
)
238 * Dummy functions when SYSV IPC isn't configured
246 int shm_swap (int prio
, int gfp_mask
)
251 asmlinkage
long sys_semget (key_t key
, int nsems
, int semflg
)
256 asmlinkage
long sys_semop (int semid
, struct sembuf
*sops
, unsigned nsops
)
261 asmlinkage
long sys_semctl (int semid
, int semnum
, int cmd
, union semun arg
)
266 asmlinkage
long sys_msgget (key_t key
, int msgflg
)
271 asmlinkage
long sys_msgsnd (int msqid
, struct msgbuf
*msgp
, size_t msgsz
, int msgflg
)
276 asmlinkage
long sys_msgrcv (int msqid
, struct msgbuf
*msgp
, size_t msgsz
, long msgtyp
,
282 asmlinkage
long sys_msgctl (int msqid
, int cmd
, struct msqid_ds
*buf
)
287 asmlinkage
long sys_shmget (key_t key
, size_t size
, int shmflag
)
292 asmlinkage
long sys_shmat (int shmid
, char *shmaddr
, int shmflg
, ulong
*addr
)
297 asmlinkage
long sys_shmdt (char *shmaddr
)
302 asmlinkage
long sys_shmctl (int shmid
, int cmd
, struct shmid_ds
*buf
)
307 void shm_unuse(swp_entry_t entry
, struct page
*page
)
311 int map_zero_setup(struct vm_area_struct
*vma
)
316 #endif /* CONFIG_SYSVIPC */