svn commit: r324748 - in stable/11/sys: kern sys
Andriy Gapon
avg at FreeBSD.org
Thu Oct 19 07:54:05 UTC 2017
Author: avg
Date: Thu Oct 19 07:54:04 2017
New Revision: 324748
URL: https://svnweb.freebsd.org/changeset/base/324748
Log:
MFC r324311: sysctl-s in a module should be accessible only when the module is initialized
Sponsored by: Panzura
Modified:
stable/11/sys/kern/kern_linker.c
stable/11/sys/kern/kern_sysctl.c
stable/11/sys/sys/sysctl.h
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/sys/kern/kern_linker.c
==============================================================================
--- stable/11/sys/kern/kern_linker.c Thu Oct 19 07:23:47 2017 (r324747)
+++ stable/11/sys/kern/kern_linker.c Thu Oct 19 07:54:04 2017 (r324748)
@@ -288,7 +288,7 @@ linker_file_sysuninit(linker_file_t lf)
}
static void
-linker_file_register_sysctls(linker_file_t lf)
+linker_file_register_sysctls(linker_file_t lf, bool enable)
{
struct sysctl_oid **start, **stop, **oidp;
@@ -303,8 +303,34 @@ linker_file_register_sysctls(linker_file_t lf)
sx_xunlock(&kld_sx);
sysctl_wlock();
+ for (oidp = start; oidp < stop; oidp++) {
+ if (enable)
+ sysctl_register_oid(*oidp);
+ else
+ sysctl_register_disabled_oid(*oidp);
+ }
+ sysctl_wunlock();
+ sx_xlock(&kld_sx);
+}
+
+static void
+linker_file_enable_sysctls(linker_file_t lf)
+{
+ struct sysctl_oid **start, **stop, **oidp;
+
+ KLD_DPF(FILE,
+ ("linker_file_enable_sysctls: enable SYSCTLs for %s\n",
+ lf->filename));
+
+ sx_assert(&kld_sx, SA_XLOCKED);
+
+ if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
+ return;
+
+ sx_xunlock(&kld_sx);
+ sysctl_wlock();
for (oidp = start; oidp < stop; oidp++)
- sysctl_register_oid(*oidp);
+ sysctl_enable_oid(*oidp);
sysctl_wunlock();
sx_xlock(&kld_sx);
}
@@ -430,7 +456,7 @@ linker_load_file(const char *filename, linker_file_t *
return (error);
}
modules = !TAILQ_EMPTY(&lf->modules);
- linker_file_register_sysctls(lf);
+ linker_file_register_sysctls(lf, false);
linker_file_sysinit(lf);
lf->flags |= LINKER_FILE_LINKED;
@@ -443,6 +469,7 @@ linker_load_file(const char *filename, linker_file_t *
linker_file_unload(lf, LINKER_UNLOAD_FORCE);
return (ENOEXEC);
}
+ linker_file_enable_sysctls(lf);
EVENTHANDLER_INVOKE(kld_load, lf);
*result = lf;
return (0);
@@ -691,8 +718,8 @@ linker_file_unload(linker_file_t file, int flags)
*/
if (file->flags & LINKER_FILE_LINKED) {
file->flags &= ~LINKER_FILE_LINKED;
- linker_file_sysuninit(file);
linker_file_unregister_sysctls(file);
+ linker_file_sysuninit(file);
}
TAILQ_REMOVE(&linker_files, file, link);
@@ -1640,7 +1667,7 @@ restart:
if (linker_file_lookup_set(lf, "sysinit_set", &si_start,
&si_stop, NULL) == 0)
sysinit_add(si_start, si_stop);
- linker_file_register_sysctls(lf);
+ linker_file_register_sysctls(lf, true);
lf->flags |= LINKER_FILE_LINKED;
continue;
fail:
Modified: stable/11/sys/kern/kern_sysctl.c
==============================================================================
--- stable/11/sys/kern/kern_sysctl.c Thu Oct 19 07:23:47 2017 (r324747)
+++ stable/11/sys/kern/kern_sysctl.c Thu Oct 19 07:54:04 2017 (r324748)
@@ -425,6 +425,37 @@ retry:
}
void
+sysctl_register_disabled_oid(struct sysctl_oid *oidp)
+{
+
+ /*
+ * Mark the leaf as dormant if it's not to be immediately enabled.
+ * We do not disable nodes as they can be shared between modules
+ * and it is always safe to access a node.
+ */
+ KASSERT((oidp->oid_kind & CTLFLAG_DORMANT) == 0,
+ ("internal flag is set in oid_kind"));
+ if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE)
+ oidp->oid_kind |= CTLFLAG_DORMANT;
+ sysctl_register_oid(oidp);
+}
+
+void
+sysctl_enable_oid(struct sysctl_oid *oidp)
+{
+
+ SYSCTL_ASSERT_WLOCKED();
+ if ((oidp->oid_kind & CTLTYPE) == CTLTYPE_NODE) {
+ KASSERT((oidp->oid_kind & CTLFLAG_DORMANT) == 0,
+ ("sysctl node is marked as dormant"));
+ return;
+ }
+ KASSERT((oidp->oid_kind & CTLFLAG_DORMANT) != 0,
+ ("enabling already enabled sysctl oid"));
+ oidp->oid_kind &= ~CTLFLAG_DORMANT;
+}
+
+void
sysctl_unregister_oid(struct sysctl_oid *oidp)
{
struct sysctl_oid *p;
@@ -965,7 +996,7 @@ sysctl_sysctl_next_ls(struct sysctl_oid_list *lsp, int
*next = oidp->oid_number;
*oidpp = oidp;
- if (oidp->oid_kind & CTLFLAG_SKIP)
+ if ((oidp->oid_kind & (CTLFLAG_SKIP | CTLFLAG_DORMANT)) != 0)
continue;
if (!namelen) {
@@ -1761,6 +1792,8 @@ sysctl_find_oid(int *name, u_int namelen, struct sysct
}
lsp = SYSCTL_CHILDREN(oid);
} else if (indx == namelen) {
+ if ((oid->oid_kind & CTLFLAG_DORMANT) != 0)
+ return (ENOENT);
*noid = oid;
if (nindx != NULL)
*nindx = indx;
Modified: stable/11/sys/sys/sysctl.h
==============================================================================
--- stable/11/sys/sys/sysctl.h Thu Oct 19 07:23:47 2017 (r324747)
+++ stable/11/sys/sys/sysctl.h Thu Oct 19 07:54:04 2017 (r324748)
@@ -83,6 +83,7 @@ struct ctlname {
#define CTLFLAG_RD 0x80000000 /* Allow reads of variable */
#define CTLFLAG_WR 0x40000000 /* Allow writes to the variable */
#define CTLFLAG_RW (CTLFLAG_RD|CTLFLAG_WR)
+#define CTLFLAG_DORMANT 0x20000000 /* This sysctl is not active yet */
#define CTLFLAG_ANYBODY 0x10000000 /* All users can set this var */
#define CTLFLAG_SECURE 0x08000000 /* Permit set only if securelevel<=0 */
#define CTLFLAG_PRISON 0x04000000 /* Prisoned roots can fiddle */
@@ -218,6 +219,8 @@ int sysctl_dpcpu_quad(SYSCTL_HANDLER_ARGS);
* These functions are used to add/remove an oid from the mib.
*/
void sysctl_register_oid(struct sysctl_oid *oidp);
+void sysctl_register_disabled_oid(struct sysctl_oid *oidp);
+void sysctl_enable_oid(struct sysctl_oid *oidp);
void sysctl_unregister_oid(struct sysctl_oid *oidp);
/* Declare a static oid to allow child oids to be added to it. */
More information about the svn-src-stable-11
mailing list