kern/86775: system reboot without syncing
Guram Dukashvili
korvin at tehnomir.lipetsk.ru
Fri Sep 30 23:10:25 PDT 2005
>Number: 86775
>Category: kern
>Synopsis: system reboot without syncing
>Confidential: no
>Severity: critical
>Priority: high
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Sat Oct 01 06:10:19 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator: Guram Dukashvili
>Release: FreeBSD 5.4-STABLE i386
>Organization:
>Environment:
System: FreeBSD post2.tehnomir.lipetsk.ru 5.4-STABLE FreeBSD 5.4-STABLE #0: Thu Sep 29 14:09:36 MSD 2005 root at post2.tehnomir.lipetsk.ru:/usr/obj/usr/src/sys/MCOM i386
>Description:
kevent syscall with aio filter invoke system reboot without sync under regular user
and may be security issue
>How-To-Repeat:
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <aio.h>
class KQueue {
public:
~KQueue();
KQueue();
KQueue & testRegularFiles();
protected:
private:
int kqueue_;
};
KQueue::~KQueue()
{
if( close(kqueue_) != 0 ){
perror(NULL);
abort();
}
}
KQueue::KQueue()
{
kqueue_ = kqueue();
if( kqueue_ == -1 ){
perror(NULL);
abort();
}
}
KQueue & KQueue::testRegularFiles()
{
struct kevent kev;
int f;
f = open("qwert",O_RDWR | O_CREAT/* | O_NONBLOCK*/);
if( f == -1 ){
perror(NULL);
abort();
}
if( fcntl(f,F_SETFL,fcntl(f,F_GETFL,0) | O_NONBLOCK) != 0 ){
perror(NULL);
abort();
}
char b[1 * 1024 * 1024];
struct aiocb iocb;
memset(&iocb,0,sizeof(iocb));
iocb.aio_fildes = f;
iocb.aio_nbytes = sizeof(b);
iocb.aio_buf = b;
iocb.aio_offset = 0;
iocb.aio_sigevent.sigev_notify_kqueue = kqueue_;
iocb.aio_sigevent.sigev_notify = SIGEV_KEVENT;
if( aio_write(&iocb) != 0 ){
perror(NULL);
abort();
}
int kcount;
struct timespec timeout = { 0, 0 }, * pto = NULL;
for(;;){
kcount = kevent(kqueue_,NULL,0,&kev,1,NULL);
if( kcount == -1 ){
perror(NULL);
abort();
}
if( kcount == 0 ) break;
if( kev.flags & EV_ERROR ){
errno = kev.data;
perror(NULL);
abort();
}
if( kev.flags & EV_EOF ){
if( (errno = kev.fflags) != 0 ){
perror(NULL);
abort();
}
}
if( kev.filter == EVFILT_READ ){
fprintf(stderr,"EVFILT_READ\n");
}
if( kev.filter == EVFILT_WRITE ){
fprintf(stderr,"EVFILT_READ\n");
}
if( kev.filter == EVFILT_AIO ){
fprintf(stderr,"EVFILT_AIO\n");
kev.ident = (uintptr_t) &iocb;
kev.filter = EVFILT_AIO;
// this flags invoke reboot
kev.flags |= EV_CLEAR;
// reboot after this call
if( kevent(kqueue_,&kev,1,NULL,0,NULL) == -1 ){
perror(NULL);
abort();
}
}
pto = &timeout;
}
if( close(f) != 0 ){
perror(NULL);
abort();
}
return *this;
}
int main(int argc,char ** argv)
{
KQueue kqueue;
kqueue.testRegularFiles();
return 0;
}
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list