Date: Mon, 1 Feb 1999 20:20:13 -0500 (EST) From: Robert Watson <robert@cyrus.watson.org> To: current@FreeBSD.ORG Subject: swap_page_getswapspace failed (don't do stupid things with /dev/mem) Message-ID: <Pine.BSF.3.96.990201201334.10163A-100000@fledge.watson.org>
next in thread | raw e-mail | index | archive | help
So, never do stupid things as root; that's always my moto. Well, so I did
something stupid as root, but it wasn't inherrently *that* stupid, at
least not stupid enough to require a hard boot :). Below is the source
code for the beginnings of an audit daemon--all it does is disable
auditing on its own process, then read from /dev/audit. My goal was
simply to make sure that data was going back and forth via the device
correctly.
Except I decided to test that feature that overrides the device filename
(normally /dev/audit). Instead, I chose /dev/mem. Don't do that (ouch).
The machine began to churn -- ok, so the buffer expands as necessary
without limit, which is something that will go away once I actually write
the daemon. But it kept churning, and gradually I lost control of
things--my keyboard, eventually my mouse, and eventually the system just
hung. Retrying it after a hard boot (and let me tell you that the off
switch did not work on my IBM 560E notebook for a few tries :), I tried
again on the console. The system is reduced to an endlessly printed:
swap_pager_getswapspace: failed
from the kernel. And needless to say, it loops fairly tightly and we
don't get much in the way of key-pressing. Clearly, this is not something
you should do with /dev/mem, but how was I to know :). Perhaps someone
could determine if there is a race condition/etc that allows this
condition to be entered, and instead default to killing the process or
something. My kernel code is a few days old on the 4.0-CURRENT branch.
Source: auditd.c (just disable auditing stuff to make it compile). Invoke
as auditd /dev/mem.
/*-
* Copyright (c) 1999 Robert Watson
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: $
*/
/*
* User-land audit daemon
* Listens on /dev/audit reading out records, and dropping them into
* /var/log/audit.
* Disables its own auditing to prevent nasties.
*/
#include <sys/types.h>
#include <sys/audit.h>
#include <sys/fcntl.h>
#include <sys/uio.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "auditd.h"
void usage(void)
{
fprintf(stderr, "auditd [-d] [-f auditdevice]\n");
exit(-1);
}
void main(int argc, char *argv[])
{
int i, fd, size, bufsize, not_daemon;
char ch, *buf, *devfile=AUDIT_DEVICE;
not_daemon = 0;
while ((ch = getopt(argc, argv, "df:")) != -1) {
switch(ch) {
case 'd':
not_daemon = 1;
break;
case 'f':
devfile = optarg;
break;
default:
/* warnx("unknown flag -%c ignored", optopt); */
usage();
}
}
buf = (char *) malloc(AUDIT_DEF_BUF_SIZE * sizeof(char));
if (!buf) {
fprintf(stderr, "auditd: unable to malloc buffer\n");
exit(-1);
}
bufsize = AUDIT_DEF_BUF_SIZE;
i = aud_switch(AUD_STATE_OFF);
if (i == -1) {
perror("auditd: aud_switch");
exit(-1);
}
fd = open(devfile, O_RDONLY);
if (fd == -1) {
perror("auditd: open: audit device");
exit(-1);
}
if (!not_daemon) {
i = daemon(1, 1);
if (i == -1) {
perror("auditd: daemon");
exit(-1);
}
}
while (1) {
/* read the size of the next block */
i = read(fd, &size, sizeof(size));
if (i == sizeof(size)) {
if (size > bufsize) {
free(buf);
bufsize = size;
buf = NULL;
while (buf == NULL) {
buf = (char *)
malloc(bufsize *
sizeof(char));
}
i = read(fd, buf, bufsize);
fprintf(stderr, "got stuff (%d/%d)\n", i,
bufsize);
}
}
}
}
Robert N Watson
robert@fledge.watson.org http://www.watson.org/~robert/
PGP key fingerprint: 03 01 DD 8E 15 67 48 73 25 6D 10 FC EC 68 C1 1C
Carnegie Mellon University http://www.cmu.edu/
TIS Labs at Network Associates, Inc. http://www.tis.com/
SafePort Network Services http://www.safeport.com/
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.96.990201201334.10163A-100000>
