Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102550719
D40127.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
11 KB
Referenced Files
None
Subscribers
None
D40127.diff
View Options
diff --git a/sys/kern/kern_environment.c b/sys/kern/kern_environment.c
--- a/sys/kern/kern_environment.c
+++ b/sys/kern/kern_environment.c
@@ -38,6 +38,7 @@
#include <sys/cdefs.h>
#include <sys/param.h>
+#include <sys/eventhandler.h>
#include <sys/systm.h>
#include <sys/kenv.h>
#include <sys/kernel.h>
@@ -666,6 +667,7 @@
kenvp[i + 1] = NULL;
mtx_unlock(&kenv_lock);
}
+ EVENTHANDLER_INVOKE(setenv, name);
return (0);
}
@@ -689,6 +691,7 @@
kenvp[i] = NULL;
mtx_unlock(&kenv_lock);
zfree(oldenv, M_KENV);
+ EVENTHANDLER_INVOKE(unsetenv, name);
return (0);
}
mtx_unlock(&kenv_lock);
diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c
--- a/sys/kern/kern_linker.c
+++ b/sys/kern/kern_linker.c
@@ -2351,3 +2351,12 @@
CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
sysctl_kern_function_list, "",
"kernel function list");
+
+#ifdef VIMAGE
+void
+linker_file_restore_vnet_variable(linker_file_t lf, void *addr, size_t size)
+{
+ sx_assert(&kld_sx, SA_LOCKED);
+ LINKER_RESTORE_VNET_DEFAULT(lf, addr, size);
+}
+#endif
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -54,6 +54,7 @@
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/jail.h>
+#include <sys/linker.h>
#include <sys/kdb.h>
#include <sys/lock.h>
#include <sys/mutex.h>
@@ -127,6 +128,7 @@
int recurse);
static int sysctl_old_kernel(struct sysctl_req *, const void *, size_t);
static int sysctl_new_kernel(struct sysctl_req *, void *, size_t);
+static int name2oid(char *, int *, int *, struct sysctl_oid **);
static struct sysctl_oid *
sysctl_find_oidname(const char *name, struct sysctl_oid_list *list)
@@ -512,8 +514,12 @@
if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE &&
(oidp->oid_kind & CTLFLAG_TUN) != 0 &&
(oidp->oid_kind & CTLFLAG_NOFETCH) == 0) {
- /* only fetch value once */
- oidp->oid_kind |= CTLFLAG_NOFETCH;
+#ifdef VIMAGE
+ /* can fetch multiple times for VNET loader tunable */
+ if ((oidp->oid_kind & CTLFLAG_VNET) == 0)
+#endif
+ /* only fetch value once */
+ oidp->oid_kind |= CTLFLAG_NOFETCH;
/* try to fetch value from kernel environment */
sysctl_load_tunable_by_oid_locked(oidp);
}
@@ -969,6 +975,129 @@
}
SYSINIT(sysctl, SI_SUB_KMEM, SI_ORDER_FIRST, sysctl_register_all, NULL);
+#ifdef VIMAGE
+static void
+sysctl_setenv_vnet(void *arg __unused, char *name)
+{
+ struct sysctl_oid *oidp;
+ int oid[CTL_MAXNAME];
+ int error, nlen;
+
+ SYSCTL_WLOCK();
+ error = name2oid(name, oid, &nlen, &oidp);
+ if (error)
+ goto out;
+
+ if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE &&
+ (oidp->oid_kind & CTLFLAG_VNET) != 0 &&
+ (oidp->oid_kind & CTLFLAG_TUN) != 0 &&
+ (oidp->oid_kind & CTLFLAG_NOFETCH) == 0) {
+ /* try to update value from kernel environment */
+ sysctl_load_tunable_by_oid_locked(oidp);
+ }
+
+out:
+ SYSCTL_WUNLOCK();
+}
+
+struct cbargs {
+ struct sysctl_oid *oidp;
+ void *addr;
+ size_t size;
+};
+
+static int
+sysctl_linker_file_cb(linker_file_t lf, void *arg)
+{
+ struct sysctl_oid **start, **stop, **o;
+ struct cbargs *args = arg;
+
+ if (linker_file_lookup_set(lf, "sysctl_set", &start, &stop, NULL) != 0)
+ return (0);
+ for (o = start; o < stop; o++) {
+ if (*o == args->oidp) {
+ linker_file_restore_vnet_variable(lf, args->addr, args->size);
+ return (1);
+ }
+ }
+ return (0);
+}
+
+static void
+sysctl_unsetenv_vnet(void *arg __unused, char *name)
+{
+ struct rm_priotracker tracker;
+ struct sysctl_oid *oidp;
+ int oid[CTL_MAXNAME];
+ int error, nlen;
+
+ SYSCTL_RLOCK(&tracker);
+ error = name2oid(name, oid, &nlen, &oidp);
+ if (error)
+ goto out;
+
+ if ((oidp->oid_kind & CTLTYPE) != CTLTYPE_NODE &&
+ (oidp->oid_kind & CTLFLAG_VNET) != 0 &&
+ (oidp->oid_kind & CTLFLAG_TUN) != 0 &&
+ (oidp->oid_kind & CTLFLAG_NOFETCH) == 0) {
+ void *addr;
+ size_t size;
+
+ switch (oidp->oid_kind & CTLTYPE) {
+ case CTLTYPE_INT:
+ case CTLTYPE_UINT:
+ size = sizeof(int);
+ break;
+ case CTLTYPE_LONG:
+ case CTLTYPE_ULONG:
+ size = sizeof(long);
+ break;
+ case CTLTYPE_S8:
+ case CTLTYPE_U8:
+ size = sizeof(int8_t);
+ break;
+ case CTLTYPE_S16:
+ case CTLTYPE_U16:
+ size = sizeof(int16_t);
+ break;
+ case CTLTYPE_S32:
+ case CTLTYPE_U32:
+ size = sizeof(int32_t);
+ break;
+ case CTLTYPE_S64:
+ case CTLTYPE_U64:
+ size = sizeof(int64_t);
+ break;
+ case CTLTYPE_STRING:
+ MPASS(oidp->oid_arg2 > 0);
+ size = oidp->oid_arg2;
+ break;
+ default:
+ // not supported
+ goto out;
+ }
+ addr = oidp->oid_arg1;
+ SYSCTL_RUNLOCK(&tracker);
+
+ struct cbargs args = {
+ .oidp = oidp,
+ .addr = addr,
+ .size = size
+ };
+ linker_file_foreach(sysctl_linker_file_cb, &args);
+ return;
+ }
+out:
+ SYSCTL_RUNLOCK(&tracker);
+}
+
+/*
+ * Register the kernel's setenv / unsetenv events.
+ */
+EVENTHANDLER_DEFINE(setenv, sysctl_setenv_vnet, NULL, EVENTHANDLER_PRI_ANY);
+EVENTHANDLER_DEFINE(unsetenv, sysctl_unsetenv_vnet, NULL, EVENTHANDLER_PRI_ANY);
+#endif
+
/*
* "Staff-functions"
*
diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c
--- a/sys/kern/link_elf.c
+++ b/sys/kern/link_elf.c
@@ -162,6 +162,7 @@
static long link_elf_strtab_get(linker_file_t, caddr_t *);
#ifdef VIMAGE
static void link_elf_propagate_vnets(linker_file_t);
+static void link_elf_restore_vnet_default(linker_file_t, void *, size_t);
#endif
static int elf_lookup(linker_file_t, Elf_Size, int, Elf_Addr *);
@@ -183,6 +184,7 @@
KOBJMETHOD(linker_strtab_get, link_elf_strtab_get),
#ifdef VIMAGE
KOBJMETHOD(linker_propagate_vnets, link_elf_propagate_vnets),
+ KOBJMETHOD(linker_restore_vnet_default, link_elf_restore_vnet_default),
#endif
KOBJMETHOD_END
};
@@ -213,6 +215,7 @@
static struct elf_set_head set_pcpu_list;
#ifdef VIMAGE
static struct elf_set_head set_vnet_list;
+static void * linker_kernel_vnet_default;
#endif
static void
@@ -506,6 +509,8 @@
TAILQ_INIT(&set_pcpu_list);
#ifdef VIMAGE
TAILQ_INIT(&set_vnet_list);
+ linker_kernel_vnet_default = malloc(VNET_STOP - VNET_START, M_LINKER, M_WAITOK);
+ memcpy(linker_kernel_vnet_default, (void *)VNET_START, VNET_STOP - VNET_START);
#endif
}
@@ -1941,6 +1946,25 @@
vnet_data_copy((void *)ef->vnet_base, size);
}
}
+
+static void
+link_elf_restore_vnet_default(linker_file_t lf, void *addr, size_t size)
+{
+ elf_file_t ef = (elf_file_t)lf;
+ uintptr_t *oaddr;
+
+ MPASS(size > 0);
+ if (ef->vnet_base == 0) {
+ MPASS(lf == linker_kernel_file);
+ MPASS(VNET_START <= (uintptr_t)addr && (uintptr_t)addr + size <= VNET_STOP);
+ oaddr = (uintptr_t)linker_kernel_vnet_default + ((uintptr_t)addr - VNET_START);
+ } else {
+ MPASS((uintptr_t)ef->vnet_base <= (uintptr_t)addr &&
+ (uintptr_t)addr + size <= (uintptr_t)ef->vnet_base + (ef->vnet_stop - ef->vnet_start));
+ oaddr = (uintptr_t)ef->vnet_start + ((uintptr_t)addr - (uintptr_t)ef->vnet_base);
+ }
+ memcpy(addr, (void *)oaddr, size);
+}
#endif
#if defined(__i386__) || defined(__amd64__) || defined(__aarch64__) || defined(__powerpc__)
diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c
--- a/sys/kern/link_elf_obj.c
+++ b/sys/kern/link_elf_obj.c
@@ -75,6 +75,9 @@
int flags; /* Section flags. */
int sec; /* Original section number. */
char *name;
+#ifdef VIMAGE
+ void *oaddr; /* Original addr, for vnet */
+#endif
} Elf_progent;
typedef struct {
@@ -152,6 +155,7 @@
static long link_elf_strtab_get(linker_file_t, caddr_t *);
#ifdef VIMAGE
static void link_elf_propagate_vnets(linker_file_t);
+static void link_elf_restore_vnet_default(linker_file_t, void *, size_t);
#endif
static int elf_obj_lookup(linker_file_t lf, Elf_Size symidx, int deps,
@@ -175,6 +179,7 @@
KOBJMETHOD(linker_strtab_get, link_elf_strtab_get),
#ifdef VIMAGE
KOBJMETHOD(linker_propagate_vnets, link_elf_propagate_vnets),
+ KOBJMETHOD(linker_restore_vnet_default, link_elf_restore_vnet_default),
#endif
KOBJMETHOD_END
};
@@ -546,6 +551,7 @@
}
memcpy(vnet_data, ef->progtab[pb].addr,
ef->progtab[pb].size);
+ ef->progtab[pb].oaddr = ef->progtab[pb].addr;
ef->progtab[pb].addr = vnet_data;
#endif
} else if ((ef->progtab[pb].name != NULL &&
@@ -1070,29 +1076,14 @@
"for %s\n", __func__,
(uintmax_t)shdr[i].sh_size,
filename);
+ error = ENOSPC;
+ goto out;
}
}
-#ifdef VIMAGE
- else if (ef->progtab[pb].name != NULL &&
- !strcmp(ef->progtab[pb].name, VNET_SETNAME)) {
- ef->progtab[pb].addr =
- vnet_data_alloc(shdr[i].sh_size);
- if (ef->progtab[pb].addr == NULL) {
- printf("%s: vnet module space is out "
- "of space; cannot allocate %#jx "
- "for %s\n", __func__,
- (uintmax_t)shdr[i].sh_size,
- filename);
- }
- }
-#endif
else
ef->progtab[pb].addr =
(void *)(uintptr_t)mapbase;
- if (ef->progtab[pb].addr == NULL) {
- error = ENOSPC;
- goto out;
- }
+
ef->progtab[pb].size = shdr[i].sh_size;
ef->progtab[pb].flags = shdr[i].sh_flags;
ef->progtab[pb].sec = i;
@@ -1120,6 +1111,29 @@
} else
bzero(ef->progtab[pb].addr, shdr[i].sh_size);
+#ifdef VIMAGE
+ /* Initialize the vnet area. */
+ if (ef->progtab[pb].name != NULL &&
+ !strcmp(ef->progtab[pb].name, VNET_SETNAME)) {
+ void *vnet_data;
+
+ vnet_data = vnet_data_alloc(shdr[i].sh_size);
+ if (vnet_data == NULL) {
+ printf("%s: vnet module space is out "
+ "of space; cannot allocate %#jx "
+ "for %s\n", __func__,
+ (uintmax_t)shdr[i].sh_size,
+ filename);
+ error = ENOSPC;
+ goto out;
+ }
+ memcpy(vnet_data, ef->progtab[pb].addr,
+ ef->progtab[pb].size);
+ vnet_data_copy(vnet_data, shdr[i].sh_size);
+ ef->progtab[pb].oaddr = ef->progtab[pb].addr;
+ ef->progtab[pb].addr = vnet_data;
+ }
+#endif
/* Update all symbol values with the offset. */
for (j = 0; j < ef->ddbsymcnt; j++) {
es = &ef->ddbsymtab[j];
@@ -1878,4 +1892,32 @@
}
}
}
+
+static void
+link_elf_restore_vnet_default(linker_file_t lf, void *addr, size_t size)
+{
+ elf_file_t ef = (elf_file_t)lf;
+
+ MPASS(size > 0);
+ MPASS(ef->progtab != NULL);
+
+ for (int i = 0; i < ef->nprogtab; i++) {
+ if (ef->progtab[i].size == 0)
+ continue;
+ if (ef->progtab[i].name == NULL)
+ continue;
+ if (strcmp(ef->progtab[i].name, VNET_SETNAME) != 0)
+ continue;
+
+ MPASS(ef->progtab[i].oaddr != NULL);
+ MPASS(ef->progtab[i].addr <= addr &&
+ ((uintptr_t)addr + size) <= ((uintptr_t)ef->progtab[i].addr +
+ ef->progtab[i].size));
+
+ memcpy(addr, (void *)((uintptr_t)ef->progtab[i].oaddr +
+ ((uintptr_t)addr - (uintptr_t)ef->progtab[i].addr)),
+ size);
+ break;
+ }
+}
#endif
diff --git a/sys/kern/linker_if.m b/sys/kern/linker_if.m
--- a/sys/kern/linker_if.m
+++ b/sys/kern/linker_if.m
@@ -162,4 +162,13 @@
METHOD void propagate_vnets {
linker_file_t file;
};
+
+#
+# Restore vnets' default values
+#
+METHOD void restore_vnet_default {
+ linker_file_t file;
+ void * addr;
+ size_t size;
+};
#endif
diff --git a/sys/sys/eventhandler.h b/sys/sys/eventhandler.h
--- a/sys/sys/eventhandler.h
+++ b/sys/sys/eventhandler.h
@@ -326,4 +326,9 @@
typedef void (*rt_addrmsg_fn)(void *, struct ifaddr *, int);
EVENTHANDLER_DECLARE(rt_addrmsg, rt_addrmsg_fn);
+/* Kernel environment variable change event */
+typedef void (*env_change_fn)(void *, const char *);
+EVENTHANDLER_DECLARE(setenv, env_change_fn);
+EVENTHANDLER_DECLARE(unsetenv, env_change_fn);
+
#endif /* _SYS_EVENTHANDLER_H_ */
diff --git a/sys/sys/linker.h b/sys/sys/linker.h
--- a/sys/sys/linker.h
+++ b/sys/sys/linker.h
@@ -205,6 +205,10 @@
int linker_kldload_busy(int flags);
void linker_kldload_unbusy(int flags);
+#ifdef VIMAGE
+void linker_file_restore_vnet_variable(linker_file_t lf, void *addr,
+ size_t size);
+#endif
#endif /* _KERNEL */
/*
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Nov 14, 10:48 PM (8 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14634746
Default Alt Text
D40127.diff (11 KB)
Attached To
Mode
D40127: sysctl: Update 'master' copy of vnet SYSCTLs on kernel environment variables change
Attached
Detach File
Event Timeline
Log In to Comment