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/ipsecesp.c
          +++ new/usr/src/uts/common/inet/ip/ipsecesp.c
↓ open down ↓ 290 lines elided ↑ open up ↑
 291  291          ns = netstack_find_by_stackid(stackid);
 292  292          if (ns == NULL)
 293  293                  return (-1);
 294  294          ipss = ns->netstack_ipsec;
 295  295          if (ipss == NULL) {
 296  296                  netstack_rele(ns);
 297  297                  return (-1);
 298  298          }
 299  299          ekp = (esp_kstats_t *)kp->ks_data;
 300  300  
 301      -        mutex_enter(&ipss->ipsec_alg_lock);
      301 +        rw_enter(&ipss->ipsec_alg_lock, RW_READER);
 302  302          ekp->esp_stat_num_aalgs.value.ui64 =
 303  303              ipss->ipsec_nalgs[IPSEC_ALG_AUTH];
 304  304          ekp->esp_stat_num_ealgs.value.ui64 =
 305  305              ipss->ipsec_nalgs[IPSEC_ALG_ENCR];
 306      -        mutex_exit(&ipss->ipsec_alg_lock);
      306 +        rw_exit(&ipss->ipsec_alg_lock);
 307  307  
 308  308          netstack_rele(ns);
 309  309          return (0);
 310  310  }
 311  311  
 312  312  #ifdef DEBUG
 313  313  /*
 314  314   * Debug routine, useful to see pre-encryption data.
 315  315   */
 316  316  static char *
↓ open down ↓ 871 lines elided ↑ open up ↑
1188 1188  static void
1189 1189  esp_insert_prop(sadb_prop_t *prop, ipsacq_t *acqrec, uint_t combs,
1190 1190      netstack_t *ns)
1191 1191  {
1192 1192          sadb_comb_t *comb = (sadb_comb_t *)(prop + 1);
1193 1193          ipsec_action_t *ap;
1194 1194          ipsec_prot_t *prot;
1195 1195          ipsecesp_stack_t *espstack = ns->netstack_ipsecesp;
1196 1196          ipsec_stack_t   *ipss = ns->netstack_ipsec;
1197 1197  
1198      -        ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
     1198 +        ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock));
1199 1199  
1200 1200          prop->sadb_prop_exttype = SADB_EXT_PROPOSAL;
1201 1201          prop->sadb_prop_len = SADB_8TO64(sizeof (sadb_prop_t));
1202 1202          *(uint32_t *)(&prop->sadb_prop_replay) = 0;     /* Quick zero-out! */
1203 1203  
1204 1204          prop->sadb_prop_replay = espstack->ipsecesp_replay_size;
1205 1205  
1206 1206          /*
1207 1207           * Based upon algorithm properties, and what-not, prioritize a
1208 1208           * proposal, based on the ordering of the ESP algorithms in the
↓ open down ↓ 109 lines elided ↑ open up ↑
1318 1318          }
1319 1319  
1320 1320          /* Set up ACQUIRE. */
1321 1321          pfkeymp = sadb_setup_acquire(acqrec, SADB_SATYPE_ESP,
1322 1322              ns->netstack_ipsec);
1323 1323          if (pfkeymp == NULL) {
1324 1324                  esp0dbg(("sadb_setup_acquire failed.\n"));
1325 1325                  mutex_exit(&acqrec->ipsacq_lock);
1326 1326                  return;
1327 1327          }
1328      -        ASSERT(MUTEX_HELD(&ipss->ipsec_alg_lock));
     1328 +        ASSERT(RW_READ_HELD(&ipss->ipsec_alg_lock));
1329 1329          combs = ipss->ipsec_nalgs[IPSEC_ALG_AUTH] *
1330 1330              ipss->ipsec_nalgs[IPSEC_ALG_ENCR];
1331 1331          msgmp = pfkeymp->b_cont;
1332 1332          samsg = (sadb_msg_t *)(msgmp->b_rptr);
1333 1333  
1334 1334          /* Insert proposal here. */
1335 1335  
1336 1336          prop = (sadb_prop_t *)(((uint64_t *)samsg) + samsg->sadb_msg_len);
1337 1337          esp_insert_prop(prop, acqrec, combs, ns);
1338 1338          samsg->sadb_msg_len += prop->sadb_prop_len;
1339 1339          msgmp->b_wptr += SADB_64TO8(samsg->sadb_msg_len);
1340 1340  
1341      -        mutex_exit(&ipss->ipsec_alg_lock);
     1341 +        rw_exit(&ipss->ipsec_alg_lock);
