summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2006-03-15 21:02:10 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2006-03-15 21:02:10 +0000
commit4fab456581899b539dfa38abbe09ffa5d335281f (patch)
tree70982219338e71c3fd83ca47983d1282384fd2c5
parenta995e755d4518486473cf6405ba5e125b6eb050a (diff)
add sysctl_int_lower(). This can read, but can only write to a kernel
variable if the result is a lowering of the value; tested matthieu
-rw-r--r--sys/kern/kern_sysctl.c22
-rw-r--r--sys/sys/sysctl.h3
2 files changed, 23 insertions, 2 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index 5cdfb1ae031..037afc29aed 100644
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sysctl.c,v 1.138 2006/01/28 09:53:37 dlg Exp $ */
+/* $OpenBSD: kern_sysctl.c,v 1.139 2006/03/15 21:02:09 deraadt Exp $ */
/* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */
/*-
@@ -674,6 +674,26 @@ debug_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
#endif /* DEBUG */
/*
+ * Reads, or writes that lower the value
+ */
+int
+sysctl_int_lower(void *oldp, size_t *oldlenp, void *newp, size_t newlen, int *valp)
+{
+ unsigned int oval = *valp, val = *valp;
+ int error;
+
+ if (newp == NULL)
+ return (sysctl_rdint(oldp, oldlenp, newp, *valp));
+
+ if ((error = sysctl_int(oldp, oldlenp, newp, newlen, &val)))
+ return (error);
+ if (val > oval)
+ return (EPERM); /* do not allow raising */
+ *(unsigned int *)valp = val;
+ return (0);
+}
+
+/*
* Validate parameters and get old / set new parameters
* for an integer-valued sysctl function.
*/
diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
index 60c0fd22ca2..12409ce7471 100644
--- a/sys/sys/sysctl.h
+++ b/sys/sys/sysctl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sysctl.h,v 1.86 2006/02/06 17:37:28 jmc Exp $ */
+/* $OpenBSD: sysctl.h,v 1.87 2006/03/15 21:02:04 deraadt Exp $ */
/* $NetBSD: sysctl.h,v 1.16 1996/04/09 20:55:36 cgd Exp $ */
/*
@@ -660,6 +660,7 @@ extern struct ctldebug debug15, debug16, debug17, debug18, debug19;
typedef int (sysctlfn)(int *, u_int, void *, size_t *, void *, size_t, struct proc *);
int sysctl_int(void *, size_t *, void *, size_t, int *);
+int sysctl_int_lower(void *, size_t *, void *, size_t, int *);
int sysctl_rdint(void *, size_t *, void *, int);
int sysctl_int_arr(int **, int *, u_int, void *, size_t *, void *, size_t);
int sysctl_quad(void *, size_t *, void *, size_t, int64_t *);