-/* $OpenBSD: dt_dev.c,v 1.35 2024/08/21 09:27:37 mpi Exp $ */
+/* $OpenBSD: dt_dev.c,v 1.36 2024/08/22 10:08:25 mvs Exp $ */
/*
* Copyright (c) 2019 Martin Pieuchot <mpi@openbsd.org>
* to keep track of enabled PCBs.
*
* Locks used to protect struct members in this file:
+ * a atomic
* m per-softc mutex
* K kernel lock
*/
struct rwlock dt_lock = RWLOCK_INITIALIZER("dtlk");
volatile uint32_t dt_tracing = 0; /* [K] # of processes tracing */
-int allowdt;
+int allowdt; /* [a] */
void dtattach(struct device *, struct device *, void *);
int dtopen(dev_t, int, int, struct proc *);
struct dt_softc *sc;
int unit = minor(dev);
- if (!allowdt)
+ if (atomic_load_int(&allowdt) == 0)
return EPERM;
sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_CANFAIL|M_ZERO);
-/* $OpenBSD: kern_sysctl.c,v 1.442 2024/08/20 13:29:25 mvs Exp $ */
+/* $OpenBSD: kern_sysctl.c,v 1.443 2024/08/22 10:08:25 mvs Exp $ */
/* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */
/*-
int allowkmem;
+int sysctl_securelevel(void *, size_t *, void *, size_t, struct proc *);
int sysctl_diskinit(int, struct proc *);
int sysctl_proc_args(int *, u_int, void *, size_t *, struct proc *);
int sysctl_proc_cwd(int *, u_int, void *, size_t *, struct proc *);
return (sysctl_rdstring(oldp, oldlenp, newp, version));
case KERN_NUMVNODES: /* XXX numvnodes is a long */
return (sysctl_rdint(oldp, oldlenp, newp, numvnodes));
+#if NDT > 0
+ case KERN_ALLOWDT:
+ return (sysctl_securelevel_int(oldp, oldlenp, newp, newlen,
+ &allowdt));
+#endif
case KERN_HOSTID:
return (sysctl_int(oldp, oldlenp, newp, newlen, &hostid));
case KERN_CLOCKRATE:
kern_sysctl_locked(int *name, u_int namelen, void *oldp, size_t *oldlenp,
void *newp, size_t newlen, struct proc *p)
{
- int error, level, stackgap;
+ int error, stackgap;
dev_t dev;
extern int pool_debug;
switch (name[0]) {
case KERN_SECURELVL:
- level = securelevel;
- if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &level)) ||
- newp == NULL)
- return (error);
- if ((securelevel > 0 || level < -1) &&
- level < securelevel && p->p_p->ps_pid != 1)
- return (EPERM);
- securelevel = level;
- return (0);
-#if NDT > 0
- case KERN_ALLOWDT:
- return (sysctl_securelevel_int(oldp, oldlenp, newp, newlen,
- &allowdt));
-#endif
+ return (sysctl_securelevel(oldp, oldlenp, newp, newlen, p));
case KERN_ALLOWKMEM:
return (sysctl_securelevel_int(oldp, oldlenp, newp, newlen,
&allowkmem));
return (error);
}
+int
+sysctl_securelevel(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
+ struct proc *p)
+{
+ int oldval, newval;
+ int error;
+
+ if (oldp && *oldlenp < sizeof(int))
+ return (ENOMEM);
+ if (newp && newlen != sizeof(int))
+ return (EINVAL);
+ *oldlenp = sizeof(int);
+
+ if (newp) {
+ if ((error = copyin(newp, &newval, sizeof(int))))
+ return (error);
+ do {
+ oldval = atomic_load_int(&securelevel);
+ if ((oldval > 0 || newval < -1) && newval < oldval &&
+ p->p_p->ps_pid != 1)
+ return (EPERM);
+ } while (atomic_cas_uint(&securelevel, oldval, newval) !=
+ oldval);
+
+ if (oldp) {
+ /* new value has been set although user gets error */
+ if ((error = copyout(&oldval, oldp, sizeof(int))))
+ return (error);
+ }
+ } else if (oldp) {
+ oldval = atomic_load_int(&securelevel);
+
+ if ((error = copyout(&oldval, oldp, sizeof(int))))
+ return (error);
+ }
+
+ return (0);
+}
+
/*
* Selects between sysctl_rdint and sysctl_int according to securelevel.
*/
sysctl_securelevel_int(void *oldp, size_t *oldlenp, void *newp, size_t newlen,
int *valp)
{
- if (securelevel > 0)
+ if (atomic_load_int(&securelevel) > 0)
return (sysctl_rdint(oldp, oldlenp, newp, *valp));
return (sysctl_int(oldp, oldlenp, newp, newlen, valp));
}