From f8cbe0e7fd4f172d5ed456a8f7425890e1ea20cd Mon Sep 17 00:00:00 2001 From: Dan McDonald Date: Wed, 26 Jul 2017 11:40:04 -0400 Subject: [PATCH] 8541 pfiles does not properly identify PF_KEY or PF_POLICY Reviewed by: Mike Zeller Reviewed by: Patrick Mooney Reviewed by: Yuri Pankov Approved by: Richard Lowe --- usr/src/cmd/ptools/pfiles/pfiles.c | 4 +- usr/src/uts/common/inet/ip/keysock.c | 114 ++++++++++++++++++++++----- usr/src/uts/common/inet/ip/spdsock.c | 15 ++++ usr/src/uts/common/inet/ipsec_impl.h | 4 + usr/src/uts/intel/ia32/ml/modstubs.s | 7 +- usr/src/uts/sparc/ml/modstubs.s | 3 +- 6 files changed, 123 insertions(+), 24 deletions(-) diff --git a/usr/src/cmd/ptools/pfiles/pfiles.c b/usr/src/cmd/ptools/pfiles/pfiles.c index 0b8404780674..d7142809f73f 100644 --- a/usr/src/cmd/ptools/pfiles/pfiles.c +++ b/usr/src/cmd/ptools/pfiles/pfiles.c @@ -24,7 +24,7 @@ * Copyright 2012 DEY Storage Systems, Inc. All rights reserved. */ /* - * Copyright (c) 2013 Joyent, Inc. All Rights reserved. + * Copyright (c) 2017 Joyent, Inc. All Rights reserved. */ #include @@ -556,6 +556,8 @@ show_sockaddr(const char *str, struct sockaddr *sa, socklen_t len) case AF_GOSIP: p = "AF_GOSIP"; break; case AF_IPX: p = "AF_IPX"; break; case AF_ROUTE: p = "AF_ROUTE"; break; + case AF_KEY: p = "AF_KEY"; break; + case AF_POLICY: p = "AF_POLICY"; break; case AF_LINK: p = "AF_LINK"; break; } diff --git a/usr/src/uts/common/inet/ip/keysock.c b/usr/src/uts/common/inet/ip/keysock.c index c05c147b4bbd..3567710fdafd 100644 --- a/usr/src/uts/common/inet/ip/keysock.c +++ b/usr/src/uts/common/inet/ip/keysock.c @@ -22,6 +22,9 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2017 Joyent, Inc. + */ #include #include @@ -314,11 +317,7 @@ keysock_plumb_ipsec(netstack_t *ns) /* ARGSUSED */ static int -keysock_param_get(q, mp, cp, cr) - queue_t *q; - mblk_t *mp; - caddr_t cp; - cred_t *cr; +keysock_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr) { keysockparam_t *keysockpa = (keysockparam_t *)cp; uint_t value; @@ -336,12 +335,7 @@ keysock_param_get(q, mp, cp, cr) /* This routine sets an NDD variable in a keysockparam_t structure. */ /* ARGSUSED */ static int -keysock_param_set(q, mp, value, cp, cr) - queue_t *q; - mblk_t *mp; - char *value; - caddr_t cp; - cred_t *cr; +keysock_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *cr) { ulong_t new_value; keysockparam_t *keysockpa = (keysockparam_t *)cp; @@ -775,9 +769,7 @@ keysock_capability_req(queue_t *q, mblk_t *mp) * The current state of the stream is copied from keysock_state. */ static void -keysock_info_req(q, mp) - queue_t *q; - mblk_t *mp; +keysock_info_req(queue_t *q, mblk_t *mp) { mp = tpi_ack_alloc(mp, sizeof (struct T_info_ack), M_PCPROTO, T_INFO_ACK); @@ -794,11 +786,7 @@ keysock_info_req(q, mp) * upstream. */ static void -keysock_err_ack(q, mp, t_error, sys_error) - queue_t *q; - mblk_t *mp; - int t_error; - int sys_error; +keysock_err_ack(queue_t *q, mblk_t *mp, int t_error, int sys_error) { if ((mp = mi_tpi_err_ack_alloc(mp, t_error, sys_error)) != NULL) qreply(q, mp); @@ -891,6 +879,81 @@ keysock_opt_set(queue_t *q, uint_t mgmt_flags, int level, 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. */ @@ -954,11 +1017,24 @@ keysock_wput_other(queue_t *q, mblk_t *mp) 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)) { diff --git a/usr/src/uts/common/inet/ip/spdsock.c b/usr/src/uts/common/inet/ip/spdsock.c index be1c696018db..0703ec931b38 100644 --- a/usr/src/uts/common/inet/ip/spdsock.c +++ b/usr/src/uts/common/inet/ip/spdsock.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Joyent, Inc. */ #include @@ -34,6 +35,7 @@ #include #define _SUN_TPI_VERSION 2 #include +#include #include #include #include @@ -3404,11 +3406,24 @@ spdsock_wput_other(queue_t *q, mblk_t *mp) break; } return; + case M_IOCDATA: + keysock_spdsock_wput_iocdata(q, mp, PF_POLICY); + 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, spds->spds_g_nd, mp)) { diff --git a/usr/src/uts/common/inet/ipsec_impl.h b/usr/src/uts/common/inet/ipsec_impl.h index 8c4f222898cb..80e35e6ad40a 100644 --- a/usr/src/uts/common/inet/ipsec_impl.h +++ b/usr/src/uts/common/inet/ipsec_impl.h @@ -22,6 +22,7 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * Copyright (c) 2012 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Joyent, Inc. */ #ifndef _INET_IPSEC_IMPL_H @@ -110,6 +111,9 @@ extern "C" { extern boolean_t keysock_extended_reg(netstack_t *); extern uint32_t keysock_next_seq(netstack_t *); +/* Common-code for spdsock and keysock. */ +extern void keysock_spdsock_wput_iocdata(queue_t *, mblk_t *, sa_family_t); + /* * Locking for ipsec policy rules: * diff --git a/usr/src/uts/intel/ia32/ml/modstubs.s b/usr/src/uts/intel/ia32/ml/modstubs.s index 782076c09848..76570f88555f 100644 --- a/usr/src/uts/intel/ia32/ml/modstubs.s +++ b/usr/src/uts/intel/ia32/ml/modstubs.s @@ -21,7 +21,7 @@ /* * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2015, Joyent, Inc. All rights reserved. + * Copyright (c) 2017, Joyent, Inc. All rights reserved. */ #include @@ -518,7 +518,7 @@ fcnname/**/_info: \ WSTUB(ipsecah, ipsecah_icmp_error, nomod_zero); END_MODULE(ipsecah); #endif - + #ifndef IPSECESP_MODULE MODULE(ipsecesp,drv); WSTUB(ipsecesp, ipsecesp_fill_defs, nomod_zero); @@ -529,9 +529,10 @@ fcnname/**/_info: \ WSTUB(ipsecesp, ipsecesp_send_keepalive, nomod_zero); END_MODULE(ipsecesp); #endif - + #ifndef KEYSOCK_MODULE MODULE(keysock, drv); + WSTUB(keysock, keysock_spdsock_wput_iocdata, nomod_void); WSTUB(keysock, keysock_plumb_ipsec, nomod_zero); WSTUB(keysock, keysock_extended_reg, nomod_zero); WSTUB(keysock, keysock_next_seq, nomod_zero); diff --git a/usr/src/uts/sparc/ml/modstubs.s b/usr/src/uts/sparc/ml/modstubs.s index 845705dba88f..658ba929d205 100644 --- a/usr/src/uts/sparc/ml/modstubs.s +++ b/usr/src/uts/sparc/ml/modstubs.s @@ -21,8 +21,8 @@ /* * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2015, Joyent, Inc. All rights reserved. * Copyright 2016 Nexenta Systems, Inc. + * Copyright (c) 2017, Joyent, Inc. All rights reserved. */ #if !defined(lint) @@ -422,6 +422,7 @@ stubs_base: #ifndef KEYSOCK_MODULE MODULE(keysock,drv); + WSTUB(keysock, keysock_spdsock_wput_iocdata, nomod_void); WSTUB(keysock, keysock_plumb_ipsec, nomod_zero); WSTUB(keysock, keysock_extended_reg, nomod_zero); WSTUB(keysock, keysock_next_seq, nomod_zero);