Print this page
OS-4865 lxbrand async socket errors catch programs off guard
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
OS-4213 lxbrand should be able to set TCP_DEFER_ACCEPT after other socket operations
OS-3893 sendfile compat checks shouldn't be done in so_sendmblk
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/fs/sockfs/sockcommon_sops.c
          +++ new/usr/src/uts/common/fs/sockfs/sockcommon_sops.c
↓ open down ↓ 120 lines elided ↑ open up ↑
 121  121  {
 122  122          return (socket_init_common(so, pso, flags, cr));
 123  123  }
 124  124  
 125  125  int
 126  126  so_bind(struct sonode *so, struct sockaddr *name, socklen_t namelen,
 127  127      int flags, struct cred *cr)
 128  128  {
 129  129          int error;
 130  130  
 131      -        SO_BLOCK_FALLBACK(so, SOP_BIND(so, name, namelen, flags, cr));
      131 +        SO_BLOCK_FALLBACK_SAFE(so, SOP_BIND(so, name, namelen, flags, cr));
 132  132  
 133  133          ASSERT(flags == _SOBIND_XPG4_2 || flags == _SOBIND_SOCKBSD);
 134  134  
 135  135          /* X/Open requires this check */
 136  136          if ((so->so_state & SS_CANTSENDMORE) && !xnet_skip_checks) {
 137  137                  if (xnet_check_print) {
 138  138                          printf("sockfs: X/Open bind state check "
 139  139                              "caused EINVAL\n");
 140  140                  }
 141  141                  error = EINVAL;
↓ open down ↓ 156 lines elided ↑ open up ↑
 298  298          sock_connid_t id;
 299  299  
 300  300          ASSERT(MUTEX_NOT_HELD(&so->so_lock));
 301  301          SO_BLOCK_FALLBACK(so, SOP_CONNECT(so, name, namelen, fflag, flags, cr));
 302  302  
 303  303          /*
 304  304           * If there is a pending error, return error
 305  305           * This can happen if a non blocking operation caused an error.
 306  306           */
 307  307  
 308      -        if (so->so_error != 0) {
      308 +        if (so->so_error != 0 && (so->so_mode & SM_DEFERERR) == 0) {
 309  309                  mutex_enter(&so->so_lock);
 310  310                  error = sogeterr(so, B_TRUE);
 311  311                  mutex_exit(&so->so_lock);
 312  312                  if (error != 0)
 313  313                          goto done;
 314  314          }
 315  315  
 316  316          if (so->so_filter_active == 0 ||
 317  317              (error = sof_filter_connect(so, (struct sockaddr *)name,
 318  318              &namelen, cr)) < 0) {
↓ open down ↓ 78 lines elided ↑ open up ↑
 397  397  
 398  398          /*
 399  399           * For atomic sends we will only do one iteration.
 400  400           */
 401  401          do {
 402  402                  if (so->so_state & SS_CANTSENDMORE) {
 403  403                          error = EPIPE;
 404  404                          break;
 405  405                  }
 406  406  
 407      -                if (so->so_error != 0) {
      407 +                if (so->so_error != 0 && (so->so_mode & SM_DEFERERR) == 0) {
 408  408                          mutex_enter(&so->so_lock);
 409  409                          error = sogeterr(so, B_TRUE);
 410  410                          mutex_exit(&so->so_lock);
 411  411                          if (error != 0)
 412  412                                  break;
 413  413                  }
 414  414  
 415  415                  /*
 416  416                   * Send down OOB messages even if the send path is being
 417  417                   * flow controlled (assuming the protocol supports OOB data).
↓ open down ↓ 88 lines elided ↑ open up ↑
 506  506          }
 507  507  
 508  508          while (mp != NULL) {
 509  509                  mblk_t *nmp, *last_mblk;
 510  510                  size_t mlen;
 511  511  
 512  512                  if (so->so_state & SS_CANTSENDMORE) {
 513  513                          error = EPIPE;
 514  514                          break;
 515  515                  }
 516      -                if (so->so_error != 0) {
      516 +                if (so->so_error != 0 && (so->so_mode & SM_DEFERERR) == 0) {
 517  517                          mutex_enter(&so->so_lock);
 518  518                          error = sogeterr(so, B_TRUE);
 519  519                          mutex_exit(&so->so_lock);
 520  520                          if (error != 0)
 521  521                                  break;
 522  522                  }
 523  523                  /* Socket filters are not flow controlled */
 524  524                  if (SO_SND_FLOWCTRLD(so) && !fil_inject) {
 525  525                          /*
 526  526                           * Need to wait until the protocol is ready to receive
↓ open down ↓ 52 lines elided ↑ open up ↑
 579  579  #pragma inline(so_sendmblk_impl)
 580  580  
 581  581  int
 582  582  so_sendmblk(struct sonode *so, struct nmsghdr *msg, int fflag,
 583  583      struct cred *cr, mblk_t **mpp)
 584  584  {
 585  585          int error;
 586  586  
 587  587          SO_BLOCK_FALLBACK(so, SOP_SENDMBLK(so, msg, fflag, cr, mpp));
 588  588  
 589      -        if ((so->so_mode & SM_SENDFILESUPP) == 0) {
 590      -                SO_UNBLOCK_FALLBACK(so);
 591      -                return (EOPNOTSUPP);
 592      -        }
 593      -
 594  589          error = so_sendmblk_impl(so, msg, fflag, cr, mpp, so->so_filter_top,
 595  590              B_FALSE);
 596  591  
 597  592          SO_UNBLOCK_FALLBACK(so);
 598  593  
 599  594          return (error);
 600  595  }
 601  596  
 602  597  int
 603  598  so_shutdown(struct sonode *so, int how, struct cred *cr)
↓ open down ↓ 42 lines elided ↑ open up ↑
 646  641          SO_UNBLOCK_FALLBACK(so);
 647  642          return (error);
 648  643  }
 649  644  
 650  645  int
 651  646  so_getsockname(struct sonode *so, struct sockaddr *addr,
 652  647      socklen_t *addrlen, struct cred *cr)
 653  648  {
 654  649          int error;
 655  650  
 656      -        SO_BLOCK_FALLBACK(so, SOP_GETSOCKNAME(so, addr, addrlen, cr));
      651 +        SO_BLOCK_FALLBACK_SAFE(so, SOP_GETSOCKNAME(so, addr, addrlen, cr));
 657  652  
 658  653          if (so->so_filter_active == 0 ||
 659  654              (error = sof_filter_getsockname(so, addr, addrlen, cr)) < 0)
 660  655                  error = (*so->so_downcalls->sd_getsockname)
 661  656                      (so->so_proto_handle, addr, addrlen, cr);
 662  657  
 663  658          SO_UNBLOCK_FALLBACK(so);
 664  659          return (error);
 665  660  }
 666  661  
↓ open down ↓ 28 lines elided ↑ open up ↑
 695  690  
 696  691  int
 697  692  so_getsockopt(struct sonode *so, int level, int option_name,
 698  693      void *optval, socklen_t *optlenp, int flags, struct cred *cr)
 699  694  {
 700  695          int error = 0;
 701  696  
 702  697          if (level == SOL_FILTER)
 703  698                  return (sof_getsockopt(so, option_name, optval, optlenp, cr));
 704  699  
 705      -        SO_BLOCK_FALLBACK(so,
      700 +        SO_BLOCK_FALLBACK_SAFE(so,
 706  701              SOP_GETSOCKOPT(so, level, option_name, optval, optlenp, flags, cr));
 707  702  
 708  703          if ((so->so_filter_active == 0 ||
 709  704              (error = sof_filter_getsockopt(so, level, option_name, optval,
 710  705              optlenp, cr)) < 0) &&
 711  706              (error = socket_getopt_common(so, level, option_name, optval,
 712  707              optlenp, flags)) < 0) {
 713  708                  error = (*so->so_downcalls->sd_getsockopt)
 714  709                      (so->so_proto_handle, level, option_name, optval, optlenp,
 715  710                      cr);
↓ open down ↓ 68 lines elided ↑ open up ↑
 784  779  so_setsockopt(struct sonode *so, int level, int option_name,
 785  780      const void *optval, socklen_t optlen, struct cred *cr)
 786  781  {
 787  782          int error = 0;
 788  783          struct timeval tl;
 789  784          const void *opt = optval;
 790  785  
 791  786          if (level == SOL_FILTER)
 792  787                  return (sof_setsockopt(so, option_name, optval, optlen, cr));
 793  788  
 794      -        SO_BLOCK_FALLBACK(so,
      789 +        SO_BLOCK_FALLBACK_SAFE(so,
 795  790              SOP_SETSOCKOPT(so, level, option_name, optval, optlen, cr));
 796  791  
 797  792          /* X/Open requires this check */
 798  793          if (so->so_state & SS_CANTSENDMORE && !xnet_skip_checks) {
 799  794                  SO_UNBLOCK_FALLBACK(so);
 800  795                  if (xnet_check_print)
 801  796                          printf("sockfs: X/Open setsockopt check => EINVAL\n");
 802  797                  return (EINVAL);
 803  798          }
 804  799  
↓ open down ↓ 64 lines elided ↑ open up ↑
 869  864      struct cred *cr, int32_t *rvalp)
 870  865  {
 871  866          int error = 0;
 872  867  
 873  868          SO_BLOCK_FALLBACK(so, SOP_IOCTL(so, cmd, arg, mode, cr, rvalp));
 874  869  
 875  870          /*
 876  871           * If there is a pending error, return error
 877  872           * This can happen if a non blocking operation caused an error.
 878  873           */
 879      -        if (so->so_error != 0) {
      874 +        if (so->so_error != 0 && (so->so_mode & SM_DEFERERR) == 0) {
 880  875                  mutex_enter(&so->so_lock);
 881  876                  error = sogeterr(so, B_TRUE);
 882  877                  mutex_exit(&so->so_lock);
 883  878                  if (error != 0)
 884  879                          goto done;
 885  880          }
 886  881  
 887  882          /*
 888  883           * calling strioc can result in the socket falling back to TPI,
 889  884           * if that is supported.
↓ open down ↓ 1068 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX