Print this page
OS-5223 removed shm segment is no longer available
Reviewed by: Bryan Cantrill <bryan@joyent.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/os/shm.c
          +++ new/usr/src/uts/common/os/shm.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 1986, 2010, Oracle and/or its affiliates. All rights reserved.
       24 + * Copyright 2016 Joyent, Inc.
  24   25   */
  25   26  
  26   27  /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  27   28  /*        All Rights Reserved   */
  28   29  
  29   30  /*
  30   31   * University Copyright- Copyright (c) 1982, 1986, 1988
  31   32   * The Regents of the University of California
  32   33   * All Rights Reserved
  33   34   *
↓ open down ↓ 278 lines elided ↑ open up ↑
 312  313          as_rangelock(as);
 313  314  
 314  315          if (useISM) {
 315  316                  /*
 316  317                   * Handle ISM
 317  318                   */
 318  319                  uint_t  share_szc;
 319  320                  size_t  share_size;
 320  321                  struct  shm_data ssd;
 321  322                  uintptr_t align_hint;
      323 +                long    curprot;
 322  324  
 323  325                  /*
 324  326                   * Pick a share pagesize to use, if (!isspt(sp)).
 325  327                   * Otherwise use the already chosen page size.
 326  328                   *
 327  329                   * For the initial shmat (!isspt(sp)), where sptcreate is
 328  330                   * called, map_pgsz is called to recommend a [D]ISM pagesize,
 329  331                   * important for systems which offer more than one potential
 330  332                   * [D]ISM pagesize.
 331  333                   * If the shmat is just to attach to an already created
↓ open down ↓ 114 lines elided ↑ open up ↑
 446  448                          as_purge(as);
 447  449                          if (result != RANGE_OKAY ||
 448  450                              as_gap(as, len, &base, &len, AH_LO,
 449  451                              (caddr_t)NULL) != 0) {
 450  452                                  error = EINVAL;
 451  453                                  as_rangeunlock(as);
 452  454                                  goto errret;
 453  455                          }
 454  456                  }
 455  457  
      458 +                curprot = sp->shm_opts & SHM_PROT_MASK;
 456  459                  if (!isspt(sp)) {
 457  460                          error = sptcreate(size, &segspt, sp->shm_amp, prot,
 458  461                              flags, share_szc);
 459  462                          if (error) {
 460  463                                  as_rangeunlock(as);
 461  464                                  goto errret;
 462  465                          }
 463  466                          sp->shm_sptinfo->sptas = segspt->s_as;
 464  467                          sp->shm_sptseg = segspt;
 465      -                        sp->shm_sptprot = prot;
 466      -                } else if ((prot & sp->shm_sptprot) != sp->shm_sptprot) {
      468 +                        sp->shm_opts = (sp->shm_opts & ~SHM_PROT_MASK) | prot;
      469 +                } else if ((prot & curprot) != curprot) {
 467  470                          /*
 468  471                           * Ensure we're attaching to an ISM segment with
 469  472                           * fewer or equal permissions than what we're
 470  473                           * allowed.  Fail if the segment has more
 471  474                           * permissions than what we're allowed.
 472  475                           */
 473  476                          error = EACCES;
 474  477                          as_rangeunlock(as);
 475  478                          goto errret;
 476  479                  }
↓ open down ↓ 264 lines elided ↑ open up ↑
 741  744          /* Unlock segment */
 742  745          case SHM_UNLOCK:
 743  746                  if ((error = secpolicy_lock_memory(cr)) != 0)
 744  747                          break;
 745  748  
 746  749                  if (sp->shm_lkcnt && (--sp->shm_lkcnt == 0)) {
 747  750                          shmem_unlock(sp, sp->shm_amp);
 748  751                  }
 749  752                  break;
 750  753  
      754 +        /* Stage segment for removal, but don't remove until last detach */
      755 +        case SHM_RMID:
      756 +                if ((error = secpolicy_ipc_owner(cr, (kipc_perm_t *)sp)) != 0)
      757 +                        break;
      758 +
      759 +                /*
      760 +                 * If attached, just mark it as a pending remove, otherwise
      761 +                 * we must perform the normal ipc_rmid now.
      762 +                 */
      763 +                if ((sp->shm_perm.ipc_ref - 1) > 0) {
      764 +                        sp->shm_opts |= SHM_RM_PENDING;
      765 +                } else {
      766 +                        mutex_exit(lock);
      767 +                        return (ipc_rmid(shm_svc, shmid, cr));
      768 +                }
      769 +                break;
      770 +
 751  771          default:
 752  772                  error = EINVAL;
 753  773                  break;
 754  774          }
 755  775          mutex_exit(lock);
 756  776          return (error);
 757  777  }
 758  778  
 759  779  static void
 760  780  shm_detach(proc_t *pp, segacct_t *sap)
↓ open down ↓ 10 lines elided ↑ open up ↑
 771  791          (void) as_unmap(pp->p_as, addr, len);
 772  792  
 773  793          /*
 774  794           * Perform some detach-time accounting.
 775  795           */
 776  796          (void) ipc_lock(shm_svc, sp->shm_perm.ipc_id);
 777  797          if (sap->sa_flags & SHMSA_ISM)
 778  798                  sp->shm_ismattch--;
 779  799          sp->shm_dtime = gethrestime_sec();
 780  800          sp->shm_lpid = pp->p_pid;
      801 +        if ((sp->shm_opts & SHM_RM_PENDING) != 0 &&
      802 +            sp->shm_perm.ipc_ref == 2) {
      803 +                /*
      804 +                 * If this is the last detach of the segment across the whole
      805 +                 * system then now we can perform the delayed IPC_RMID.
      806 +                 * The ipc_ref count has 1 for the original 'get' and one for
      807 +                 * each 'attach' (see 'stat' handling in shmctl).
      808 +                 */
      809 +                sp->shm_opts &= ~SHM_RM_PENDING;
      810 +                mutex_enter(&shm_svc->ipcs_lock);
      811 +                ipc_rmsvc(shm_svc, (kipc_perm_t *)sp);  /* Drops lock */
      812 +                ASSERT(!MUTEX_HELD(&shm_svc->ipcs_lock));
      813 +                ASSERT(((kipc_perm_t *)sp)->ipc_ref > 0);
      814 +
      815 +                /* Lock was dropped, need to retake it for following rele. */
      816 +                (void) ipc_lock(shm_svc, sp->shm_perm.ipc_id);
      817 +        }
 781  818          ipc_rele(shm_svc, (kipc_perm_t *)sp);   /* Drops lock */
 782  819  
 783  820          kmem_free(sap, sizeof (segacct_t));
 784  821  }
 785  822  
 786  823  static int
 787  824  shmdt(caddr_t addr)
 788  825  {
 789  826          proc_t *pp = curproc;
 790  827          segacct_t *sap, template;
↓ open down ↓ 520 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX