From 84980ee0e625676805d84800a6fe2cffe228aec0 Mon Sep 17 00:00:00 2001 From: Rob Norris Date: Tue, 23 Jan 2024 16:34:49 +1100 Subject: [PATCH] Linux 6.8 compat: implement strlcpy fallback Linux has removed strlcpy in favour of strscpy. This implements a fallback implementation of strlcpy for this case. Reviewed-by: Brian Behlendorf Signed-off-by: Rob Norris Sponsored-by: https://despairlabs.com/sponsor/ Closes #15805 --- config/kernel-strlcpy.m4 | 47 ++++++++++++++++++++++++++ config/kernel.m4 | 4 +++ include/os/linux/spl/sys/string.h | 49 ++++++++++++++++++++++++++++ module/os/linux/spl/spl-kmem-cache.c | 1 + module/os/linux/spl/spl-kstat.c | 1 + module/os/linux/spl/spl-thread.c | 1 + module/os/linux/spl/spl-zone.c | 1 + 7 files changed, 104 insertions(+) create mode 100644 config/kernel-strlcpy.m4 diff --git a/config/kernel-strlcpy.m4 b/config/kernel-strlcpy.m4 new file mode 100644 index 000000000..c31cf52d7 --- /dev/null +++ b/config/kernel-strlcpy.m4 @@ -0,0 +1,47 @@ +dnl # +dnl # 6.8.x replaced strlcpy with strscpy. Check for both so we can provide +dnl # appropriate fallbacks. +dnl # +AC_DEFUN([ZFS_AC_KERNEL_SRC_STRLCPY], [ + ZFS_LINUX_TEST_SRC([kernel_has_strlcpy], [ + #include + ], [ + const char *src = "goodbye"; + char dst[32]; + size_t len; + len = strlcpy(dst, src, sizeof (dst)); + ]) +]) + +AC_DEFUN([ZFS_AC_KERNEL_SRC_STRSCPY], [ + ZFS_LINUX_TEST_SRC([kernel_has_strscpy], [ + #include + ], [ + const char *src = "goodbye"; + char dst[32]; + ssize_t len; + len = strscpy(dst, src, sizeof (dst)); + ]) +]) + +AC_DEFUN([ZFS_AC_KERNEL_STRLCPY], [ + AC_MSG_CHECKING([whether strlcpy() exists]) + ZFS_LINUX_TEST_RESULT([kernel_has_strlcpy], [ + AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_KERNEL_STRLCPY, 1, + [strlcpy() exists]) + ], [ + AC_MSG_RESULT([no]) + ]) +]) + +AC_DEFUN([ZFS_AC_KERNEL_STRSCPY], [ + AC_MSG_CHECKING([whether strscpy() exists]) + ZFS_LINUX_TEST_RESULT([kernel_has_strscpy], [ + AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_KERNEL_STRSCPY, 1, + [strscpy() exists]) + ], [ + AC_MSG_RESULT([no]) + ]) +]) diff --git a/config/kernel.m4 b/config/kernel.m4 index d25b65994..30bdd6579 100644 --- a/config/kernel.m4 +++ b/config/kernel.m4 @@ -149,6 +149,8 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_SRC], [ ZFS_AC_KERNEL_SRC_SYSFS ZFS_AC_KERNEL_SRC_SET_SPECIAL_STATE ZFS_AC_KERNEL_SRC_STANDALONE_LINUX_STDARG + ZFS_AC_KERNEL_SRC_STRLCPY + ZFS_AC_KERNEL_SRC_STRSCPY ZFS_AC_KERNEL_SRC_PAGEMAP_FOLIO_WAIT_BIT ZFS_AC_KERNEL_SRC_ADD_DISK ZFS_AC_KERNEL_SRC_KTHREAD @@ -294,6 +296,8 @@ AC_DEFUN([ZFS_AC_KERNEL_TEST_RESULT], [ ZFS_AC_KERNEL_SYSFS ZFS_AC_KERNEL_SET_SPECIAL_STATE ZFS_AC_KERNEL_STANDALONE_LINUX_STDARG + ZFS_AC_KERNEL_STRLCPY + ZFS_AC_KERNEL_STRSCPY ZFS_AC_KERNEL_PAGEMAP_FOLIO_WAIT_BIT ZFS_AC_KERNEL_ADD_DISK ZFS_AC_KERNEL_KTHREAD diff --git a/include/os/linux/spl/sys/string.h b/include/os/linux/spl/sys/string.h index 38134dcf4..f44bf23eb 100644 --- a/include/os/linux/spl/sys/string.h +++ b/include/os/linux/spl/sys/string.h @@ -1 +1,50 @@ +/* + * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC. + * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). + * Written by Brian Behlendorf . + * UCRL-CODE-235197 + * + * This file is part of the SPL, Solaris Porting Layer. + * + * The SPL is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * The SPL is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with the SPL. If not, see . + */ + +#ifndef _SPL_STRING_H +#define _SPL_STRING_H + #include + +/* Fallbacks for kernel missing strlcpy */ +#ifndef HAVE_KERNEL_STRLCPY + +#if defined(HAVE_KERNEL_STRSCPY) +/* + * strscpy is strlcpy, but returns an error on truncation. strlcpy is defined + * to return strlen(src), so detect error and override it. + */ +static inline size_t +strlcpy(char *dest, const char *src, size_t size) +{ + ssize_t ret = strscpy(dest, src, size); + if (likely(ret > 0)) + return ((size_t)ret); + return (strlen(src)); +} +#else +#error "no strlcpy fallback available" +#endif + +#endif /* HAVE_KERNEL_STRLCPY */ + +#endif /* _SPL_STRING_H */ diff --git a/module/os/linux/spl/spl-kmem-cache.c b/module/os/linux/spl/spl-kmem-cache.c index 4b1508171..42821ad60 100644 --- a/module/os/linux/spl/spl-kmem-cache.c +++ b/module/os/linux/spl/spl-kmem-cache.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include diff --git a/module/os/linux/spl/spl-kstat.c b/module/os/linux/spl/spl-kstat.c index 430858114..ad553a73a 100644 --- a/module/os/linux/spl/spl-kstat.c +++ b/module/os/linux/spl/spl-kstat.c @@ -32,6 +32,7 @@ #include #include #include +#include static kmutex_t kstat_module_lock; static struct list_head kstat_module_list; diff --git a/module/os/linux/spl/spl-thread.c b/module/os/linux/spl/spl-thread.c index b4ef86a5e..ee3eb4690 100644 --- a/module/os/linux/spl/spl-thread.c +++ b/module/os/linux/spl/spl-thread.c @@ -26,6 +26,7 @@ #include #include #include +#include /* * Thread interfaces diff --git a/module/os/linux/spl/spl-zone.c b/module/os/linux/spl/spl-zone.c index e821fbb4f..d0d0cca15 100644 --- a/module/os/linux/spl/spl-zone.c +++ b/module/os/linux/spl/spl-zone.c @@ -30,6 +30,7 @@ #include #include #include +#include #if defined(CONFIG_USER_NS) #include