Print this page
8381 Convert ipsec_alg_lock from mutex to rwlock

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/inet/ip/ipsecah.c
          +++ new/usr/src/uts/common/inet/ip/ipsecah.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   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
       24 + * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved.
  24   25   */
  25   26  
  26   27  #include <sys/types.h>
  27   28  #include <sys/stream.h>
  28   29  #include <sys/stropts.h>
  29   30  #include <sys/errno.h>
  30   31  #include <sys/strlog.h>
  31   32  #include <sys/tihdr.h>
  32   33  #include <sys/socket.h>
  33   34  #include <sys/ddi.h>
↓ open down ↓ 206 lines elided ↑ open up ↑
 240  241          ns = netstack_find_by_stackid(stackid);
 241  242          if (ns == NULL)
 242  243                  return (-1);
 243  244          ipss = ns->netstack_ipsec;
 244  245          if (ipss == NULL) {
 245  246                  netstack_rele(ns);
 246  247                  return (-1);
 247  248          }
 248  249          ekp = (ah_kstats_t *)kp->ks_data;
 249  250  
 250      -        mutex_enter(&ipss->ipsec_alg_lock);
      251 +        rw_enter(&ipss->ipsec_alg_lock, RW_READER);
 251  252          ekp->ah_stat_num_aalgs.value.ui64 = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
 252      -        mutex_exit(&ipss->ipsec_alg_lock);
      253 +        rw_exit(&ipss->ipsec_alg_lock);
 253  254  
 254  255          netstack_rele(ns);
 255  256          return (0);
 256  257  }
 257  258  
 258  259  /*
 259  260   * Don't have to lock ipsec_age_interval, as only one thread will access it at
 260  261   * a time, because I control the one function that does a qtimeout() on
 261  262   * ah_pfkey_q.
 262  263   */
↓ open down ↓ 303 lines elided ↑ open up ↑
 566  567                          allocsize += sens_len;
 567  568                  }
 568  569          }
 569  570  
 570  571          /*
 571  572           * Allocate the PF_KEY message that follows KEYSOCK_OUT.
 572  573           * The alg reader lock needs to be held while allocating
 573  574           * the variable part (i.e. the algorithms) of the message.
 574  575           */
 575  576  
 576      -        mutex_enter(&ipss->ipsec_alg_lock);
      577 +        rw_enter(&ipss->ipsec_alg_lock, RW_READER);
 577  578  
 578  579          /*
 579  580           * Return only valid algorithms, so the number of algorithms
 580  581           * to send up may be less than the number of algorithm entries
 581  582           * in the table.
 582  583           */
 583  584          authalgs = ipss->ipsec_alglists[IPSEC_ALG_AUTH];
 584  585          for (num_aalgs = 0, i = 0; i < IPSEC_MAX_ALGS; i++)
 585  586                  if (authalgs[i] != NULL && ALG_VALID(authalgs[i]))
 586  587                          num_aalgs++;
↓ open down ↓ 1 lines elided ↑ open up ↑
 588  589          /*
 589  590           * Fill SADB_REGISTER message's algorithm descriptors.  Hold
 590  591           * down the lock while filling it.
 591  592           */
 592  593          if (num_aalgs != 0) {
 593  594                  allocsize += (num_aalgs * sizeof (*saalg));
 594  595                  allocsize += sizeof (*sasupp);
 595  596          }
 596  597          mp->b_cont = allocb(allocsize, BPRI_HI);
 597  598          if (mp->b_cont == NULL) {
 598      -                mutex_exit(&ipss->ipsec_alg_lock);
      599 +                rw_exit(&ipss->ipsec_alg_lock);
 599  600                  freemsg(mp);
 600  601                  return (B_FALSE);
 601  602          }
 602  603  
 603  604          mp->b_cont->b_wptr += allocsize;
 604  605          nextext = (sadb_ext_t *)(mp->b_cont->b_rptr + sizeof (*samsg));
 605  606  
 606  607          if (num_aalgs != 0) {
 607  608  
 608  609                  saalg = (sadb_alg_t *)(((uint8_t *)nextext) + sizeof (*sasupp));
↓ open down ↓ 26 lines elided ↑ open up ↑
 635  636                   * algorithms.
 636  637                   */
 637  638                  for (; i < IPSEC_MAX_ALGS; i++)
 638  639                          if (authalgs[i] != NULL && ALG_VALID(authalgs[i]))
 639  640                                  cmn_err(CE_PANIC,
 640  641                                      "ah_register_out()!  Missed #%d.\n", i);
 641  642  #endif /* DEBUG */
 642  643                  nextext = (sadb_ext_t *)saalg;
 643  644          }
 644  645  
 645      -        mutex_exit(&ipss->ipsec_alg_lock);
      646 +        rw_exit(&ipss->ipsec_alg_lock);
 646  647  
 647  648          if (sens_tsl != NULL) {
 648  649                  sens = (sadb_sens_t *)nextext;
 649  650                  sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY,
 650  651                      sens_tsl, sens_len);
 651  652  
 652  653                  nextext = (sadb_ext_t *)(((uint8_t *)sens) + sens_len);
 653  654          }
 654  655  
 655  656          /* Now fill the restof the SADB_REGISTER message. */
↓ open down ↓ 460 lines elided ↑ open up ↑
1116 1117                  if (!is_system_labeled())
1117 1118                          return (EOPNOTSUPP);
1118 1119          }
1119 1120          /*
1120 1121           * XXX Policy : I'm not checking identities at this time, but
1121 1122           * if I did, I'd do them here, before I sent the weak key
1122 1123           * check up to the algorithm.
1123 1124           */
1124 1125  
1125 1126          /* verify that there is a mapping for the specified algorithm */
1126      -        mutex_enter(&ipss->ipsec_alg_lock);
     1127 +        rw_enter(&ipss->ipsec_alg_lock, RW_READER);
