1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #ifndef _IPC_IMPL_H 27 #define _IPC_IMPL_H 28 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 #include <sys/types.h> 32 #include <sys/ipc.h> 33 #include <sys/mutex.h> 34 #include <sys/ipc_rctl.h> 35 #include <sys/project.h> 36 #include <sys/zone.h> 37 #include <sys/sysmacros.h> 38 #include <sys/avl.h> 39 #include <sys/id_space.h> 40 #include <sys/cred.h> 41 #include <sys/list.h> 42 43 #ifdef __cplusplus 44 extern "C" { 45 #endif 46 47 typedef uint64_t ipc_time_t; 48 49 /* For xxxctl64 */ 50 #define IPC_SET64 13 /* set options */ 51 #define IPC_STAT64 14 /* get options */ 52 53 /* 54 * There are two versions of the userland ipc_perm structure: 55 * ipc_perm - the version used by user applications and by the kernel 56 * when the user and kernel data models match (in ipc.h) 57 * ipc_perm32 - the 64-bit kernel's view of a 32-bit struct ipc_perm 58 */ 59 #if defined(_SYSCALL32) 60 struct ipc_perm32 { 61 uid32_t uid; /* owner's user id */ 62 gid32_t gid; /* owner's group id */ 63 uid32_t cuid; /* creator's user id */ 64 gid32_t cgid; /* creator's group id */ 65 mode32_t mode; /* access modes */ 66 uint32_t seq; /* slot usage sequence number */ 67 key32_t key; /* key */ 68 int32_t pad[4]; /* reserve area */ 69 }; 70 #endif /* _SYSCALL32 */ 71 72 /* 73 * This is the ipc_perm equivalent used in the xxxid_ds64 structures. 74 * It, like the structures it is used in, is intended only for use in 75 * communication between the kernel and user programs, and has the same 76 * layout across all data models. 77 * 78 * The xxxid_ds64 structures rely on ipc_perm64 being a multiple of 79 * 8 bytes so subsequent fields are 64-bit aligned on x86. 80 */ 81 typedef struct ipc_perm64 { 82 uid_t ipcx_uid; /* owner's user id */ 83 gid_t ipcx_gid; /* owner's group id */ 84 uid_t ipcx_cuid; /* creator's user id */ 85 gid_t ipcx_cgid; /* creator's group id */ 86 mode_t ipcx_mode; /* access modes */ 87 key_t ipcx_key; /* key */ 88 projid_t ipcx_projid; /* allocating project id */ 89 zoneid_t ipcx_zoneid; /* creator's zone id */ 90 } ipc_perm64_t; 91 92 /* 93 * These are versions of xxxid_ds which are intended only for use in 94 * communication between the kernel and user programs, and therefore 95 * have the same layout across all data models. Omitted are all 96 * implementation-specific fields which would be of no use to user 97 * programs. 98 */ 99 struct shmid_ds64 { 100 ipc_perm64_t shmx_perm; /* operation permission struct */ 101 pid_t shmx_lpid; /* pid of last shmop */ 102 pid_t shmx_cpid; /* pid of creator */ 103 uint64_t shmx_segsz; /* size of segment in bytes */ 104 uint64_t shmx_nattch; /* # of attaches */ 105 uint64_t shmx_cnattch; /* # of ISM attaches */ 106 uint64_t shmx_lkcnt; /* lock count ??? */ 107 ipc_time_t shmx_atime; /* last shmat time */ 108 ipc_time_t shmx_dtime; /* last shmdt time */ 109 ipc_time_t shmx_ctime; /* last change time */ 110 }; 111 112 struct semid_ds64 { 113 ipc_perm64_t semx_perm; /* operation permission struct */ 114 ushort_t semx_nsems; /* # of semaphores in set */ 115 ushort_t _semx_pad[3]; /* pad to 8-byte multiple */ 116 ipc_time_t semx_otime; /* last semop time */ 117 ipc_time_t semx_ctime; /* last change time */ 118 }; 119 120 struct msqid_ds64 { 121 ipc_perm64_t msgx_perm; /* operation permission struct */ 122 uint64_t msgx_cbytes; /* current # bytes on q */ 123 uint64_t msgx_qnum; /* # of messages on q */ 124 uint64_t msgx_qbytes; /* max # of bytes on q */ 125 pid_t msgx_lspid; /* pid of last msgsnd */ 126 pid_t msgx_lrpid; /* pid of last msgrcv */ 127 ipc_time_t msgx_stime; /* last msgsnd time */ 128 ipc_time_t msgx_rtime; /* last msgrcv time */ 129 ipc_time_t msgx_ctime; /* last change time */ 130 }; 131 132 #ifdef _KERNEL 133 134 /* 135 * Implementation macros 136 */ 137 #define IPC_FREE(x) (((x)->ipc_mode & IPC_ALLOC) == 0) 138 139 #define IPC_SEQ_BITS 7 140 #define IPC_SEQ_MASK ((1 << IPC_SEQ_BITS) - 1) 141 #define IPC_SEQ_SHIFT (31 - IPC_SEQ_BITS) 142 #define IPC_INDEX_MASK ((1 << IPC_SEQ_SHIFT) - 1) 143 #define IPC_SEQ(x) ((unsigned int)(x) >> IPC_SEQ_SHIFT) 144 #define IPC_INDEX(x) ((unsigned int)(x) & IPC_INDEX_MASK) 145 146 #define IPC_IDS_MIN (PAGESIZE / 64) /* starting # of entries */ 147 #define IPC_IDS_MAX (1 << IPC_SEQ_SHIFT) /* maximum # of entries */ 148 #define IPC_ID_INVAL UINT_MAX 149 150 #define IPC_PROJ_USAGE(p, s) \ 151 (*(rctl_qty_t *)(((char *)&p->ipc_proj->kpj_data.kpd_ipc) + \ 152 s->ipcs_rctlofs)) 153 #define IPC_ZONE_USAGE(p, s) \ 154 (*(rctl_qty_t *)(((char *)&p->ipc_zone->zone_ipc) + \ 155 s->ipcs_rctlofs)) 156 #define IPC_LOCKED(s, o) \ 157 MUTEX_HELD(&s->ipcs_table[IPC_INDEX(o->ipc_id)].ipct_lock) 158 159 /* 160 * The kernel's ipc_perm structure. 161 */ 162 typedef struct kipc_perm { 163 avl_node_t ipc_avl; /* avl node if key is non-private */ 164 list_node_t ipc_list; /* list node in list of all ids */ 165 uint_t ipc_ref; /* reference count */ 166 uid_t ipc_uid; /* owner's user id */ 167 gid_t ipc_gid; /* owner's group id */ 168 uid_t ipc_cuid; /* creator's user id */ 169 gid_t ipc_cgid; /* creator's group id */ 170 mode_t ipc_mode; /* access modes */ 171 key_t ipc_key; /* key */ 172 kproject_t *ipc_proj; /* creator's project */ 173 uint_t ipc_id; /* id */ 174 zoneid_t ipc_zoneid; /* creator's zone id */ 175 zone_t *ipc_zone; /* creator's zone */ 176 } kipc_perm_t; 177 178 typedef struct ipc_slot { 179 kmutex_t ipct_lock; /* bucket lock */ 180 kipc_perm_t *ipct_data; /* data */ 181 uint_t ipct_seq; /* sequence number */ 182 struct ipc_slot *ipct_chain; /* for stale arrays */ 183 char ipct_pad[64 - sizeof (kmutex_t) - 3 * sizeof (void *)]; 184 } ipc_slot_t; 185 186 typedef void(ipc_func_t)(kipc_perm_t *); 187 188 typedef struct ipc_service { 189 kmutex_t ipcs_lock; /* lock for (de)allocation, keys */ 190 avl_tree_t ipcs_keys; /* objects sorted by key */ 191 ipc_slot_t *ipcs_table; /* table of objects */ 192 uint_t ipcs_tabsz; /* size of table */ 193 uint_t ipcs_count; /* # of objects allocated */ 194 rctl_hndl_t ipcs_proj_rctl; /* id limiting rctl handle */ 195 rctl_hndl_t ipcs_zone_rctl; /* id limiting rctl handle */ 196 size_t ipcs_rctlofs; /* offset in kproject_data_t */ 197 id_space_t *ipcs_ids; /* id space for objects */ 198 size_t ipcs_ssize; /* object size (for allocation) */ 199 ipc_func_t *ipcs_dtor; /* object destructor */ 200 ipc_func_t *ipcs_rmid; /* object removal */ 201 list_t ipcs_usedids; /* list of allocated ids */ 202 int ipcs_atype; /* audit type (see c2/audit.h) */ 203 } ipc_service_t; 204 205 int ipcperm_access(kipc_perm_t *, int, cred_t *); 206 int ipcperm_set(ipc_service_t *, struct cred *, kipc_perm_t *, 207 struct ipc_perm *, model_t); 208 void ipcperm_stat(struct ipc_perm *, kipc_perm_t *, model_t); 209 int ipcperm_set64(ipc_service_t *, struct cred *, kipc_perm_t *, 210 ipc_perm64_t *); 211 void ipcperm_stat64(ipc_perm64_t *, kipc_perm_t *); 212 213 ipc_service_t *ipcs_create(const char *, rctl_hndl_t, rctl_hndl_t, size_t, 214 ipc_func_t *, ipc_func_t *, int, size_t); 215 void ipcs_destroy(ipc_service_t *); 216 void ipcs_lock(ipc_service_t *); 217 void ipcs_unlock(ipc_service_t *); 218 219 kmutex_t *ipc_lock(ipc_service_t *, int); 220 kmutex_t *ipc_relock(ipc_service_t *, int, kmutex_t *); 221 kmutex_t *ipc_lookup(ipc_service_t *, int, kipc_perm_t **); 222 223 void ipc_hold(ipc_service_t *, kipc_perm_t *); 224 void ipc_rele(ipc_service_t *, kipc_perm_t *); 225 void ipc_rele_locked(ipc_service_t *, kipc_perm_t *); 226 227 int ipc_get(ipc_service_t *, key_t, int, kipc_perm_t **, kmutex_t **); 228 int ipc_commit_begin(ipc_service_t *, key_t, int, kipc_perm_t *); 229 kmutex_t *ipc_commit_end(ipc_service_t *, kipc_perm_t *); 230 void ipc_cleanup(ipc_service_t *, kipc_perm_t *); 231 232 int ipc_rmid(ipc_service_t *, int, cred_t *); 233 int ipc_ids(ipc_service_t *, int *, uint_t, uint_t *); 234 235 void ipc_remove_zone(ipc_service_t *, zoneid_t); 236 237 #else /* _KERNEL */ 238 239 int msgctl64(int, int, struct msqid_ds64 *); 240 int semctl64(int, int, int, ...); 241 int shmctl64(int, int, struct shmid_ds64 *); 242 243 #endif /* _KERNEL */ 244 245 246 #ifdef __cplusplus 247 } 248 #endif 249 250 #endif /* _IPC_IMPL_H */ 251