1342 1342  
1343 1343          /*
1344 1344           * Must mutex_exit() before sending PF_KEY message up, in
1345 1345           * order to avoid recursive mutex_enter() if there are no registered
1346 1346           * listeners.
1347 1347           *
1348 1348           * Once I've sent the message, I'm cool anyway.
1349 1349           */
1350 1350          mutex_exit(&acqrec->ipsacq_lock);
1351 1351          if (extended != NULL) {
↓ open down ↓ 1684 lines elided ↑ open up ↑
3036 3036                  if (sens_tsl != NULL) {
3037 3037                          sens_len = sadb_sens_len_from_label(sens_tsl);
3038 3038                          allocsize += sens_len;
3039 3039                  }
3040 3040          }
3041 3041  
3042 3042          /*
3043 3043           * Allocate the PF_KEY message that follows KEYSOCK_OUT.
3044 3044           */
3045 3045  
3046      -        mutex_enter(&ipss->ipsec_alg_lock);
     3046 +        rw_enter(&ipss->ipsec_alg_lock, RW_READER);
3047 3047          /*
3048 3048           * Fill SADB_REGISTER message's algorithm descriptors.  Hold
3049 3049           * down the lock while filling it.
3050 3050           *
3051 3051           * Return only valid algorithms, so the number of algorithms
3052 3052           * to send up may be less than the number of algorithm entries
3053 3053           * in the table.
3054 3054           */
3055 3055          authalgs = ipss->ipsec_alglists[IPSEC_ALG_AUTH];
3056 3056          for (num_aalgs = 0, i = 0; i < IPSEC_MAX_ALGS; i++)
↓ open down ↓ 8 lines elided ↑ open up ↑
3065 3065          for (num_ealgs = 0, i = 0; i < IPSEC_MAX_ALGS; i++)
3066 3066                  if (encralgs[i] != NULL && ALG_VALID(encralgs[i]))
3067 3067                          num_ealgs++;
3068 3068  
3069 3069          if (num_ealgs != 0) {
3070 3070                  allocsize += (num_ealgs * sizeof (*saalg));
3071 3071                  allocsize += sizeof (*sasupp_encr);
3072 3072          }
3073 3073          keysock_out_mp->b_cont = allocb(allocsize, BPRI_HI);
3074 3074          if (keysock_out_mp->b_cont == NULL) {
3075      -                mutex_exit(&ipss->ipsec_alg_lock);
     3075 +                rw_exit(&ipss->ipsec_alg_lock);
3076 3076                  freemsg(keysock_out_mp);
3077 3077                  return (B_FALSE);
3078 3078          }
3079 3079          pfkey_msg_mp = keysock_out_mp->b_cont;
3080 3080          pfkey_msg_mp->b_wptr += allocsize;
3081 3081  
3082 3082          nextext = (sadb_ext_t *)(pfkey_msg_mp->b_rptr + sizeof (*samsg));
3083 3083  
3084 3084          if (num_aalgs != 0) {
3085 3085                  sasupp_auth = (sadb_supported_t *)nextext;
↓ open down ↓ 73 lines elided ↑ open up ↑
3159 3159                                      "Missed ealg #%d.\n", i);
3160 3160                          }
3161 3161                  }
3162 3162  #endif /* DEBUG */
3163 3163                  nextext = (sadb_ext_t *)saalg;
3164 3164          }
3165 3165  
3166 3166          current_aalgs = num_aalgs;
3167 3167          current_ealgs = num_ealgs;
3168 3168  
3169      -        mutex_exit(&ipss->ipsec_alg_lock);
     3169 +        rw_exit(&ipss->ipsec_alg_lock);
3170 3170  
3171 3171          if (sens_tsl != NULL) {
3172 3172                  sens = (sadb_sens_t *)nextext;
3173 3173                  sadb_sens_from_label(sens, SADB_EXT_SENSITIVITY,
3174 3174                      sens_tsl, sens_len);
3175 3175  
3176 3176                  nextext = (sadb_ext_t *)(((uint8_t *)sens) + sens_len);
3177 3177          }
3178 3178  
3179 3179          /* Now fill the rest of the SADB_REGISTER message. */
↓ open down ↓ 504 lines elided ↑ open up ↑
3684 3684  
3685 3685          if ((*diagnostic = sadb_labelchk(ksi)) != 0)
3686 3686                  return (EINVAL);
3687 3687  
3688 3688          /*
3689 3689           * XXX Policy :  I'm not checking identities at this time,
3690 3690           * but if I did, I'd do them here, before I sent
3691 3691           * the weak key check up to the algorithm.
3692 3692           */
3693 3693  
3694      -        mutex_enter(&ipss->ipsec_alg_lock);
     3694 +        rw_enter(&ipss->ipsec_alg_lock, RW_READER);
