i386/86065: system reboot without sync (and can be security issue)
Guram Dukashvili
korvin at tehnomir.lipetsk.ru
Tue Sep 13 03:10:27 PDT 2005
>Number: 86065
>Category: i386
>Synopsis: system reboot without sync (and can be security issue)
>Confidential: no
>Severity: critical
>Priority: medium
>Responsible: freebsd-i386
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Tue Sep 13 10:10:25 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator: Guram Dukashvili
>Release: 5.4-STABLE
>Organization:
FOLIUM
>Environment:
post2.tehnomir.lipetsk.ru 5.4-STABLE FreeBSD 5.4-STABLE #2: Wed Sep 7 12:45:39 MSD 2005 root at post2.tehnomir.lipetsk.ru:/usr/obj/usr/src/sys/MCOM i386
>Description:
kqueue + aio problem, source code calling this attached, executed under regular user (not root)
>How-To-Repeat:
#if HAVE_CONFIG_H
#include <config.h>
#endif
#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 & testConnect();
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::testConnect()
{
struct kevent kev;
int s;
s = socket(PF_INET,SOCK_STREAM,IPPROTO_IP);
if( s == -1 ){
perror(NULL);
abort();
}
EV_SET(&kev,s,EVFILT_READ | EVFILT_WRITE,EV_ADD | EV_CLEAR,0,0,0);
if( kevent(kqueue_,&kev,1,NULL,0,NULL) == -1 ){
perror(NULL);
abort();
}
struct sockaddr_in addr;
addr.sin_len = sizeof(addr);
addr.sin_family = PF_INET;
addr.sin_addr.s_addr = inet_addr("192.168.201.200");//INADDR_LOOPBACK;
addr.sin_port = htons(21);
if( fcntl(s,F_SETFL,fcntl(s,F_GETFL,0) | O_NONBLOCK) != 0 ){
perror(NULL);
abort();
}
if( connect(s,(const struct sockaddr *) &addr,sizeof(addr)) != 0 && errno != EINPROGRESS ){
perror(NULL);
abort();
}
int kcount;
struct timespec timeout = { 0, 0 }, * pto = NULL;
char b[1];
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 connect failed
// ident = 7, filter = -1, flags = 32789, fflags = 60, data = 0, udata = 0x0
errno = kev.fflags;
perror(NULL);
abort();
}
if( kev.filter == EVFILT_READ ){
// fprintf(stderr,"EVFILT_READ\n");
}
if( kev.filter == EVFILT_WRITE ){
fprintf(stderr,"EVFILT_READ\n");
}
ssize_t r;
while( (r = recv(s,b,sizeof(b),0)) > 0 )
fprintf(stderr,"%c",b[0]);
if( r <= 0 ){
if( errno != EAGAIN ){
perror(NULL);
abort();
}
static char cmd[] = "USER korvin\n";
r = send(s,cmd,sizeof(cmd) - 1,0);
if( r <= 0 ){
perror(NULL);
abort();
}
}
pto = &timeout;
}
if( shutdown(s,SHUT_RDWR) != 0 ){
perror(NULL);
abort();
}
if( close(s) != 0 ){
perror(NULL);
abort();
}
return *this;
}
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;
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.testConnect();
kqueue.testRegularFiles();
return 0;
}
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-i386
mailing list