1/* $FreeBSD: head/sys/kern/sysv_shm.c 82607 2001-08-31 00:02:18Z dillon $ */ |
2/* $NetBSD: sysv_shm.c,v 1.23 1994/07/04 23:25:12 glass Exp $ */ 3 4/* 5 * Copyright (c) 1994 Adam Glass and Charles Hannum. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: --- 218 unchanged lines hidden (view full) --- 228} 229 230#ifndef _SYS_SYSPROTO_H_ 231struct shmdt_args { 232 void *shmaddr; 233}; 234#endif 235 |
236/* 237 * MPSAFE 238 */ |
239int 240shmdt(p, uap) 241 struct proc *p; 242 struct shmdt_args *uap; 243{ 244 struct shmmap_state *shmmap_s; 245 int i; |
246 int error = 0; |
247 |
248 mtx_lock(&Giant); |
249 |
250 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { 251 error = ENOSYS; 252 goto done2; 253 } 254 |
255 shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm; |
256 if (shmmap_s == NULL) { 257 error = EINVAL; 258 goto done2; 259 } 260 for (i = 0; i < shminfo.shmseg; i++, shmmap_s++) { |
261 if (shmmap_s->shmid != -1 && |
262 shmmap_s->va == (vm_offset_t)uap->shmaddr) { |
263 break; |
264 } 265 } 266 if (i == shminfo.shmseg) { 267 error = EINVAL; 268 goto done2; 269 } |
270 error = shm_delete_mapping(p, shmmap_s); |
271done2: 272 mtx_unlock(&Giant); 273 return (error); |
274} 275 276#ifndef _SYS_SYSPROTO_H_ 277struct shmat_args { 278 int shmid; 279 void *shmaddr; 280 int shmflg; 281}; 282#endif 283 |
284/* 285 * MPSAFE 286 */ |
287int 288shmat(p, uap) 289 struct proc *p; 290 struct shmat_args *uap; 291{ |
292 int i, flags; |
293 struct shmid_ds *shmseg; 294 struct shmmap_state *shmmap_s = NULL; 295 struct shm_handle *shm_handle; 296 vm_offset_t attach_va; 297 vm_prot_t prot; 298 vm_size_t size; 299 int rv; |
300 int error = 0; |
301 |
302 mtx_lock(&Giant); |
303 |
304 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { 305 error = ENOSYS; 306 goto done2; 307 } |
308 309 shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm; 310 if (shmmap_s == NULL) { 311 size = shminfo.shmseg * sizeof(struct shmmap_state); 312 shmmap_s = malloc(size, M_SHM, M_WAITOK); 313 for (i = 0; i < shminfo.shmseg; i++) 314 shmmap_s[i].shmid = -1; 315 p->p_vmspace->vm_shm = (caddr_t)shmmap_s; 316 } 317 shmseg = shm_find_segment_by_shmid(uap->shmid); |
318 if (shmseg == NULL) { 319 error = EINVAL; 320 goto done2; 321 } |
322 error = ipcperm(p, &shmseg->shm_perm, 323 (uap->shmflg & SHM_RDONLY) ? IPC_R : IPC_R|IPC_W); 324 if (error) |
325 goto done2; |
326 for (i = 0; i < shminfo.shmseg; i++) { 327 if (shmmap_s->shmid == -1) 328 break; 329 shmmap_s++; 330 } |
331 if (i >= shminfo.shmseg) { 332 error = EMFILE; 333 goto done2; 334 } |
335 size = round_page(shmseg->shm_segsz); 336#ifdef VM_PROT_READ_IS_EXEC 337 prot = VM_PROT_READ | VM_PROT_EXECUTE; 338#else 339 prot = VM_PROT_READ; 340#endif 341 if ((uap->shmflg & SHM_RDONLY) == 0) 342 prot |= VM_PROT_WRITE; 343 flags = MAP_ANON | MAP_SHARED; 344 if (uap->shmaddr) { 345 flags |= MAP_FIXED; |
346 if (uap->shmflg & SHM_RND) { |
347 attach_va = (vm_offset_t)uap->shmaddr & ~(SHMLBA-1); |
348 } else if (((vm_offset_t)uap->shmaddr & (SHMLBA-1)) == 0) { |
349 attach_va = (vm_offset_t)uap->shmaddr; |
350 } else { 351 error = EINVAL; 352 goto done2; 353 } |
354 } else { 355 /* 356 * This is just a hint to vm_map_find() about where to 357 * put it. 358 */ 359 attach_va = round_page((vm_offset_t)p->p_vmspace->vm_taddr 360 + MAXTSIZ + MAXDSIZ); 361 } 362 363 shm_handle = shmseg->shm_internal; 364 vm_object_reference(shm_handle->shm_object); 365 rv = vm_map_find(&p->p_vmspace->vm_map, shm_handle->shm_object, 366 0, &attach_va, size, (flags & MAP_FIXED)?0:1, prot, prot, 0); 367 if (rv != KERN_SUCCESS) { |
368 error = ENOMEM; 369 goto done2; |
370 } 371 vm_map_inherit(&p->p_vmspace->vm_map, 372 attach_va, attach_va + size, VM_INHERIT_SHARE); 373 374 shmmap_s->va = attach_va; 375 shmmap_s->shmid = uap->shmid; 376 shmseg->shm_lpid = p->p_pid; 377 shmseg->shm_atime = time_second; 378 shmseg->shm_nattch++; 379 p->p_retval[0] = attach_va; |
380done2: 381 mtx_unlock(&Giant); 382 return (error); |
383} 384 385struct oshmid_ds { 386 struct ipc_perm shm_perm; /* operation perms */ 387 int shm_segsz; /* size of segment (bytes) */ 388 ushort shm_cpid; /* pid, creator */ 389 ushort shm_lpid; /* pid, last operation */ 390 short shm_nattch; /* no. of current attaches */ --- 4 unchanged lines hidden (view full) --- 395}; 396 397struct oshmctl_args { 398 int shmid; 399 int cmd; 400 struct oshmid_ds *ubuf; 401}; 402 |
403/* 404 * MPSAFE 405 */ |
406static int 407oshmctl(p, uap) 408 struct proc *p; 409 struct oshmctl_args *uap; 410{ 411#ifdef COMPAT_43 |
412 int error = 0; |
413 struct shmid_ds *shmseg; 414 struct oshmid_ds outbuf; 415 |
416 mtx_lock(&Giant); |
417 |
418 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { 419 error = ENOSYS; 420 goto done2; 421 } 422 |
423 shmseg = shm_find_segment_by_shmid(uap->shmid); |
424 if (shmseg == NULL) { 425 error = EINVAL; 426 goto done2; 427 } |
428 switch (uap->cmd) { 429 case IPC_STAT: 430 error = ipcperm(p, &shmseg->shm_perm, IPC_R); 431 if (error) |
432 goto done2; |
433 outbuf.shm_perm = shmseg->shm_perm; 434 outbuf.shm_segsz = shmseg->shm_segsz; 435 outbuf.shm_cpid = shmseg->shm_cpid; 436 outbuf.shm_lpid = shmseg->shm_lpid; 437 outbuf.shm_nattch = shmseg->shm_nattch; 438 outbuf.shm_atime = shmseg->shm_atime; 439 outbuf.shm_dtime = shmseg->shm_dtime; 440 outbuf.shm_ctime = shmseg->shm_ctime; 441 outbuf.shm_handle = shmseg->shm_internal; 442 error = copyout((caddr_t)&outbuf, uap->ubuf, sizeof(outbuf)); 443 if (error) |
444 goto done2; |
445 break; 446 default: 447 /* XXX casting to (sy_call_t *) is bogus, as usual. */ |
448 error = ((sy_call_t *)shmctl)(p, uap); 449 break; |
450 } |
451done2: 452 mtx_unlock(&Giant); 453 return (error); |
454#else 455 return EINVAL; 456#endif 457} 458 459#ifndef _SYS_SYSPROTO_H_ 460struct shmctl_args { 461 int shmid; 462 int cmd; 463 struct shmid_ds *buf; 464}; 465#endif 466 |
467/* 468 * MPSAFE 469 */ |
470int 471shmctl(p, uap) 472 struct proc *p; 473 struct shmctl_args *uap; 474{ |
475 int error = 0; |
476 struct shmid_ds inbuf; 477 struct shmid_ds *shmseg; 478 |
479 mtx_lock(&Giant); |
480 |
481 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { 482 error = ENOSYS; 483 goto done2; 484 } |
485 486 shmseg = shm_find_segment_by_shmid(uap->shmid); |
487 if (shmseg == NULL) { 488 error = EINVAL; 489 goto done2; 490 } |
491 switch (uap->cmd) { 492 case IPC_STAT: 493 error = ipcperm(p, &shmseg->shm_perm, IPC_R); 494 if (error) |
495 goto done2; |
496 error = copyout((caddr_t)shmseg, uap->buf, sizeof(inbuf)); 497 if (error) |
498 goto done2; |
499 break; 500 case IPC_SET: 501 error = ipcperm(p, &shmseg->shm_perm, IPC_M); 502 if (error) |
503 goto done2; |
504 error = copyin(uap->buf, (caddr_t)&inbuf, sizeof(inbuf)); 505 if (error) |
506 goto done2; |
507 shmseg->shm_perm.uid = inbuf.shm_perm.uid; 508 shmseg->shm_perm.gid = inbuf.shm_perm.gid; 509 shmseg->shm_perm.mode = 510 (shmseg->shm_perm.mode & ~ACCESSPERMS) | 511 (inbuf.shm_perm.mode & ACCESSPERMS); 512 shmseg->shm_ctime = time_second; 513 break; 514 case IPC_RMID: 515 error = ipcperm(p, &shmseg->shm_perm, IPC_M); 516 if (error) |
517 goto done2; |
518 shmseg->shm_perm.key = IPC_PRIVATE; 519 shmseg->shm_perm.mode |= SHMSEG_REMOVED; 520 if (shmseg->shm_nattch <= 0) { 521 shm_deallocate_segment(shmseg); 522 shm_last_free = IPCID_TO_IX(uap->shmid); 523 } 524 break; 525#if 0 526 case SHM_LOCK: 527 case SHM_UNLOCK: 528#endif 529 default: |
530 error = EINVAL; 531 break; |
532 } |
533done2: 534 mtx_unlock(&Giant); 535 return (error); |
536} 537 538#ifndef _SYS_SYSPROTO_H_ 539struct shmget_args { 540 key_t key; 541 size_t size; 542 int shmflg; 543}; --- 110 unchanged lines hidden (view full) --- 654 */ 655 shmseg->shm_perm.mode &= ~SHMSEG_WANTED; 656 wakeup((caddr_t)shmseg); 657 } 658 p->p_retval[0] = shmid; 659 return 0; 660} 661 |
662/* 663 * MPSAFE 664 */ |
665int 666shmget(p, uap) 667 struct proc *p; 668 struct shmget_args *uap; 669{ |
670 int segnum, mode; 671 int error; |
672 |
673 mtx_lock(&Giant); |
674 |
675 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { 676 error = ENOSYS; 677 goto done2; 678 } 679 |
680 mode = uap->shmflg & ACCESSPERMS; 681 if (uap->key != IPC_PRIVATE) { 682 again: 683 segnum = shm_find_segment_by_key(uap->key); 684 if (segnum >= 0) { 685 error = shmget_existing(p, uap, mode, segnum); 686 if (error == EAGAIN) 687 goto again; |
688 goto done2; |
689 } |
690 if ((uap->shmflg & IPC_CREAT) == 0) { 691 error = ENOENT; 692 goto done2; 693 } |
694 } |
695 error = shmget_allocate_segment(p, uap, mode); 696done2: 697 mtx_unlock(&Giant); 698 return (error); |
699} 700 |
701/* 702 * MPSAFE 703 */ |
704int 705shmsys(p, uap) 706 struct proc *p; 707 /* XXX actually varargs. */ 708 struct shmsys_args /* { 709 u_int which; 710 int a2; 711 int a3; 712 int a4; 713 } */ *uap; 714{ |
715 int error; |
716 |
717 mtx_lock(&Giant); |
718 |
719 if (!jail_sysvipc_allowed && jailed(p->p_ucred)) { 720 error = ENOSYS; 721 goto done2; 722 } 723 724 if (uap->which >= sizeof(shmcalls)/sizeof(shmcalls[0])) { 725 error = EINVAL; 726 goto done2; 727 } 728 error = (*shmcalls[uap->which])(p, &uap->a2); 729done2: 730 mtx_unlock(&Giant); 731 return (error); |
732} 733 734static void 735shmfork_myhook(p1, p2) 736 struct proc *p1, *p2; 737{ 738 struct shmmap_state *shmmap_s; 739 size_t size; --- 127 unchanged lines hidden --- |