Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
SPROG(7)	     BSD Miscellaneous Information Manual	      SPROG(7)

     sprog -- secure programming practices

     Security issues have crept	into many systems over the years.  This	docu-
     ment is a guide for programming practices that prevent these problems.

     Writing secure applications takes a very scrutinous and pessimistic out-
     look.  Applications should	be run with the	principle of "least privilege"
     so	that no	process	is ever	running	with more than the bare	minimum	access
     it	needs to accomplish its	function.  Previously tested code should be
     reused whenever possible.	Generally, anything beyond the control of a
     program should never be trusted.  This includes all forms of user input,
     system resources, interprocess communication, and the timing of events.

   Buffer Overflows
     One of the	most common types of security problems is the buffer overflow.
     In	short, if a program is not careful with	the data it receives, it may
     be	possible for this data to be written across memory, overwriting	the
     return address for	a function call, and the program will be forced	to run
     code that does unfriendly things.

     A good number of functions	in the standard	C library make it difficult or
     even impossible to	prevent	buffer overflows when used.  These include
     fscanf(3),	gets(3), getwd(3), realpath(3),	scanf(3), sprintf(3),
     strcat(3),	strcpy(3), vscanf(3), and vsprintf(3).

     Many other	functions that deal with strings can also open up a potential
     buffer overflow when not used carefully.  For example, strncat(3) does
     not go out	of its way to provide NUL character termination.  Of course,
     the proper	length must always be specified.  Usage	of strlcat(3) and
     strlcpy(3)	ensure that strings are	null terminated	and of the specified

     Functions that receive a string format must also be used carefully.  It
     is	possible for a string to contain additional format specifiers, which
     open up another possibility for a buffer overflow.	 Never pass a string
     with untrusted data without using `%s'.  Always use the proper secure id-

	   function("%s", string);

     There are mechanisms that provide a backstop for these problems at	the
     library and compiler levels, however, there is no substitute for simply
     writing good code.

   Set-user-ID Issues
     In	many cases, it may be necessary	for a program to operate with an in-
     creased set of permissions.  Reasons for this include binding to pro-
     tected sockets, reading and writing certain files and directories,	and
     access to various resources.  Using a setuid program is frequently	the
     solution.	However, it is important that programs give up these privi-
     leges as soon as possible.	 For example, if a program is binding to a
     protected socket, it should give up its privileges	as soon	as it has fin-
     ished binding to that socket.  This is accomplished with the setuid(2)
     family of system calls.

   Limited Environments
     The traditional method of restricting a process is	with the chroot(2)
     system call.  This	system call changes the	root directory from which all
     other paths are referenced	for a process and any child processes.	Of
     course, the process must have access to this path to begin	with.  The new
     environment does not actually take	effect until chdir(2) is called	to
     place the process into the	new environment.  Unfortunately, a process can
     break out of this environment if root access is obtained.

     Often, jail(2) can	be used	to create a more complete and enclosed envi-
     ronment than chroot(2) can	provide.  A jail limits	all processes inside
     that environment, including processes with	superuser privileges.

     Fine grained privileges, as described by POSIX.1e extensions, are cur-
     rently a work in progress,	and the	focus of the TrustedBSD	Project.  More
     information can be	found at

     Programs should not make assumptions about	the environment	in which they
     are running.  This	includes user input, signals, environment variables,
     system resources, interprocess communications, and	shared memory, amongst
     other things that are beyond the control of the program.  They should not
     assume that all forms of invalid data can be detected either.  Instead,
     they should use positive filtering, and only allow	a specific subset of
     inputs that are known to be safe.	This is	the same logic that an admin-
     istrator should apply to a	firewall, that is, deny	by default and specify
     what is to	be accepted.

   Race	Conditions
     A race condition is anomalous behavior caused by the relative timing of
     events.  Programs should not assume that a	particular event will occur
     before another.  The most common causes of	race conditions	are signals,
     access checks, and	file reads.  Signals are asynchronous by nature, so
     special care must be taken	while dealing with them.  Attempting to	check
     access with sequential non-atomic operations is a very bad	idea, as files
     can be moved and changed at any given time.  Instead of using a sequence
     of	access(2) and open(2), use seteuid(2) and then call open(2) directly.
     Set umask(2) properly beforehand.

     jail(2), setuid(2), strlcat(3), strlcpy(3)

     Eric Melville <> originally wrote this document based on
     a chapter of the FreeBSD Developer's Handbook written by Murray Stokely

BSD				 June 3, 2001				   BSD


Want to link to this manual page? Use this URL:

home | help