1127 1128          aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH][assoc->sadb_sa_auth];
1128 1129          if (aalg == NULL || !ALG_VALID(aalg)) {
1129      -                mutex_exit(&ipss->ipsec_alg_lock);
     1130 +                rw_exit(&ipss->ipsec_alg_lock);
1130 1131                  ah1dbg(ahstack, ("Couldn't find auth alg #%d.\n",
1131 1132                      assoc->sadb_sa_auth));
1132 1133                  *diagnostic = SADB_X_DIAGNOSTIC_BAD_AALG;
1133 1134                  return (EINVAL);
1134 1135          }
1135 1136          ASSERT(aalg->alg_mech_type != CRYPTO_MECHANISM_INVALID);
1136 1137  
1137 1138          /* sanity check key sizes */
1138 1139          if (!ipsec_valid_key_size(key->sadb_key_bits, aalg)) {
1139      -                mutex_exit(&ipss->ipsec_alg_lock);
     1140 +                rw_exit(&ipss->ipsec_alg_lock);
1140 1141                  *diagnostic = SADB_X_DIAGNOSTIC_BAD_AKEYBITS;
1141 1142                  return (EINVAL);
1142 1143          }
1143 1144  
1144 1145          /* check key and fix parity if needed */
1145 1146          if (ipsec_check_key(aalg->alg_mech_type, key, B_TRUE,
1146 1147              diagnostic) != 0) {
1147      -                mutex_exit(&ipss->ipsec_alg_lock);
     1148 +                rw_exit(&ipss->ipsec_alg_lock);
1148 1149                  return (EINVAL);
1149 1150          }
1150 1151  
1151      -        mutex_exit(&ipss->ipsec_alg_lock);
     1152 +        rw_exit(&ipss->ipsec_alg_lock);
1152 1153  
1153 1154          return (ah_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
1154 1155              diagnostic, ahstack));
1155 1156  }
1156 1157  
1157 1158  /* Refactor me */
1158 1159  /*
1159 1160   * Update a security association.  Updates come in two varieties.  The first
1160 1161   * is an update of lifetimes on a non-larval SA.  The second is an update of
1161 1162   * a larval SA, which ends up looking a lot more like an add.
↓ open down ↓ 580 lines elided ↑ open up ↑
1742 1743  static void
1743 1744  ah_insert_prop(sadb_prop_t *prop, ipsacq_t *acqrec, uint_t combs,
1744 1745      netstack_t *ns)
1745 1746  {
1746 1747          sadb_comb_t *comb = (sadb_comb_t *)(prop + 1);
1747 1748          ipsec_action_t *ap;
1748 1749          ipsec_prot_t *prot;
1749 1750          ipsecah_stack_t *ahstack = ns->netstack_ipsecah;
1750 1751          ipsec_stack_t   *ipss = ns->netstack_ipsec;
1751 1752  
1752      -        ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
     1753 +        ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock));
1753 1754  
1754 1755          prop->sadb_prop_exttype = SADB_EXT_PROPOSAL;
1755 1756          prop->sadb_prop_len = SADB_8TO64(sizeof (sadb_prop_t));
1756 1757          *(uint32_t *)(&prop->sadb_prop_replay) = 0;     /* Quick zero-out! */
1757 1758  
1758 1759          prop->sadb_prop_replay = ahstack->ipsecah_replay_size;
1759 1760  
1760 1761          /*
1761 1762           * Based upon algorithm properties, and what-not, prioritize a
1762 1763           * proposal, based on the ordering of the AH algorithms in the
↓ open down ↓ 91 lines elided ↑ open up ↑
1854 1855          }
1855 1856  
1856 1857          /* Set up ACQUIRE. */
1857 1858          pfkeymp = sadb_setup_acquire(acqrec, SADB_SATYPE_AH,
1858 1859              ns->netstack_ipsec);
1859 1860          if (pfkeymp == NULL) {
1860 1861                  ah0dbg(("sadb_setup_acquire failed.\n"));
1861 1862                  mutex_exit(&acqrec->ipsacq_lock);
1862 1863                  return;
1863 1864          }
1864      -        ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
     1865 +        ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock));
1865 1866          combs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
1866 1867          msgmp = pfkeymp->b_cont;
1867 1868          samsg = (sadb_msg_t *)(msgmp->b_rptr);
1868 1869  
1869 1870          /* Insert proposal here. */
1870 1871  
1871 1872          prop = (sadb_prop_t *)(((uint64_t *)samsg) + samsg->sadb_msg_len);
1872 1873          ah_insert_prop(prop, acqrec, combs, ns);
1873 1874          samsg->sadb_msg_len += prop->sadb_prop_len;
1874 1875          msgmp->b_wptr += SADB_64TO8(samsg->sadb_msg_len);
1875 1876  
1876      -        mutex_exit(&ipss->ipsec_alg_lock);
     1877 +        rw_exit(&ipss->ipsec_alg_lock);
1877 1878  
1878 1879          /*
1879 1880           * Must mutex_exit() before sending PF_KEY message up, in
1880 1881           * order to avoid recursive mutex_enter() if there are no registered
1881 1882           * listeners.
1882 1883           *
1883 1884           * Once I've sent the message, I'm cool anyway.
1884 1885           */
1885 1886          mutex_exit(&acqrec->ipsacq_lock);
1886 1887          if (extended != NULL) {
↓ open down ↓ 2126 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX