Topic: Buffer Overflow in FreeBSD
Versions: All the versions of FreeBSD are broken (4.x, 5.x, 6.0)
All discussion refers to CURRENT-6.0, for other versions some things could
change (btw bugged).
Discussion involves a lot of arch x32 dependant mechanisms, so, in some
points, could sound a little bit dark.
A buffer overflow has been found in i386/i386/trap.c syscall() function
of FreeBSD official
In order to rule syscalls mechanism, the 'particular' interrupt 128 (0x80)
is provided in the
IDT vector. To serve this interrupt, i386/i386/exception.s int0x80_syscall()
done and, in the end, it calls syscall().
syscall() is responsible for loading arguments from a syscall and copying
them in a kspace
pointer in order to accessing them. The code to do that is the following:
struct trapframe frame;
struct sysent *callp;
struct thread *td = curthread;
struct proc *p = td->td_proc;
narg = callp->sy_narg & SYF_ARGMASK; (<- you can see it's the only one
if (params != NULL && narg != 0)
error = copyin(params, (caddr_t)args,
(u_int)(narg * sizeof(int)));
error = 0;
> grep SYF_ARGMASK /usr/src/sys/sys/sysent.h
#define SYF_ARGMASK 0x0000FFFF
It's obvious that the amount of selectable memory is beyond the (8 * sizeof(int))
args array, so it would overwrite the saved eip by syscall() (it's invoked
through a call) or
making an interesting pointer corruption overwriting struct proc *p .
It's exploitable, but the only one way I discovered is to link a new syscall
to the sysent
array and to do this you need to be root; I've no time to work on this vulnerability,
but i think another way could be found. However it could give serious problems
A good patch could be a dinamyc memory allocation for args, but it's not
a good solution
in order to mantain a well performanced system; another one could be a strongest
check, but it's not a good solution in order to set a good flexibility.
You can get proof of concept code in http://www.gufi.org/~rookie/poc.tar.gz
P.S: in order to try the bug before make and link kld, later do 'make test'
and start ./poc exe