#include <unistd.h>
#include <string.h>
-extern int __sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
- void *newp, size_t newlen);
+#include "sysctl_internal.h"
+
int
-sysctl(name, namelen, oldp, oldlenp, newp, newlen)
- int *name;
- u_int namelen;
- void *oldp, *newp;
- size_t *oldlenp, newlen;
+sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen)
+__attribute__((disable_tail_calls))
{
- if (name[0] != CTL_USER)
- return (__sysctl(name, namelen, oldp, oldlenp, newp, newlen));
+ if (name[0] != CTL_USER) {
+ if (namelen == 2 && name[0] == CTL_KERN && name[1] == KERN_EXEC) {
+ /*
+ * 7723306: intercept kern.exec and fake a return of
+ * a dummy string ("/" in this case)
+ */
+ if (newp != NULL) {
+ errno = EPERM;
+ return -1;
+ }
+ if (oldp == NULL) {
+ if (oldlenp != NULL) *oldlenp = 2;
+ return 0;
+ }
+ if (oldlenp == NULL) {
+ errno = EFAULT;
+ return -1;
+ }
+ if (*oldlenp < 2) {
+ errno = ENOMEM;
+ return -1;
+ }
+ memmove(oldp, "/", 2);
+ *oldlenp = 2;
+ return 0;
+ }
+
+
+ int error = __sysctl(name, namelen, oldp, oldlenp, newp, newlen);
+ if (error < 0) {
+ return error;
+ }
+
+
+ return error;
+ }
if (newp != NULL) {
errno = EPERM;