Date: Sun, 22 Aug 2021 21:22:58 GMT From: Alan Somers <asomers@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: e7d99efb3638 - stable/13 - Escape any '.' characters in sysctl node names Message-ID: <202108222122.17MLMw62010465@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch stable/13 has been updated by asomers: URL: https://cgit.FreeBSD.org/src/commit/?id=e7d99efb3638b71756da8033ef8cef74213c42fd commit e7d99efb3638b71756da8033ef8cef74213c42fd Author: Alan Somers <asomers@FreeBSD.org> AuthorDate: 2021-07-21 21:11:00 +0000 Commit: Alan Somers <asomers@FreeBSD.org> CommitDate: 2021-08-22 21:11:00 +0000 Escape any '.' characters in sysctl node names ZFS creates some sysctl nodes that include a pool name, and '.' is an allowed character in pool names. But it's the separator in the sysctl tree, so it can't be included in a sysctl name. Replace it with "%25". Handily, "%" is illegal in ZFS pool names, so there's no ambiguity there. PR: 257316 Sponsored by: Axcient Reviewed by: freqlabs Differential Revision: https://reviews.freebsd.org/D31265 (cherry picked from commit 6c9506559080da2914749bf611225d7c0a153609) --- sys/kern/kern_sysctl.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 4bfe7073e5a3..f1e249ace89a 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -122,6 +122,7 @@ static int sysctl_root(SYSCTL_HANDLER_ARGS); /* Root list */ struct sysctl_oid_list sysctl__children = SLIST_HEAD_INITIALIZER(&sysctl__children); +static char* sysctl_escape_name(const char*); static int sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del, int recurse); static int sysctl_old_kernel(struct sysctl_req *, const void *, size_t); @@ -747,6 +748,46 @@ sysctl_remove_name(struct sysctl_oid *parent, const char *name, return (error); } +/* + * Duplicate the provided string, escaping any illegal characters. The result + * must be freed when no longer in use. + * + * The list of illegal characters is ".". + */ +static char* +sysctl_escape_name(const char* orig) +{ + int i, s = 0, d = 0, nillegals = 0; + char *new; + + /* First count the number of illegal characters */ + for (i = 0; orig[i] != '\0'; i++) { + if (orig[i] == '.') + nillegals++; + } + + /* Allocate storage for new string */ + new = malloc(i + 2 * nillegals + 1, M_SYSCTLOID, M_WAITOK); + + /* Copy the name, escaping characters as we go */ + while (orig[s] != '\0') { + if (orig[s] == '.') { + /* %25 is the hexadecimal representation of '.' */ + new[d++] = '%'; + new[d++] = '2'; + new[d++] = '5'; + s++; + } else { + new[d++] = orig[s++]; + } + } + + /* Finally, nul-terminate */ + new[d] = '\0'; + + return (new); +} + static int sysctl_remove_oid_locked(struct sysctl_oid *oidp, int del, int recurse) { @@ -828,14 +869,17 @@ sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent, const char *label) { struct sysctl_oid *oidp; + char *escaped; /* You have to hook up somewhere.. */ if (parent == NULL) return(NULL); + escaped = sysctl_escape_name(name); /* Check if the node already exists, otherwise create it */ SYSCTL_WLOCK(); - oidp = sysctl_find_oidname(name, parent); + oidp = sysctl_find_oidname(escaped, parent); if (oidp != NULL) { + free(escaped, M_SYSCTLOID); if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) { oidp->oid_refcnt++; /* Update the context */ @@ -854,7 +898,7 @@ sysctl_add_oid(struct sysctl_ctx_list *clist, struct sysctl_oid_list *parent, SLIST_INIT(&oidp->oid_children); oidp->oid_number = number; oidp->oid_refcnt = 1; - oidp->oid_name = strdup(name, M_SYSCTLOID); + oidp->oid_name = escaped; oidp->oid_handler = handler; oidp->oid_kind = CTLFLAG_DYN | kind; oidp->oid_arg1 = arg1;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202108222122.17MLMw62010465>