Print this page
1631 kernel panic in tcp_input_data

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/inet/tcp/tcp_input.c
          +++ new/usr/src/uts/common/inet/tcp/tcp_input.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) 2010, Oracle and/or its affiliates. All rights reserved.
       24 + * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
  24   25   */
  25   26  
  26   27  /* This file contains all TCP input processing functions. */
  27   28  
  28   29  #include <sys/types.h>
  29   30  #include <sys/stream.h>
  30   31  #include <sys/strsun.h>
  31   32  #include <sys/strsubr.h>
  32   33  #include <sys/stropts.h>
  33   34  #include <sys/strlog.h>
↓ open down ↓ 2189 lines elided ↑ open up ↑
2223 2224                          tcp->tcp_ip_forward_progress = B_FALSE;
2224 2225                          connp->conn_ixa->ixa_flags |= IXAF_REACH_CONF;
2225 2226                  } else {
2226 2227                          connp->conn_ixa->ixa_flags &= ~IXAF_REACH_CONF;
2227 2228                  }
2228 2229                  return (mp1);
2229 2230          }
2230 2231  }
2231 2232  
2232 2233  /*
     2234 + * Dummy socket upcalls for if/when the conn_t gets detached from a
     2235 + * direct-callback sonode via a user-driven close().  Easy to catch with
     2236 + * DTrace FBT, and should be mostly harmless.
     2237 + */
     2238 +
     2239 +/* ARGSUSED */
     2240 +static sock_upper_handle_t
     2241 +tcp_dummy_newconn(sock_upper_handle_t x, sock_lower_handle_t y,
     2242 +    sock_downcalls_t *z, cred_t *cr, pid_t pid, sock_upcalls_t **ignored)
     2243 +{
     2244 +        ASSERT(0);      /* Panic in debug, otherwise ignore. */
     2245 +        return (NULL);
     2246 +}
     2247 +
     2248 +/* ARGSUSED */
     2249 +static void
     2250 +tcp_dummy_connected(sock_upper_handle_t x, sock_connid_t y, cred_t *cr,
     2251 +    pid_t pid)
     2252 +{
     2253 +        ASSERT(x == NULL);
     2254 +        /* Normally we'd crhold(cr) and attach it to socket state. */
     2255 +        /* LINTED */
     2256 +}
     2257 +
     2258 +/* ARGSUSED */
     2259 +static int
     2260 +tcp_dummy_disconnected(sock_upper_handle_t x, sock_connid_t y, int blah)
     2261 +{
     2262 +        ASSERT(0);      /* Panic in debug, otherwise ignore. */
     2263 +        return (-1);
     2264 +}
     2265 +
     2266 +/* ARGSUSED */
     2267 +static void
     2268 +tcp_dummy_opctl(sock_upper_handle_t x, sock_opctl_action_t y, uintptr_t blah)
     2269 +{
     2270 +        ASSERT(x == NULL);
     2271 +        /* We really want this one to be a harmless NOP for now. */
     2272 +        /* LINTED */
     2273 +}
     2274 +
     2275 +/* ARGSUSED */
     2276 +static ssize_t
     2277 +tcp_dummy_recv(sock_upper_handle_t x, mblk_t *mp, size_t len, int flags,
     2278 +    int *error, boolean_t *push)
     2279 +{
     2280 +        ASSERT(x == NULL);
     2281 +
     2282 +        /*
     2283 +         * Consume the message, set ESHUTDOWN, and return an error.
     2284 +         * Nobody's home!
     2285 +         */
     2286 +        freemsg(mp);
     2287 +        *error = ESHUTDOWN;
     2288 +        return (-1);
     2289 +}
     2290 +
     2291 +/* ARGSUSED */
     2292 +static void
     2293 +tcp_dummy_set_proto_props(sock_upper_handle_t x, struct sock_proto_props *y)
     2294 +{
     2295 +        ASSERT(0);      /* Panic in debug, otherwise ignore. */
     2296 +}
     2297 +
     2298 +/* ARGSUSED */
     2299 +static void
     2300 +tcp_dummy_txq_full(sock_upper_handle_t x, boolean_t y)
     2301 +{
     2302 +        ASSERT(0);      /* Panic in debug, otherwise ignore. */
     2303 +}
     2304 +
     2305 +/* ARGSUSED */
     2306 +static void
     2307 +tcp_dummy_signal_oob(sock_upper_handle_t x, ssize_t len)
     2308 +{
     2309 +        ASSERT(x == NULL);
     2310 +        /* Otherwise, this would signal socket state about OOB data. */
     2311 +}
     2312 +
     2313 +/* ARGSUSED */
     2314 +static void
     2315 +tcp_dummy_set_error(sock_upper_handle_t x, int err)
     2316 +{
     2317 +        ASSERT(0);      /* Panic in debug, otherwise ignore. */
     2318 +}
     2319 +
     2320 +/* ARGSUSED */
     2321 +static void
     2322 +tcp_dummy_onearg(sock_upper_handle_t x)
     2323 +{
     2324 +        ASSERT(0);      /* Panic in debug, otherwise ignore. */
     2325 +}
     2326 +
     2327 +static sock_upcalls_t tcp_dummy_upcalls = {
     2328 +        tcp_dummy_newconn,
     2329 +        tcp_dummy_connected,
     2330 +        tcp_dummy_disconnected,
     2331 +        tcp_dummy_opctl,
     2332 +        tcp_dummy_recv,
     2333 +        tcp_dummy_set_proto_props,
     2334 +        tcp_dummy_txq_full,
     2335 +        tcp_dummy_signal_oob,
     2336 +        tcp_dummy_onearg,
     2337 +        tcp_dummy_set_error,
     2338 +        tcp_dummy_onearg
     2339 +};
     2340 +
     2341 +/*
2233 2342   * Handle M_DATA messages from IP. Its called directly from IP via
2234 2343   * squeue for received IP packets.
2235 2344   *
2236 2345   * The first argument is always the connp/tcp to which the mp belongs.
2237 2346   * There are no exceptions to this rule. The caller has already put
2238 2347   * a reference on this connp/tcp and once tcp_input_data() returns,
2239 2348   * the squeue will do the refrele.
2240 2349   *
2241 2350   * The TH_SYN for the listener directly go to tcp_input_listener via
2242 2351   * squeue. ICMP errors go directly to tcp_icmp_input().
↓ open down ↓ 21 lines elided ↑ open up ↑
2264 2373          ip_pkt_t        ipp;
2265 2374          boolean_t       ofo_seg = B_FALSE; /* Out of order segment */
2266 2375          uint32_t        cwnd;
2267 2376          uint32_t        add;
2268 2377          int             npkt;
2269 2378          int             mss;
2270 2379          conn_t          *connp = (conn_t *)arg;
2271 2380          squeue_t        *sqp = (squeue_t *)arg2;
2272 2381          tcp_t           *tcp = connp->conn_tcp;
2273 2382          tcp_stack_t     *tcps = tcp->tcp_tcps;
     2383 +        sock_upcalls_t  *sockupcalls;
