diff options
author | Mike Zeller <mike@mikezeller.net> | 2019-09-05 15:16:44 -0400 |
---|---|---|
committer | Mike Zeller <mike@mikezeller.net> | 2019-09-17 12:58:15 -0400 |
commit | 8f77bed5b9e3f96e1fcf344bef8e85a338e9da6b (patch) | |
tree | 0325a267e942343099e1e1471a38127457538e64 | |
parent | 496f2accfa0b13708051729f478a7bdaeff40d12 (diff) | |
download | illumos-joyent-8f77bed5b9e3f96e1fcf344bef8e85a338e9da6b.tar.gz |
OS-7980 lx getsockopt should return EOPNOTSUPP when TCP options are used with AF_UNIX
Reviewed by: Dan McDonald <danmcd@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Approved by: Jerry Jelinek <jerry.jelinek@joyent.com>
-rw-r--r-- | usr/src/uts/common/brand/lx/syscall/lx_socket.c | 34 |
1 files changed, 28 insertions, 6 deletions
diff --git a/usr/src/uts/common/brand/lx/syscall/lx_socket.c b/usr/src/uts/common/brand/lx/syscall/lx_socket.c index b25c5c465b..694549a4cb 100644 --- a/usr/src/uts/common/brand/lx/syscall/lx_socket.c +++ b/usr/src/uts/common/brand/lx/syscall/lx_socket.c @@ -3824,6 +3824,16 @@ lx_getsockopt_icmpv6(sonode_t *so, int optname, void *optval, return (error); } +/* + * When attempting to get socket options on AF_UNIX sockets we need to be a bit + * careful with the returned errno values. It turns out different OSes return + * different errno values here: + * - illumos: ENOPROTOOPT + * - Linux: EOPNOTSUPP + * - FreeBSD: EINVAL + * Therefore we remap ENOPROTOOPT to EOPNOTSUPP when a userland program attempts + * to get one of the various TCP_XXX options under this condition. + */ static int lx_getsockopt_tcp(sonode_t *so, int optname, void *optval, socklen_t *optlen) { @@ -3843,7 +3853,10 @@ lx_getsockopt_tcp(sonode_t *so, int optname, void *optval, socklen_t *optlen) * oath. */ if (*optlen < sizeof (int)) { - error = EINVAL; + return (EINVAL); + } + if (so->so_family == AF_UNIX) { + return (EOPNOTSUPP); } else { *intval = 0; } @@ -3865,12 +3878,12 @@ lx_getsockopt_tcp(sonode_t *so, int optname, void *optval, socklen_t *optlen) TCP_CONN_NOTIFY_THRESHOLD, &syn_backoff, &len, 0, cr); if (error != 0) - return (error); + goto out; error = socket_getsockopt(so, IPPROTO_TCP, TCP_CONN_ABORT_THRESHOLD, &syn_abortconn, &len, 0, cr); if (error != 0) - return (error); + goto out; syn_cnt = 0; while (syn_backoff < syn_abortconn) { @@ -3884,7 +3897,7 @@ lx_getsockopt_tcp(sonode_t *so, int optname, void *optval, socklen_t *optlen) *optlen = sizeof (int); } - return (error); + goto out; case LX_TCP_DEFER_ACCEPT: /* @@ -3902,7 +3915,7 @@ lx_getsockopt_tcp(sonode_t *so, int optname, void *optval, socklen_t *optlen) if ((error = socket_getsockopt(so, SOL_FILTER, FIL_LIST, fi, &len, 0, cr)) != 0) { *optlen = sizeof (int); - return (error); + goto out; } *intval = 0; @@ -3916,17 +3929,26 @@ lx_getsockopt_tcp(sonode_t *so, int optname, void *optval, socklen_t *optlen) } } *optlen = sizeof (int); - return (error); + goto out; default: break; } if (!lx_sockopt_lookup(sockopts_tbl, &optname, optlen)) { + if (optname <= sockopts_tbl.lpo_max && + so->so_family == AF_UNIX) { + return (EOPNOTSUPP); + } return (ENOPROTOOPT); } error = socket_getsockopt(so, IPPROTO_TCP, optname, optval, optlen, 0, cr); + +out: + if (error == ENOPROTOOPT && so->so_family == AF_UNIX) { + return (EOPNOTSUPP); + } return (error); } |