From 36dc7c346bc0f8f933289a47d166f1e3762ff167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Sat, 10 Apr 2021 03:27:26 +0200 Subject: [PATCH 1/5] module/zfs/zvol.c: purge unused zvol_volmode_cb_arg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ahelenia Ziemiańska --- module/zfs/zvol.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/module/zfs/zvol.c b/module/zfs/zvol.c index b6609363f047..23df0e1541a3 100644 --- a/module/zfs/zvol.c +++ b/module/zfs/zvol.c @@ -1383,10 +1383,6 @@ zvol_set_snapdev_impl(char *name, uint64_t snapdev) spl_fstrans_unmark(cookie); } -typedef struct zvol_volmode_cb_arg { - uint64_t volmode; -} zvol_volmode_cb_arg_t; - static void zvol_set_volmode_impl(char *name, uint64_t volmode) { From 6b251adc24a2ee2603c0cc83ac4206806f0b0954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Sat, 10 Apr 2021 03:28:53 +0200 Subject: [PATCH 2/5] libspl: lift common bits of getexecname() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ahelenia Ziemiańska --- lib/libspl/Makefile.am | 2 + lib/libspl/getexecname.c | 59 +++++++++++++++++++++++++++++ lib/libspl/libspl_impl.h | 24 ++++++++++++ lib/libspl/os/freebsd/getexecname.c | 49 +++++------------------- lib/libspl/os/linux/getexecname.c | 37 +++--------------- 5 files changed, 99 insertions(+), 72 deletions(-) create mode 100644 lib/libspl/getexecname.c create mode 100644 lib/libspl/libspl_impl.h diff --git a/lib/libspl/Makefile.am b/lib/libspl/Makefile.am index d27932aff981..fbde2b57f08b 100644 --- a/lib/libspl/Makefile.am +++ b/lib/libspl/Makefile.am @@ -21,6 +21,8 @@ libspl_assert_la_SOURCES = \ assert.c USER_C = \ + libspl_impl.h \ + getexecname.c \ list.c \ mkdirp.c \ page.c \ diff --git a/lib/libspl/getexecname.c b/lib/libspl/getexecname.c new file mode 100644 index 000000000000..dca7162034f7 --- /dev/null +++ b/lib/libspl/getexecname.c @@ -0,0 +1,59 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + + +#include +#include +#include +#include +#include +#include "libspl_impl.h" + + +const char * +getexecname(void) +{ + static char execname[PATH_MAX + 1] = ""; + static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; + + char *ptr = execname; + ssize_t rc; + + (void) pthread_mutex_lock(&mtx); + + if (strlen(execname) == 0) { + rc = getexecname_impl(execname); + if (rc == -1) { + execname[0] = '\0'; + ptr = NULL; + } else { + execname[rc] = '\0'; + } + } + + (void) pthread_mutex_unlock(&mtx); + return (ptr); +} diff --git a/lib/libspl/libspl_impl.h b/lib/libspl/libspl_impl.h new file mode 100644 index 000000000000..cda56e64c962 --- /dev/null +++ b/lib/libspl/libspl_impl.h @@ -0,0 +1,24 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License, Version 1.0 only + * (the "License"). You may not use this file except in compliance + * with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ + + +extern ssize_t getexecname_impl(char *execname); diff --git a/lib/libspl/os/freebsd/getexecname.c b/lib/libspl/os/freebsd/getexecname.c index 2b057cc73016..256b28c1b70e 100644 --- a/lib/libspl/os/freebsd/getexecname.c +++ b/lib/libspl/os/freebsd/getexecname.c @@ -20,52 +20,21 @@ * CDDL HEADER END */ - -#include +#include #include -#include -#include -#include #include #include #include -#include +#include "../../libspl_impl.h" -const char * -getexecname(void) +__attribute__((visibility("hidden"))) ssize_t +getexecname_impl(char *execname) { - static char execname[PATH_MAX + 1] = ""; - static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; - char *ptr = NULL; - ssize_t rc; - - (void) pthread_mutex_lock(&mtx); - - if (strlen(execname) == 0) { - int error, name[4]; - size_t len; + size_t len = PATH_MAX; + int name[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; - name[0] = CTL_KERN; - name[1] = KERN_PROC; - name[2] = KERN_PROC_PATHNAME; - name[3] = -1; - len = PATH_MAX; - error = sysctl(name, nitems(name), execname, &len, NULL, 0); - if (error != 0) { - rc = -1; - } else { - rc = len; - } - if (rc == -1) { - execname[0] = '\0'; - } else { - execname[rc] = '\0'; - ptr = execname; - } - } else { - ptr = execname; - } + if (sysctl(name, nitems(name), execname, &len, NULL, 0) != 0) + return (-1); - (void) pthread_mutex_unlock(&mtx); - return (ptr); + return (len); } diff --git a/lib/libspl/os/linux/getexecname.c b/lib/libspl/os/linux/getexecname.c index 6352a1a34015..a640556bcbec 100644 --- a/lib/libspl/os/linux/getexecname.c +++ b/lib/libspl/os/linux/getexecname.c @@ -19,41 +19,14 @@ * * CDDL HEADER END */ -/* - * Copyright 2007 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - #include -#include -#include -#include +#include #include +#include "../../libspl_impl.h" -const char * -getexecname(void) +__attribute__((visibility("hidden"))) ssize_t +getexecname_impl(char *execname) { - static char execname[PATH_MAX + 1] = ""; - static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; - char *ptr = NULL; - ssize_t rc; - - (void) pthread_mutex_lock(&mtx); - - if (strlen(execname) == 0) { - rc = readlink("/proc/self/exe", - execname, sizeof (execname) - 1); - if (rc == -1) { - execname[0] = '\0'; - } else { - execname[rc] = '\0'; - ptr = execname; - } - } else { - ptr = execname; - } - - (void) pthread_mutex_unlock(&mtx); - return (ptr); + return (readlink("/proc/self/exe", execname, PATH_MAX)); } From 3a40d129ba8492324835aa555069f7b543eb8e5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Sun, 11 Apr 2021 01:18:40 +0200 Subject: [PATCH 3/5] linux/spl: base proc_dohostid() on proc_dostring() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes /proc/sys/kernel/spl/hostid on kernels with mainline commit 32927393dc1ccd60fb2bdc05b9e8e88753761469 ("sysctl: pass kernel pointers to ->proc_handler") ‒ 5.7-rc1 and up The access_ok() check in copy_to_user() in proc_copyout_string() would always fail, so all userspace reads and writes would fail with EINVAL proc_dostring() strips only the final new-line, but simple_strtoul() doesn't actually need a back-trimmed string ‒ writing "012345678 \n" is still allowed, as is "012345678zupsko", &c. This alters what happens when an invalid value is written ‒ previously it'd get set to what-ever simple_strtoul() returned (probably 0, thereby resetting it to default), now it does nothing Signed-off-by: Ahelenia Ziemiańska Closes #11878 --- module/os/linux/spl/spl-proc.c | 93 +++++++--------------------------- 1 file changed, 17 insertions(+), 76 deletions(-) diff --git a/module/os/linux/spl/spl-proc.c b/module/os/linux/spl/spl-proc.c index 3e58598d43f8..63cd7cc2e5bc 100644 --- a/module/os/linux/spl/spl-proc.c +++ b/module/os/linux/spl/spl-proc.c @@ -53,60 +53,6 @@ static struct proc_dir_entry *proc_spl_taskq_all = NULL; static struct proc_dir_entry *proc_spl_taskq = NULL; struct proc_dir_entry *proc_spl_kstat = NULL; -static int -proc_copyin_string(char *kbuffer, int kbuffer_size, const char *ubuffer, - int ubuffer_size) -{ - int size; - - if (ubuffer_size > kbuffer_size) - return (-EOVERFLOW); - - if (copy_from_user((void *)kbuffer, (void *)ubuffer, ubuffer_size)) - return (-EFAULT); - - /* strip trailing whitespace */ - size = strnlen(kbuffer, ubuffer_size); - while (size-- >= 0) - if (!isspace(kbuffer[size])) - break; - - /* empty string */ - if (size < 0) - return (-EINVAL); - - /* no space to terminate */ - if (size == kbuffer_size) - return (-EOVERFLOW); - - kbuffer[size + 1] = 0; - return (0); -} - -static int -proc_copyout_string(char *ubuffer, int ubuffer_size, const char *kbuffer, - char *append) -{ - /* - * NB if 'append' != NULL, it's a single character to append to the - * copied out string - usually "\n", for /proc entries and - * (i.e. a terminating zero byte) for sysctl entries - */ - int size = MIN(strlen(kbuffer), ubuffer_size); - - if (copy_to_user(ubuffer, kbuffer, size)) - return (-EFAULT); - - if (append != NULL && size < ubuffer_size) { - if (copy_to_user(ubuffer + size, append, 1)) - return (-EFAULT); - - size++; - } - - return (size); -} - #ifdef DEBUG_KMEM static int proc_domemused(struct ctl_table *table, int write, @@ -187,39 +133,34 @@ static int proc_dohostid(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { - int len, rc = 0; char *end, str[32]; + unsigned long hid; + spl_ctl_table dummy = *table; + + dummy.data = str; + dummy.maxlen = sizeof (str) - 1; + + if (!write) + snprintf(str, sizeof (str), "%lx", + (unsigned long) zone_get_hostid(NULL)); + + /* always returns 0 */ + proc_dostring(&dummy, write, buffer, lenp, ppos); if (write) { /* * We can't use proc_doulongvec_minmax() in the write - * case here because hostid while a hex value has no - * leading 0x which confuses the helper function. + * case here because hostid, while a hex value, has no + * leading 0x, which confuses the helper function. */ - rc = proc_copyin_string(str, sizeof (str), buffer, *lenp); - if (rc < 0) - return (rc); - spl_hostid = simple_strtoul(str, &end, 16); + hid = simple_strtoul(str, &end, 16); if (str == end) return (-EINVAL); - - } else { - len = snprintf(str, sizeof (str), "%lx", - (unsigned long) zone_get_hostid(NULL)); - if (*ppos >= len) - rc = 0; - else - rc = proc_copyout_string(buffer, - *lenp, str + *ppos, "\n"); - - if (rc >= 0) { - *lenp = rc; - *ppos += rc; - } + spl_hostid = hid; } - return (rc); + return (0); } static void From 53efab30142077ff886dfadecccfb762d71d0c76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Sun, 11 Apr 2021 01:51:04 +0200 Subject: [PATCH 4/5] linux/libspl: gethostid: read from /proc/sys/kernel/spl/hostid, simplify MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The kernel and user-space must agree, after all Signed-off-by: Ahelenia Ziemiańska --- lib/libspl/os/linux/gethostid.c | 41 ++++++++++++++------------------- 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/lib/libspl/os/linux/gethostid.c b/lib/libspl/os/linux/gethostid.c index 457d5bf6fa3e..c04b7fd3eef3 100644 --- a/lib/libspl/os/linux/gethostid.c +++ b/lib/libspl/os/linux/gethostid.c @@ -40,47 +40,40 @@ get_spl_hostid(void) * Allow the hostid to be subverted for testing. */ env = getenv("ZFS_HOSTID"); - if (env) { - hostid = strtoull(env, NULL, 0); - return (hostid & HOSTID_MASK); - } + if (env) + return (strtoull(env, NULL, 0)); - f = fopen("/sys/module/spl/parameters/spl_hostid", "re"); + f = fopen("/proc/sys/kernel/spl/hostid", "re"); if (!f) return (0); - if (fscanf(f, "%lu", &hostid) != 1) + if (fscanf(f, "%lx", &hostid) != 1) hostid = 0; fclose(f); - return (hostid & HOSTID_MASK); + return (hostid); } unsigned long get_system_hostid(void) { - unsigned long system_hostid = get_spl_hostid(); + unsigned long hostid = get_spl_hostid(); + /* - * We do not use the library call gethostid() because - * it generates a hostid value that the kernel is - * unaware of, if the spl_hostid module parameter has not - * been set and there is no system hostid file (e.g. - * /etc/hostid). The kernel and userspace must agree. + * We do not use gethostid(3) because it can return a bogus ID, + * depending on the libc and /etc/hostid presence, + * and the kernel and userspace must agree. * See comments above hostid_read() in the SPL. */ - if (system_hostid == 0) { - int fd, rc; - unsigned long hostid; - int hostid_size = 4; /* 4 bytes regardless of arch */ - - fd = open("/etc/hostid", O_RDONLY | O_CLOEXEC); + if (hostid == 0) { + int fd = open("/etc/hostid", O_RDONLY | O_CLOEXEC); if (fd >= 0) { - rc = read(fd, &hostid, hostid_size); - if (rc > 0) - system_hostid = (hostid & HOSTID_MASK); - close(fd); + if (read(fd, &hostid, 4) < 0) + hostid = 0; + (void) close(fd); } } - return (system_hostid); + + return (hostid & HOSTID_MASK); } From bdfded7c98db6b2b38b597fd33e681ec34f37f8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Sun, 11 Apr 2021 16:29:00 +0200 Subject: [PATCH 5/5] linux/spl: proc: use global table_{min,max} values instead of local ones MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ahelenia Ziemiańska --- module/os/linux/spl/spl-proc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/module/os/linux/spl/spl-proc.c b/module/os/linux/spl/spl-proc.c index 63cd7cc2e5bc..c4af27a7fcd7 100644 --- a/module/os/linux/spl/spl-proc.c +++ b/module/os/linux/spl/spl-proc.c @@ -59,13 +59,13 @@ proc_domemused(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { int rc = 0; - unsigned long min = 0, max = ~0, val; + unsigned long val; spl_ctl_table dummy = *table; dummy.data = &val; dummy.proc_handler = &proc_dointvec; - dummy.extra1 = &min; - dummy.extra2 = &max; + dummy.extra1 = &table_min; + dummy.extra2 = &table_max; if (write) { *ppos += *lenp; @@ -87,14 +87,14 @@ proc_doslab(struct ctl_table *table, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { int rc = 0; - unsigned long min = 0, max = ~0, val = 0, mask; + unsigned long val = 0, mask; spl_ctl_table dummy = *table; spl_kmem_cache_t *skc = NULL; dummy.data = &val; dummy.proc_handler = &proc_dointvec; - dummy.extra1 = &min; - dummy.extra2 = &max; + dummy.extra1 = &table_min; + dummy.extra2 = &table_max; if (write) { *ppos += *lenp;