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 (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
26 /* All Rights Reserved */
27
28
29 /*
30 * Common Inter-Process Communication routines.
31 *
32 * Overview
33 * --------
34 *
35 * The System V inter-process communication (IPC) facilities provide
36 * three services, message queues, semaphore arrays, and shared memory
37 * segments, which are mananged using filesystem-like namespaces.
38 * Unlike a filesystem, these namespaces aren't mounted and accessible
39 * via a path -- a special API is used to interact with the different
40 * facilities (nothing precludes a VFS-based interface, but the
41 * standards require the special APIs). Furthermore, these special
42 * APIs don't use file descriptors, nor do they have an equivalent.
1200 service->ipcs_table[index].ipct_data = NULL;
1201
1202 if (perm->ipc_key != IPC_PRIVATE)
1203 avl_remove(&service->ipcs_keys, perm);
1204 list_remove(&service->ipcs_usedids, perm);
1205 perm->ipc_mode &= ~IPC_ALLOC;
1206
1207 id_free(service->ipcs_ids, index);
1208
1209 if (service->ipcs_table[index].ipct_seq++ == IPC_SEQ_MASK)
1210 service->ipcs_table[index].ipct_seq = 0;
1211 service->ipcs_count--;
1212 ASSERT(IPC_PROJ_USAGE(perm, service) > 0);
1213 ASSERT(IPC_ZONE_USAGE(perm, service) > 0);
1214 IPC_PROJ_USAGE(perm, service) -= 1;
1215 IPC_ZONE_USAGE(perm, service) -= 1;
1216 ASSERT(service->ipcs_count || ((IPC_PROJ_USAGE(perm, service) == 0) &&
1217 (IPC_ZONE_USAGE(perm, service) == 0)));
1218 }
1219
1220
1221 /*
1222 * Common code to perform an IPC_RMID. Returns an errno value on
1223 * failure, 0 on success.
1224 */
1225 int
1226 ipc_rmid(ipc_service_t *service, int id, cred_t *cr)
1227 {
1228 kipc_perm_t *perm;
1229 kmutex_t *lock;
1230
1231 mutex_enter(&service->ipcs_lock);
1232
1233 lock = ipc_lookup(service, id, &perm);
1234 if (lock == NULL) {
1235 mutex_exit(&service->ipcs_lock);
1236 return (EINVAL);
1237 }
1238
1239 ASSERT(service->ipcs_count > 0);
1240
1241 if (secpolicy_ipc_owner(cr, perm) != 0) {
1242 mutex_exit(lock);
1243 mutex_exit(&service->ipcs_lock);
1244 return (EPERM);
1245 }
1246
1247 /*
1248 * Nothing can fail from this point on.
1249 */
1250 ipc_remove(service, perm);
1251 mutex_exit(&service->ipcs_lock);
1252
1253 /* perform any per-service removal actions */
1254 service->ipcs_rmid(perm);
1255
1256 ipc_rele(service, perm);
1257
1258 return (0);
1259 }
1260
1261 /*
1262 * Implementation for shmids, semids, and msgids. buf is the address
1263 * of the user buffer, nids is the size, and pnids is a pointer to
1264 * where we write the actual number of ids that [would] have been
1265 * copied out.
1266 */
1267 int
1268 ipc_ids(ipc_service_t *service, int *buf, uint_t nids, uint_t *pnids)
1269 {
1270 kipc_perm_t *perm;
1271 size_t idsize = 0;
1272 int error = 0;
1273 int idcount;
1274 int *ids;
1275 int numids = 0;
1276 zoneid_t zoneid = getzoneid();
1277 int global = INGLOBALZONE(curproc);
|
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 (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2016 Joyent, Inc.
24 */
25
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28
29
30 /*
31 * Common Inter-Process Communication routines.
32 *
33 * Overview
34 * --------
35 *
36 * The System V inter-process communication (IPC) facilities provide
37 * three services, message queues, semaphore arrays, and shared memory
38 * segments, which are mananged using filesystem-like namespaces.
39 * Unlike a filesystem, these namespaces aren't mounted and accessible
40 * via a path -- a special API is used to interact with the different
41 * facilities (nothing precludes a VFS-based interface, but the
42 * standards require the special APIs). Furthermore, these special
43 * APIs don't use file descriptors, nor do they have an equivalent.
1201 service->ipcs_table[index].ipct_data = NULL;
1202
1203 if (perm->ipc_key != IPC_PRIVATE)
1204 avl_remove(&service->ipcs_keys, perm);
1205 list_remove(&service->ipcs_usedids, perm);
1206 perm->ipc_mode &= ~IPC_ALLOC;
1207
1208 id_free(service->ipcs_ids, index);
1209
1210 if (service->ipcs_table[index].ipct_seq++ == IPC_SEQ_MASK)
1211 service->ipcs_table[index].ipct_seq = 0;
1212 service->ipcs_count--;
1213 ASSERT(IPC_PROJ_USAGE(perm, service) > 0);
1214 ASSERT(IPC_ZONE_USAGE(perm, service) > 0);
1215 IPC_PROJ_USAGE(perm, service) -= 1;
1216 IPC_ZONE_USAGE(perm, service) -= 1;
1217 ASSERT(service->ipcs_count || ((IPC_PROJ_USAGE(perm, service) == 0) &&
1218 (IPC_ZONE_USAGE(perm, service) == 0)));
1219 }
1220
1221 /*
1222 * Perform actual IPC_RMID, either via ipc_rmid or due to a delayed *_RMID.
1223 */
1224 void
1225 ipc_rmsvc(ipc_service_t *service, kipc_perm_t *perm)
1226 {
1227 ASSERT(service->ipcs_count > 0);
1228 ASSERT(MUTEX_HELD(&service->ipcs_lock));
1229
1230 ipc_remove(service, perm);
1231 mutex_exit(&service->ipcs_lock);
1232
1233 /* perform any per-service removal actions */
1234 service->ipcs_rmid(perm);
1235
1236 ipc_rele(service, perm);
1237 }
1238
1239 /*
1240 * Common code to perform an IPC_RMID. Returns an errno value on
1241 * failure, 0 on success.
1242 */
1243 int
1244 ipc_rmid(ipc_service_t *service, int id, cred_t *cr)
1245 {
1246 kipc_perm_t *perm;
1247 kmutex_t *lock;
1248
1249 mutex_enter(&service->ipcs_lock);
1250
1251 lock = ipc_lookup(service, id, &perm);
1252 if (lock == NULL) {
1253 mutex_exit(&service->ipcs_lock);
1254 return (EINVAL);
1255 }
1256
1257 ASSERT(service->ipcs_count > 0);
1258
1259 if (secpolicy_ipc_owner(cr, perm) != 0) {
1260 mutex_exit(lock);
1261 mutex_exit(&service->ipcs_lock);
1262 return (EPERM);
1263 }
1264
1265 /*
1266 * Nothing can fail from this point on.
1267 */
1268 ipc_rmsvc(service, perm);
1269
1270 return (0);
1271 }
1272
1273 /*
1274 * Implementation for shmids, semids, and msgids. buf is the address
1275 * of the user buffer, nids is the size, and pnids is a pointer to
1276 * where we write the actual number of ids that [would] have been
1277 * copied out.
1278 */
1279 int
1280 ipc_ids(ipc_service_t *service, int *buf, uint_t nids, uint_t *pnids)
1281 {
1282 kipc_perm_t *perm;
1283 size_t idsize = 0;
1284 int error = 0;
1285 int idcount;
1286 int *ids;
1287 int numids = 0;
1288 zoneid_t zoneid = getzoneid();
1289 int global = INGLOBALZONE(curproc);
|