From e69cf3dec8a20e2a39d015b45518fb04c7d18023 Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Wed, 31 May 2023 15:43:01 -0400 Subject: [PATCH] kernel_getsockname and kernel_getpeername dropped addrlen arg. v4.16-rc1-1-g9b2c45d479d0 This interface now returns (sizeof (addr)) on success, instead of 0. Therefore, we have to change the error condition detection. The compat for older kernels handles the addrlen check internally. Signed-off-by: Auke Kok --- kmod/src/Makefile.kernelcompat | 9 +++++++++ kmod/src/kernelcompat.h | 30 ++++++++++++++++++++++++++++++ kmod/src/net.c | 34 +++++++++++++--------------------- 3 files changed, 52 insertions(+), 21 deletions(-) diff --git a/kmod/src/Makefile.kernelcompat b/kmod/src/Makefile.kernelcompat index 97840bf5..ca408a1a 100644 --- a/kmod/src/Makefile.kernelcompat +++ b/kmod/src/Makefile.kernelcompat @@ -158,3 +158,12 @@ endif ifneq (,$(shell grep 'int...get..const struct xattr_handler.*struct dentry.*dentry,' include/linux/xattr.h)) ccflags-y += -DKC_XATTR_STRUCT_XATTR_HANDLER=1 endif + +# +# v4.16-rc1-1-g9b2c45d479d0 +# +# kernel_getsockname() and kernel_getpeername dropped addrlen arg +# +ifneq (,$(shell grep 'kernel_getsockname.*,$$' include/linux/net.h)) +ccflags-y += -DKC_KERNEL_GETSOCKNAME_ADDRLEN=1 +endif diff --git a/kmod/src/kernelcompat.h b/kmod/src/kernelcompat.h index 2df4ddfe..e3b93c66 100644 --- a/kmod/src/kernelcompat.h +++ b/kmod/src/kernelcompat.h @@ -222,4 +222,34 @@ struct kc_shrinker_wrapper { #endif /* KC_SHRINKER_SHRINK */ +#ifdef KC_KERNEL_GETSOCKNAME_ADDRLEN +#include +#include +static inline int kc_kernel_getsockname(struct socket *sock, struct sockaddr *addr) +{ + int addrlen = sizeof(struct sockaddr_in); + int ret = kernel_getsockname(sock, addr, &addrlen); + if (ret == 0 && addrlen != sizeof(struct sockaddr_in)) + return -EAFNOSUPPORT; + else if (ret < 0) + return ret; + + return sizeof(struct sockaddr_in); +} +static inline int kc_kernel_getpeername(struct socket *sock, struct sockaddr *addr) +{ + int addrlen = sizeof(struct sockaddr_in); + int ret = kernel_getpeername(sock, addr, &addrlen); + if (ret == 0 && addrlen != sizeof(struct sockaddr_in)) + return -EAFNOSUPPORT; + else if (ret < 0) + return ret; + + return sizeof(struct sockaddr_in); +} +#else +#define kc_kernel_getsockname(sock, addr) kernel_getsockname(sock, addr) +#define kc_kernel_getpeername(sock, addr) kernel_getpeername(sock, addr) +#endif + #endif diff --git a/kmod/src/net.c b/kmod/src/net.c index eab190da..c539fde1 100644 --- a/kmod/src/net.c +++ b/kmod/src/net.c @@ -897,7 +897,6 @@ static int sock_opts_and_names(struct scoutfs_net_connection *conn, struct socket *sock) { struct timeval tv; - int addrlen; int optval; int ret; @@ -947,23 +946,18 @@ static int sock_opts_and_names(struct scoutfs_net_connection *conn, if (ret) goto out; - addrlen = sizeof(struct sockaddr_in); - ret = kernel_getsockname(sock, (struct sockaddr *)&conn->sockname, - &addrlen); - if (ret == 0 && addrlen != sizeof(struct sockaddr_in)) - ret = -EAFNOSUPPORT; - if (ret) + ret = kc_kernel_getsockname(sock, (struct sockaddr *)&conn->sockname); + if (ret < 0) goto out; - addrlen = sizeof(struct sockaddr_in); - ret = kernel_getpeername(sock, (struct sockaddr *)&conn->peername, - &addrlen); - if (ret == 0 && addrlen != sizeof(struct sockaddr_in)) - ret = -EAFNOSUPPORT; - if (ret) + ret = kc_kernel_getpeername(sock, (struct sockaddr *)&conn->peername); + if (ret < 0) goto out; + ret = 0; + conn->last_peername = conn->peername; + out: return ret; } @@ -1471,20 +1465,18 @@ int scoutfs_net_bind(struct super_block *sb, goto out; ret = kernel_listen(sock, 255); - if (ret) + if (ret < 0) goto out; - addrlen = sizeof(struct sockaddr_in); - ret = kernel_getsockname(sock, (struct sockaddr *)&conn->sockname, - &addrlen); - if (ret == 0 && addrlen != sizeof(struct sockaddr_in)) - ret = -EAFNOSUPPORT; - if (ret) + ret = kc_kernel_getsockname(sock, (struct sockaddr *)&conn->sockname); + if (ret < 0) goto out; + ret = 0; + conn->sock = sock; *sin = conn->sockname; - ret = 0; + out: if (ret < 0 && sock) sock_release(sock);