summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Zeller <mike@mikezeller.net>2019-09-05 15:16:44 -0400
committerMike Zeller <mike@mikezeller.net>2019-09-17 12:58:15 -0400
commit8f77bed5b9e3f96e1fcf344bef8e85a338e9da6b (patch)
tree0325a267e942343099e1e1471a38127457538e64
parent496f2accfa0b13708051729f478a7bdaeff40d12 (diff)
downloadillumos-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.c34
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);
}