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