diff options
| author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2018-04-12 20:08:07 +0000 |
|---|---|---|
| committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2018-04-12 20:08:52 +0000 |
| commit | 99dda62835ffd7e81816de700276a4ec1420691e (patch) | |
| tree | ac62bc616a63587a0880a18277e8a89811b32d66 | |
| parent | 4dae3ebd73596b3ad87cb2e26db5cafbe2c3b053 (diff) | |
| download | illumos-joyent-99dda62835ffd7e81816de700276a4ec1420691e.tar.gz | |
OS-6575 panic from lxpr_format_tcp
Reviewed by: Dan McDonald <danmcd@joyent.com>
Approved by: Dan McDonald <danmcd@joyent.com>
| -rw-r--r-- | usr/src/uts/common/brand/lx/procfs/lx_prvnops.c | 44 |
1 files changed, 30 insertions, 14 deletions
diff --git a/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c b/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c index 71e608c0d0..15203cee91 100644 --- a/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c +++ b/usr/src/uts/common/brand/lx/procfs/lx_prvnops.c @@ -3528,6 +3528,7 @@ lxpr_format_tcp(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf, ushort_t ipver) conn_t *connp; netstack_t *ns; ip_stack_t *ipst; + int sonode_shift; ASSERT(ipver == IPV4_VERSION || ipver == IPV6_VERSION); if (ipver == IPV4_VERSION) { @@ -3566,15 +3567,16 @@ lxpr_format_tcp(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf, ushort_t ipver) return; ipst = ns->netstack_ip; + sonode_shift = highbit(sizeof (sonode_t)); + for (i = 0; i < CONN_G_HASH_SIZE; i++) { connfp = &ipst->ips_ipcl_globalhash_fanout[i]; connp = NULL; while ((connp = ipcl_get_next_conn(connfp, connp, IPCL_TCPCONN)) != NULL) { tcp_t *tcp; - vattr_t attr; + ino_t inode; sonode_t *so = (sonode_t *)connp->conn_upper_handle; - vnode_t *vp = (so != NULL) ? so->so_vnode : NULL; if (connp->conn_ipversion != ipver) continue; tcp = connp->conn_tcp; @@ -3603,10 +3605,16 @@ lxpr_format_tcp(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf, ushort_t ipver) ntohs(connp->conn_fport)); } - /* fetch the simulated inode for the socket */ - if (vp == NULL || - VOP_GETATTR(vp, &attr, 0, CRED(), NULL) != 0) - attr.va_nodeid = 0; + /* + * We cannot use VOP_GETATTR here to fetch the + * simulated inode for the socket via the + * so->so_vnode. This is because there is a (very + * tight) race for when the v_vfsp is set on the + * sonode's vnode. However, all we really want here is + * the inode number, which we can compute using the + * same algorithm as socket_vop_getattr. + */ + inode = ((ino_t)so >> sonode_shift) & 0xFFFF; lxpr_uiobuf_printf(uiobuf, "%02X %08X:%08X %02X:%08X %08X " @@ -3618,7 +3626,7 @@ lxpr_format_tcp(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf, ushort_t ipver) connp->conn_cred->cr_uid, 0, /* timeout */ /* inode + more */ - (ino_t)attr.va_nodeid, 0, NULL, 0, 0, 0, 0, 0); + inode, 0, NULL, 0, 0, 0, 0, 0); } } netstack_rele(ns); @@ -3644,6 +3652,7 @@ lxpr_format_udp(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf, ushort_t ipver) conn_t *connp; netstack_t *ns; ip_stack_t *ipst; + int sonode_shift; ASSERT(ipver == IPV4_VERSION || ipver == IPV6_VERSION); if (ipver == IPV4_VERSION) { @@ -3682,16 +3691,17 @@ lxpr_format_udp(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf, ushort_t ipver) return; ipst = ns->netstack_ip; + sonode_shift = highbit(sizeof (sonode_t)); + for (i = 0; i < CONN_G_HASH_SIZE; i++) { connfp = &ipst->ips_ipcl_globalhash_fanout[i]; connp = NULL; while ((connp = ipcl_get_next_conn(connfp, connp, IPCL_UDPCONN)) != NULL) { udp_t *udp; + ino_t inode; int state = 0; - vattr_t attr; sonode_t *so = (sonode_t *)connp->conn_upper_handle; - vnode_t *vp = (so != NULL) ? so->so_vnode : NULL; if (connp->conn_ipversion != ipver) continue; udp = connp->conn_udp; @@ -3730,10 +3740,16 @@ lxpr_format_udp(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf, ushort_t ipver) break; } - /* fetch the simulated inode for the socket */ - if (vp == NULL || - VOP_GETATTR(vp, &attr, 0, CRED(), NULL) != 0) - attr.va_nodeid = 0; + /* + * We cannot use VOP_GETATTR here to fetch the + * simulated inode for the socket via the + * so->so_vnode. This is because there is a (very + * tight) race for when the v_vfsp is set on the + * sonode's vnode. However, all we really want here is + * the inode number, which we can compute using the + * same algorithm as socket_vop_getattr. + */ + inode = ((ino_t)so >> sonode_shift) & 0xFFFF; lxpr_uiobuf_printf(uiobuf, "%02X %08X:%08X %02X:%08X %08X " @@ -3745,7 +3761,7 @@ lxpr_format_udp(lxpr_node_t *lxpnp, lxpr_uiobuf_t *uiobuf, ushort_t ipver) connp->conn_cred->cr_uid, 0, /* timeout */ /* inode, ref, pointer, drops */ - (ino_t)attr.va_nodeid, 0, NULL, 0); + inode, 0, NULL, 0); } } netstack_rele(ns); |