3695 3695  
3696 3696          /*
3697 3697           * First locate the authentication algorithm.
3698 3698           */
3699 3699  #ifdef IPSEC_LATENCY_TEST
3700 3700          if (akey != NULL && assoc->sadb_sa_auth != SADB_AALG_NONE) {
3701 3701  #else
3702 3702          if (akey != NULL) {
3703 3703  #endif
3704 3704                  ipsec_alginfo_t *aalg;
3705 3705  
3706 3706                  aalg = ipss->ipsec_alglists[IPSEC_ALG_AUTH]
3707 3707                      [assoc->sadb_sa_auth];
3708 3708                  if (aalg == NULL || !ALG_VALID(aalg)) {
3709      -                        mutex_exit(&ipss->ipsec_alg_lock);
     3709 +                        rw_exit(&ipss->ipsec_alg_lock);
3710 3710                          esp1dbg(espstack, ("Couldn't find auth alg #%d.\n",
3711 3711                              assoc->sadb_sa_auth));
3712 3712                          *diagnostic = SADB_X_DIAGNOSTIC_BAD_AALG;
3713 3713                          return (EINVAL);
3714 3714                  }
3715 3715  
3716 3716                  /*
3717 3717                   * Sanity check key sizes.
3718 3718                   * Note: It's not possible to use SADB_AALG_NONE because
3719 3719                   * this auth_alg is not defined with ALG_FLAG_VALID. If this
3720 3720                   * ever changes, the same check for SADB_AALG_NONE and
3721 3721                   * a auth_key != NULL should be made here ( see below).
3722 3722                   */
3723 3723                  if (!ipsec_valid_key_size(akey->sadb_key_bits, aalg)) {
3724      -                        mutex_exit(&ipss->ipsec_alg_lock);
     3724 +                        rw_exit(&ipss->ipsec_alg_lock);
3725 3725                          *diagnostic = SADB_X_DIAGNOSTIC_BAD_AKEYBITS;
3726 3726                          return (EINVAL);
3727 3727                  }
3728 3728                  ASSERT(aalg->alg_mech_type != CRYPTO_MECHANISM_INVALID);
3729 3729  
3730 3730                  /* check key and fix parity if needed */
3731 3731                  if (ipsec_check_key(aalg->alg_mech_type, akey, B_TRUE,
3732 3732                      diagnostic) != 0) {
3733      -                        mutex_exit(&ipss->ipsec_alg_lock);
     3733 +                        rw_exit(&ipss->ipsec_alg_lock);
3734 3734                          return (EINVAL);
3735 3735                  }
3736 3736          }
3737 3737  
3738 3738          /*
3739 3739           * Then locate the encryption algorithm.
3740 3740           */
3741 3741          if (ekey != NULL) {
3742 3742                  uint_t keybits;
3743 3743                  ipsec_alginfo_t *ealg;
3744 3744  
3745 3745                  ealg = ipss->ipsec_alglists[IPSEC_ALG_ENCR]
3746 3746                      [assoc->sadb_sa_encrypt];
3747 3747                  if (ealg == NULL || !ALG_VALID(ealg)) {
3748      -                        mutex_exit(&ipss->ipsec_alg_lock);
     3748 +                        rw_exit(&ipss->ipsec_alg_lock);
3749 3749                          esp1dbg(espstack, ("Couldn't find encr alg #%d.\n",
3750 3750                              assoc->sadb_sa_encrypt));
3751 3751                          *diagnostic = SADB_X_DIAGNOSTIC_BAD_EALG;
3752 3752                          return (EINVAL);
3753 3753                  }
3754 3754  
3755 3755                  /*
3756 3756                   * Sanity check key sizes. If the encryption algorithm is
3757 3757                   * SADB_EALG_NULL but the encryption key is NOT
3758 3758                   * NULL then complain.
3759 3759                   *
3760 3760                   * The keying material includes salt bits if required by
3761 3761                   * algorithm and optionally the Initial IV, check the
3762 3762                   * length of whats left.
3763 3763                   */
3764 3764                  keybits = ekey->sadb_key_bits;
3765 3765                  keybits -= ekey->sadb_key_reserved;
3766 3766                  keybits -= SADB_8TO1(ealg->alg_saltlen);
3767 3767                  if ((assoc->sadb_sa_encrypt == SADB_EALG_NULL) ||
3768 3768                      (!ipsec_valid_key_size(keybits, ealg))) {
3769      -                        mutex_exit(&ipss->ipsec_alg_lock);
     3769 +                        rw_exit(&ipss->ipsec_alg_lock);
3770 3770                          *diagnostic = SADB_X_DIAGNOSTIC_BAD_EKEYBITS;
3771 3771                          return (EINVAL);
3772 3772                  }
3773 3773                  ASSERT(ealg->alg_mech_type != CRYPTO_MECHANISM_INVALID);
3774 3774  
3775 3775                  /* check key */
3776 3776                  if (ipsec_check_key(ealg->alg_mech_type, ekey, B_FALSE,
3777 3777                      diagnostic) != 0) {
3778      -                        mutex_exit(&ipss->ipsec_alg_lock);
     3778 +                        rw_exit(&ipss->ipsec_alg_lock);
3779 3779                          return (EINVAL);
3780 3780                  }
3781 3781          }
3782      -        mutex_exit(&ipss->ipsec_alg_lock);
     3782 +        rw_exit(&ipss->ipsec_alg_lock);
3783 3783  
3784 3784          return (esp_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
3785 3785              diagnostic, espstack));
3786 3786  }
3787 3787  
3788 3788  /*
3789 3789   * Update a security association.  Updates come in two varieties.  The first
3790 3790   * is an update of lifetimes on a non-larval SA.  The second is an update of
3791 3791   * a larval SA, which ends up looking a lot more like an add.
3792 3792   */
↓ open down ↓ 404 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX