Print this page
8541 pfiles does not properly identify PF_KEY or PF_POLICY
Reviewed by: Mike Zeller <mike.zeller@joyent.com>
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
        
*** 20,29 ****
--- 20,32 ----
   */
  /*
   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
   * Use is subject to license terms.
   */
+ /*
+  * Copyright 2017 Joyent, Inc.
+  */
  
  #include <sys/param.h>
  #include <sys/types.h>
  #include <sys/stream.h>
  #include <sys/strsubr.h>
*** 890,899 ****
--- 893,977 ----
          }
          return (errno);
  }
  
  /*
+  * Handle STREAMS ioctl copyin for getsockname() for both PF_KEY and
+  * PF_POLICY.
+  */
+ void
+ keysock_spdsock_wput_iocdata(queue_t *q, mblk_t *mp, sa_family_t family)
+ {
+         mblk_t *mp1;
+         STRUCT_HANDLE(strbuf, sb);
+         /* What size of sockaddr do we need? */
+         const uint_t addrlen = sizeof (struct sockaddr);
+ 
+         /* We only handle TI_GET{MY,PEER}NAME (get{sock,peer}name()). */
+         switch (((struct iocblk *)mp->b_rptr)->ioc_cmd) {
+         case TI_GETMYNAME:
+         case TI_GETPEERNAME:
+                 break;
+         default:
+                 freemsg(mp);
+                 return;
+         }
+ 
+         switch (mi_copy_state(q, mp, &mp1)) {
+         case -1:
+                 return;
+         case MI_COPY_CASE(MI_COPY_IN, 1):
+                 break;
+         case MI_COPY_CASE(MI_COPY_OUT, 1):
+                 /*
+                  * The address has been copied out, so now
+                  * copyout the strbuf.
+                  */
+                 mi_copyout(q, mp);
+                 return;
+         case MI_COPY_CASE(MI_COPY_OUT, 2):
+                 /*
+                  * The address and strbuf have been copied out.
+                  * We're done, so just acknowledge the original
+                  * M_IOCTL.
+                  */
+                 mi_copy_done(q, mp, 0);
+                 return;
+         default:
+                 /*
+                  * Something strange has happened, so acknowledge
+                  * the original M_IOCTL with an EPROTO error.
+                  */
+                 mi_copy_done(q, mp, EPROTO);
+                 return;
+         }
+ 
+         /*
+          * Now we have the strbuf structure for TI_GET{MY,PEER}NAME. Next we
+          * copyout the requested address and then we'll copyout the strbuf.
+          * Regardless of sockname or peername, we just return a sockaddr with
+          * sa_family set.
+          */
+         STRUCT_SET_HANDLE(sb, ((struct iocblk *)mp->b_rptr)->ioc_flag,
+             (void *)mp1->b_rptr);
+ 
+         if (STRUCT_FGET(sb, maxlen) < addrlen) {
+                 mi_copy_done(q, mp, EINVAL);
+                 return;
+         }
+ 
+         mp1 = mi_copyout_alloc(q, mp, STRUCT_FGETP(sb, buf), addrlen, B_TRUE);
+         if (mp1 == NULL)
+                 return;
+ 
+         STRUCT_FSET(sb, len, addrlen);
+         ((struct sockaddr *)mp1->b_wptr)->sa_family = family;
+         mp1->b_wptr += addrlen;
+         mi_copyout(q, mp);
+ }
+ 
+ /*
   * Handle STREAMS messages.
   */
  static void
  keysock_wput_other(queue_t *q, mblk_t *mp)
  {
*** 952,966 ****
--- 1030,1057 ----
                          /* Not supported by keysock. */
                          keysock_err_ack(q, mp, TNOTSUPPORT, 0);
                          break;
                  }
                  return;
+         case M_IOCDATA:
+                 keysock_spdsock_wput_iocdata(q, mp, PF_KEY);
+                 return;
          case M_IOCTL:
                  iocp = (struct iocblk *)mp->b_rptr;
                  error = EINVAL;
  
                  switch (iocp->ioc_cmd) {
+                 case TI_GETMYNAME:
+                 case TI_GETPEERNAME:
+                         /*
+                          * For pfiles(1) observability with getsockname().
+                          * See keysock_spdsock_wput_iocdata() for the rest of
+                          * this.
+                          */
+                         mi_copyin(q, mp, NULL,
+                             SIZEOF_STRUCT(strbuf, iocp->ioc_flag));
+                         return;
                  case ND_SET:
                  case ND_GET:
                          if (nd_getset(q, keystack->keystack_g_nd, mp)) {
                                  qreply(q, mp);
                                  return;