blob: 8e74203fa98aad2cde0a1540618f30f21a2c9dd5 [file] [log] [blame]
<html lang="en">
<head>
<title>Setuid Program Example - The GNU C Library</title>
<meta http-equiv="Content-Type" content="text/html">
<meta name="description" content="The GNU C Library">
<meta name="generator" content="makeinfo 4.13">
<link title="Top" rel="start" href="index.html#Top">
<link rel="up" href="Users-and-Groups.html#Users-and-Groups" title="Users and Groups">
<link rel="prev" href="Enable_002fDisable-Setuid.html#Enable_002fDisable-Setuid" title="Enable/Disable Setuid">
<link rel="next" href="Tips-for-Setuid.html#Tips-for-Setuid" title="Tips for Setuid">
<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">
<!--
This file documents the GNU C library.
This is Edition 0.12, last updated 2007-10-27,
of `The GNU C Library Reference Manual', for version
2.8 (Sourcery G++ Lite 2011.03-41).
Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2002,
2003, 2007, 2008, 2010 Free Software Foundation, Inc.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
any later version published by the Free Software Foundation; with the
Invariant Sections being ``Free Software Needs Free Documentation''
and ``GNU Lesser General Public License'', the Front-Cover texts being
``A GNU Manual'', and with the Back-Cover Texts as in (a) below. A
copy of the license is included in the section entitled "GNU Free
Documentation License".
(a) The FSF's Back-Cover Text is: ``You have the freedom to
copy and modify this GNU manual. Buying copies from the FSF
supports it in developing GNU and promoting software freedom.''-->
<meta http-equiv="Content-Style-Type" content="text/css">
<style type="text/css"><!--
pre.display { font-family:inherit }
pre.format { font-family:inherit }
pre.smalldisplay { font-family:inherit; font-size:smaller }
pre.smallformat { font-family:inherit; font-size:smaller }
pre.smallexample { font-size:smaller }
pre.smalllisp { font-size:smaller }
span.sc { font-variant:small-caps }
span.roman { font-family:serif; font-weight:normal; }
span.sansserif { font-family:sans-serif; font-weight:normal; }
--></style>
<link rel="stylesheet" type="text/css" href="../cs.css">
</head>
<body>
<div class="node">
<a name="Setuid-Program-Example"></a>
<p>
Next:&nbsp;<a rel="next" accesskey="n" href="Tips-for-Setuid.html#Tips-for-Setuid">Tips for Setuid</a>,
Previous:&nbsp;<a rel="previous" accesskey="p" href="Enable_002fDisable-Setuid.html#Enable_002fDisable-Setuid">Enable/Disable Setuid</a>,
Up:&nbsp;<a rel="up" accesskey="u" href="Users-and-Groups.html#Users-and-Groups">Users and Groups</a>
<hr>
</div>
<h3 class="section">29.9 Setuid Program Example</h3>
<p>Here's an example showing how to set up a program that changes its
effective user ID.
<p>This is part of a game program called <code>caber-toss</code> that manipulates
a file <samp><span class="file">scores</span></samp> that should be writable only by the game program
itself. The program assumes that its executable file will be installed
with the setuid bit set and owned by the same user as the <samp><span class="file">scores</span></samp>
file. Typically, a system administrator will set up an account like
<code>games</code> for this purpose.
<p>The executable file is given mode <code>4755</code>, so that doing an
&lsquo;<samp><span class="samp">ls -l</span></samp>&rsquo; on it produces output like:
<pre class="smallexample"> -rwsr-xr-x 1 games 184422 Jul 30 15:17 caber-toss
</pre>
<p class="noindent">The setuid bit shows up in the file modes as the &lsquo;<samp><span class="samp">s</span></samp>&rsquo;.
<p>The scores file is given mode <code>644</code>, and doing an &lsquo;<samp><span class="samp">ls -l</span></samp>&rsquo; on
it shows:
<pre class="smallexample"> -rw-r--r-- 1 games 0 Jul 31 15:33 scores
</pre>
<p>Here are the parts of the program that show how to set up the changed
user ID. This program is conditionalized so that it makes use of the
file IDs feature if it is supported, and otherwise uses <code>setreuid</code>
to swap the effective and real user IDs.
<pre class="smallexample"> #include &lt;stdio.h&gt;
#include &lt;sys/types.h&gt;
#include &lt;unistd.h&gt;
#include &lt;stdlib.h&gt;
/* <span class="roman">Remember the effective and real UIDs.</span> */
static uid_t euid, ruid;
/* <span class="roman">Restore the effective UID to its original value.</span> */
void
do_setuid (void)
{
int status;
#ifdef _POSIX_SAVED_IDS
status = seteuid (euid);
#else
status = setreuid (ruid, euid);
#endif
if (status &lt; 0) {
fprintf (stderr, "Couldn't set uid.\n");
exit (status);
}
}
/* <span class="roman">Set the effective UID to the real UID.</span> */
void
undo_setuid (void)
{
int status;
#ifdef _POSIX_SAVED_IDS
status = seteuid (ruid);
#else
status = setreuid (euid, ruid);
#endif
if (status &lt; 0) {
fprintf (stderr, "Couldn't set uid.\n");
exit (status);
}
}
/* <span class="roman">Main program.</span> */
int
main (void)
{
/* <span class="roman">Remember the real and effective user IDs.</span> */
ruid = getuid ();
euid = geteuid ();
undo_setuid ();
/* <span class="roman">Do the game and record the score.</span> */
...
}
</pre>
<p>Notice how the first thing the <code>main</code> function does is to set the
effective user ID back to the real user ID. This is so that any other
file accesses that are performed while the user is playing the game use
the real user ID for determining permissions. Only when the program
needs to open the scores file does it switch back to the file user ID,
like this:
<pre class="smallexample"> /* <span class="roman">Record the score.</span> */
int
record_score (int score)
{
FILE *stream;
char *myname;
/* <span class="roman">Open the scores file.</span> */
do_setuid ();
stream = fopen (SCORES_FILE, "a");
undo_setuid ();
/* <span class="roman">Write the score to the file.</span> */
if (stream)
{
myname = cuserid (NULL);
if (score &lt; 0)
fprintf (stream, "%10s: Couldn't lift the caber.\n", myname);
else
fprintf (stream, "%10s: %d feet.\n", myname, score);
fclose (stream);
return 0;
}
else
return -1;
}
</pre>
</body></html>