2274 2384  
2275 2385          /*
2276 2386           * RST from fused tcp loopback peer should trigger an unfuse.
2277 2387           */
2278 2388          if (tcp->tcp_fused) {
2279 2389                  TCP_STAT(tcps, tcp_fusion_aborted);
2280 2390                  tcp_unfuse(tcp);
2281 2391          }
2282 2392  
2283 2393          iphdr = mp->b_rptr;
↓ open down ↓ 105 lines elided ↑ open up ↑
2389 2499                           * pointer that is out of sequence, we expunge
2390 2500                           * the data.  This allows us to still register
2391 2501                           * the urgent mark and generate the M_PCSIG,
2392 2502                           * which we can do.
2393 2503                           */
2394 2504                          mp->b_wptr = (uchar_t *)tcpha + TCP_HDR_LENGTH(tcpha);
2395 2505                          seg_len = 0;
2396 2506                  }
2397 2507          }
2398 2508  
     2509 +        sockupcalls = connp->conn_upcalls;
     2510 +        /* A conn_t may have belonged to a now-closed socket.  Be careful. */
     2511 +        if (sockupcalls == NULL)
     2512 +                sockupcalls = &tcp_dummy_upcalls;
     2513 +
2399 2514          switch (tcp->tcp_state) {
2400 2515          case TCPS_SYN_SENT:
2401 2516                  if (connp->conn_final_sqp == NULL &&
2402 2517                      tcp_outbound_squeue_switch && sqp != NULL) {
2403 2518                          ASSERT(connp->conn_initial_sqp == connp->conn_sqp);
2404 2519                          connp->conn_final_sqp = sqp;
2405 2520                          if (connp->conn_final_sqp != connp->conn_sqp) {
2406 2521                                  DTRACE_PROBE1(conn__final__sqp__switch,
2407 2522                                      conn_t *, connp);
2408 2523                                  CONN_INC_REF(connp);
↓ open down ↓ 191 lines elided ↑ open up ↑
2600 2715  
2601 2716                                          if (!IPCL_IS_NONSTR(connp)) {
2602 2717                                                  /* Send up T_CONN_CON */
2603 2718                                                  if (ira->ira_cred != NULL) {
2604 2719                                                          mblk_setcred(mp1,
2605 2720                                                              ira->ira_cred,
2606 2721                                                              ira->ira_cpid);
2607 2722                                                  }
2608 2723                                                  putnext(connp->conn_rq, mp1);
2609 2724                                          } else {
2610      -                                                (*connp->conn_upcalls->
2611      -                                                    su_connected)
     2725 +                                                (*sockupcalls->su_connected)
2612 2726                                                      (connp->conn_upper_handle,
2613 2727                                                      tcp->tcp_connid,
2614 2728                                                      ira->ira_cred,
2615 2729                                                      ira->ira_cpid);
2616 2730                                                  freemsg(mp1);
2617 2731                                          }
2618 2732  
2619 2733                                          freemsg(mp);
2620 2734                                          return;
2621 2735                                  }
↓ open down ↓ 6 lines elided ↑ open up ↑
2628 2742                                   */
2629 2743                                  TCP_STAT(tcps, tcp_fusion_unfusable);
2630 2744                                  tcp->tcp_unfusable = B_TRUE;
2631 2745                                  if (!IPCL_IS_NONSTR(connp)) {
2632 2746                                          if (ira->ira_cred != NULL) {
2633 2747                                                  mblk_setcred(mp1, ira->ira_cred,
2634 2748                                                      ira->ira_cpid);
2635 2749                                          }
2636 2750                                          putnext(connp->conn_rq, mp1);
2637 2751                                  } else {
2638      -                                        (*connp->conn_upcalls->su_connected)
     2752 +                                        (*sockupcalls->su_connected)
2639 2753                                              (connp->conn_upper_handle,
2640 2754                                              tcp->tcp_connid, ira->ira_cred,
2641 2755                                              ira->ira_cpid);
2642 2756                                          freemsg(mp1);
2643 2757                                  }
2644 2758                          }
2645 2759  
2646 2760                          /*
2647 2761                           * Check to see if there is data to be sent.  If
2648 2762                           * yes, set the transmit flag.  Then check to see
↓ open down ↓ 353 lines elided ↑ open up ↑
3002 3116                           *
3003 3117                           * This prevents duplicate SIGURGS due to a "late"
3004 3118                           * zero-window probe when the T_EXDATA_IND has already
3005 3119                           * been sent up.
3006 3120                           */
3007 3121                          if ((flags & TH_URG) &&
3008 3122                              (!tcp->tcp_urp_last_valid || SEQ_GT(urp + seg_seq,
3009 3123                              tcp->tcp_urp_last))) {
3010 3124                                  if (IPCL_IS_NONSTR(connp)) {
3011 3125                                          if (!TCP_IS_DETACHED(tcp)) {
3012      -                                                (*connp->conn_upcalls->
3013      -                                                    su_signal_oob)
     3126 +                                                (*sockupcalls->su_signal_oob)
3014 3127                                                      (connp->conn_upper_handle,
3015 3128                                                      urp);
3016 3129                                          }
3017 3130                                  } else {
3018 3131                                          mp1 = allocb(0, BPRI_MED);
3019 3132                                          if (mp1 == NULL) {
3020 3133                                                  freemsg(mp);
3021 3134                                                  return;
3022 3135                                          }
3023 3136                                          if (!TCP_IS_DETACHED(tcp) &&
↓ open down ↓ 257 lines elided ↑ open up ↑
3281 3394                           * Neither is a T_EXDATA_IND mblk needed to be
3282 3395                           * prepended to the urgent data. The urgent data is
3283 3396                           * delivered using the su_recv upcall, where we set
3284 3397                           * the MSG_OOB flag to indicate that it is urg data.
3285 3398                           *
3286 3399                           * Neither TH_SEND_URP_MARK nor TH_MARKNEXT_NEEDED
3287 3400                           * are used by non-STREAMS sockets.
3288 3401                           */
3289 3402                          if (IPCL_IS_NONSTR(connp)) {
3290 3403                                  if (!TCP_IS_DETACHED(tcp)) {
3291      -                                        (*connp->conn_upcalls->su_signal_oob)
     3404 +                                        (*sockupcalls->su_signal_oob)
3292 3405                                              (connp->conn_upper_handle, urp);
3293 3406                                  }
3294 3407                          } else {
3295 3408                                  /*
3296 3409                                   * If we haven't generated the signal yet for
3297 3410                                   * this urgent pointer value, do it now.  Also,
3298 3411                                   * send up a zero-length M_DATA indicating
3299 3412                                   * whether or not this is the mark. The latter
3300 3413                                   * is not needed when a T_EXDATA_IND is sent up.
3301 3414                                   * However, if there are allocation failures
↓ open down ↓ 138 lines elided ↑ open up ↑
3440 3553                                  tcp_input_data(connp, mp, NULL, ira);
3441 3554                                  return;
3442 3555                          }
3443 3556                          /*
3444 3557                           * This segment contains only the urgent byte.  We
3445 3558                           * have to allocate the T_exdata_ind, if we can.
3446 3559                           */
3447 3560                          if (IPCL_IS_NONSTR(connp)) {
3448 3561                                  int error;
3449 3562  
3450      -                                (*connp->conn_upcalls->su_recv)
     3563 +                                (*sockupcalls->su_recv)
3451 3564                                      (connp->conn_upper_handle, mp, seg_len,
3452 3565                                      MSG_OOB, &error, NULL);
3453 3566                                  /*
3454 3567                                   * We should never be in middle of a
3455 3568                                   * fallback, the squeue guarantees that.
3456 3569                                   */
3457 3570                                  ASSERT(error != EOPNOTSUPP);
3458 3571                                  mp = NULL;
3459 3572                                  goto update_ack;
3460 3573                          } else if (!tcp->tcp_urp_mp) {
↓ open down ↓ 1158 lines elided ↑ open up ↑
4619 4732                          return;
4620 4733          }
4621 4734  
4622 4735          if (IPCL_IS_NONSTR(connp)) {
4623 4736                  /*
4624 4737                   * Non-STREAMS socket
4625 4738                   */
4626 4739                  boolean_t push = flags & (TH_PUSH|TH_FIN);
4627 4740                  int error;
4628 4741  
4629      -                if ((*connp->conn_upcalls->su_recv)(
4630      -                    connp->conn_upper_handle,
     4742 +                if ((*sockupcalls->su_recv)(connp->conn_upper_handle,
4631 4743                      mp, seg_len, 0, &error, &push) <= 0) {
4632 4744                          /*
4633 4745                           * We should never be in middle of a
4634 4746                           * fallback, the squeue guarantees that.
4635 4747                           */
4636 4748                          ASSERT(error != EOPNOTSUPP);
4637 4749                          if (error == ENOSPC)
4638 4750                                  tcp->tcp_rwnd -= seg_len;
4639 4751                  } else if (push) {
4640 4752                          /* PUSH bit set and sockfs is not flow controlled */
↓ open down ↓ 221 lines elided ↑ open up ↑
4862 4974                   * case the ordrel will be sent when tcp_accept_finish runs.
4863 4975                   * Note that for non-STREAMS we make an upcall even if it is an
4864 4976                   * eager, because we have an upper handle to send it to.
4865 4977                   */
4866 4978                  ASSERT(IPCL_IS_NONSTR(connp) || tcp->tcp_listener == NULL);
4867 4979                  ASSERT(!tcp->tcp_detached);
4868 4980  
4869 4981                  if (IPCL_IS_NONSTR(connp)) {
4870 4982                          ASSERT(tcp->tcp_ordrel_mp == NULL);
4871 4983                          tcp->tcp_ordrel_done = B_TRUE;
4872      -                        (*connp->conn_upcalls->su_opctl)
4873      -                            (connp->conn_upper_handle, SOCK_OPCTL_SHUT_RECV, 0);
     4984 +                        (*sockupcalls->su_opctl)(connp->conn_upper_handle,
     4985 +                            SOCK_OPCTL_SHUT_RECV, 0);
4874 4986                          goto done;
4875 4987                  }
4876 4988  
4877 4989                  if (tcp->tcp_rcv_list != NULL) {
4878 4990                          /*
4879 4991                           * Push any mblk(s) enqueued from co processing.
4880 4992                           */
4881 4993                          flags |= tcp_rcv_drain(tcp);
4882 4994                  }
4883 4995                  ASSERT(tcp->tcp_rcv_list == NULL || tcp->tcp_fused_sigurg);
↓ open down ↓ 808 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX