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

FreeBSD Manual Pages


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

     setuid -- checklist for security of setuid	programs

     Please note: This manual page was written long ago, and is	in need	of up-
     dating to match today's systems.  We think	it is valuable enough to in-
     clude, even though	parts of it are	outdated.  A carefully-researched up-
     dated version would be very useful, if anyone is feeling enthusiastic...

     Writing a secure setuid (or setgid) program is tricky.  There are a num-
     ber of possible ways of subverting	such a program.	 The most conspicuous
     security holes occur when a setuid	program	is not sufficiently careful to
     avoid giving away access to resources it legitimately has the use of.
     Most of the other attacks are basically a matter of altering the pro-
     gram's environment	in unexpected ways and hoping it will fail in some se-
     curity-breaching manner.  There are generally three categories of envi-
     ronment manipulation: supplying a legal but unexpected environment	that
     may cause the program to directly do something insecure, arranging	for
     error conditions that the program may not handle correctly, and the spe-
     cialized subcategory of giving the	program	inadequate resources in	hopes
     that it won't respond properly.

     The following are general considerations of security when writing a se-
     tuid program.

     +o	 The program should run	with the weakest userid	possible, preferably
	 one used only by itself.  A security hole in a	setuid program running
	 with a	highly-privileged userid can compromise	an entire system.  Se-
	 curity-critical programs like passwd(1) should	always have private
	 userids, to minimize possible damage from penetrations	elsewhere.

     +o	 The result of getlogin(2) or ttyname(3) may be	wrong if the descrip-
	 tors have been	meddled	with.  There is	no foolproof way to determine
	 the controlling terminal or the login name (as	opposed	to uid)	on V7.

     +o	 On some systems, the setuid bit may not be honored if the program is
	 run by	root, so the program may find itself running as	root.

     +o	 Programs that attempt to use creat(3) for locking can foul up when
	 run by	root; use of link(2) is	preferred when implementing locking.
	 Using chmod(2)	for locking is an obvious disaster.

     +o	 Breaking an existing lock is very dangerous; the breakdown of a lock-
	 ing protocol may be symptomatic of far	worse problems.	 Doing so on
	 the basis of the lock being `old' is sometimes	necessary, but pro-
	 grams can run for surprising lengths of time on heavily-loaded	sys-

     +o	 Care must be taken that user requests for I/O are checked for permis-
	 sions using the user's	permissions, not the program's.	 Use of
	 access(2) is recommended.

     +o	 Programs executed at user request (e.g. shell escapes)	must not re-
	 ceive the setuid program's permissions; use of	daughter processes and
	 "setuid(getuid())" plus "setgid(getgid())" after fork(2) but before
	 exec(3) is vital.

     +o	 Similarly, programs executed at user request must not receive other
	 sensitive resources, notably file descriptors.	 Use of	fcntl(2)
	 F_CLOSEM, FILENO_STDERR + 1 (close all	fd's greater than stderr)
	 and/or	fcntl(2) F_SETFD, FD_CLOEXEC (close-on-exec) arrangements on
	 systems which have them is recommended.

	 Other resources should	also be	examined for sanity and	possibly set
	 to desired settings, such as the current working directory, signal
	 disposition, resource limits, environment, umask, group membership,

	 Programs activated by one user	but handling traffic on	behalf of oth-
	 ers (e.g. daemons) should avoid doing "setuid(getuid())" or
	 "setgid(getgid())", since the original	invoker's identity is almost
	 certainly inappropriate.  On systems which permit it, use of
	 "setuid(geteuid())" and "setgid(getegid())" is	recommended when per-
	 forming work on behalf	of the system as opposed to a specific user.

     +o	 There are inherent permission problems	when a setuid program executes
	 another setuid	program, since the permissions are not additive.  Care
	 should	be taken that created files are	not owned by the wrong person.
	 Use of	"setuid(geteuid())" and	its gid	counterpart can	help, if the
	 system	allows them.

     +o	 Care should be	taken that newly-created files do not have the wrong
	 permission or ownership even momentarily.  Permissions	should be ar-
	 ranged	by using umask(2) in advance, rather than by creating the file
	 wide-open and then using chmod(2).  Ownership can get sticky due to
	 the limitations of the	setuid concept,	although using a daughter
	 process connected by a	pipe can help.

     +o	 Setuid	programs should	be especially careful about error checking,
	 and the normal	response to a strange situation	should be termination,
	 rather	than an	attempt	to carry on.

     The following are ways in which the program may be	induced	to carelessly
     give away its special privileges.

     +o	 The directory the program is started in, or directories it may	plau-
	 sibly chdir(2)	to, may	contain	programs with the same names as	system
	 programs, placed there	in hopes that the program will activate	a
	 shell with a permissive PATH setting.	PATH should always be stan-
	 dardized before invoking a shell (either directly or via popen(3) or
	 execvp(3) or execlp(3)).

     +o	 Similarly, a bizarre IFS setting may alter the	interpretation of a
	 shell command in really strange ways, possibly	causing	a user-sup-
	 plied program to be invoked.  IFS too should always be	standardized
	 before	invoking a shell.

     +o	 Environment variables in general cannot be trusted.  Their contents
	 should	never be taken for granted.

     +o	 Setuid	shell files (on	systems	which implement	such) simply cannot
	 cope adequately with some of these problems.  They also have some
	 nasty problems	like trying to run a .profile when run under a suit-
	 able name.  They are terminally insecure, and must be avoided.

     +o	 Relying on the	contents of files placed in publically-writable	direc-
	 tories, such as /tmp, is a nearly-incurable security problem.	Setuid
	 programs should avoid using /tmp entirely, if humanly possible.  The
	 sticky-directories modification (sticky bit on	for a directory	means
	 only owner of a file can remove it) helps, but	is not a complete so-

     +o	 A related problem is that spool directories, holding information that
	 the program will trust	later, must never be publically	writable even
	 if the	files in the directory are protected.  Among other sinister
	 manipulations that can	be performed, note that	on many	Unixes,	a core
	 dump of a setuid program is owned by the program's owner and not by
	 the user running it.

     The following are unusual but possible error conditions that the program
     should cope with properly (resource-exhaustion questions are considered
     separately, see below).

     +o	 The value of argc might be 0.

     +o	 The setting of	the umask(2) might not be sensible.  In	any case, it
	 should	be standardized	when creating files not	intended to be owned
	 by the	user.

     +o	 One or	more of	the standard descriptors might be closed, so that an
	 opened	file might get (say) descriptor	1, causing chaos if the	pro-
	 gram tries to do a printf(3).

     +o	 The current directory (or any of its parents) may be unreadable and
	 unsearchable.	On many	systems	pwd(1) does not	run setuid-root, so it
	 can fail under	such conditions.

     +o	 Descriptors shared by other processes (i.e., any that are open	on
	 startup) may be manipulated in	strange	ways by	said processes.

     +o	 The standard descriptors may refer to a terminal which	has a bizarre
	 mode setting, or which	cannot be opened again,	or which gives end-of-
	 file on any read attempt, or which cannot be read or written success-

     +o	 The process may be hit	by interrupt, quit, hangup, or broken-pipe
	 signals, singly or in fast succession.	 The user may deliberately ex-
	 ploit the race	conditions inherent in catching	signals; ignoring sig-
	 nals is safe, but catching them is not.

     +o	 Although non-keyboard signals cannot be sent by ordinary users	in V7,
	 they may perhaps be sent by the system	authorities (e.g. to indicate
	 that the system is about to shut down), so the	possibility cannot be

     +o	 On some systems there may be an alarm(3) signal pending on startup.

     +o	 The program may have children it did not create.  This	is normal when
	 the process is	part of	a pipeline.

     +o	 In some non-V7	systems, users can change the ownerships of their
	 files.	 Setuid	programs should	avoid trusting the owner identifica-
	 tion of a file.

     +o	 User-supplied arguments and input data	must be	checked	meticulously.
	 Overly-long input stored in an	array without proper bound checking
	 can easily breach security.  When software depends on a file being in
	 a specific format, user-supplied data should never be inserted	into
	 the file without being	checked	first.	Meticulous checking includes
	 allowing for the possibility of non-ASCII characters.

     +o	 Temporary files left in public	directories like /tmp might vanish at
	 inconvenient times.

     The following are resource-exhaustion possibilities that the program
     should respond properly to.

     +o	 The user might	have used up all of his	allowed	processes, so any at-
	 tempt to create a new one (via	fork(2)	or popen(3)) will fail.

     +o	 There might be	many files open, exhausting the	supply of descriptors.
	 Running fcntl(2) F_CLOSEM on systems which have it, is	recommended.

     +o	 There might be	many arguments.

     +o	 The arguments and the environment together might occupy a great deal
	 of space.

     Systems which impose other	resource limitations can open setuid programs
     to	similar	resource-exhaustion attacks.

     Setuid programs which execute ordinary programs without reducing author-
     ity pass all the above problems on	to such	unprepared children.  Stan-
     dardizing the execution environment is only a partial solution.

     passwd(1),	pwd(1),	access(2), chdir(2), chroot(2),	execve(2), fcntl(2),
     fork(2), getlogin(2), link(2), setegid(2),	seteuid(2), setgid(2),
     setgroups(2), setrlimit(2), setuid(2), sigaction(2), umask(2), alarm(3),
     creat(3), execvp(3), popen(3), printf(3), ttyname(3)

     Written by	Henry Spencer, and based on additional outside contributions.

     Henry Spencer <>

     The list really is	rather long...	and probably incomplete.

BSD			       February	26, 2009			   BSD


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

home | help