1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-06 06:20:55 -08:00

Allow update-game-score to run sgid instead of suid.

* configure.ac (gamegroup): New AC_SUBST.
(--with-gameuser): Allow to specify a group instead of a user.
In the default case, check at configure time if a 'games' user
exists.
* lib-src/update-game-score.c: Allow the program to run sgid
instead of suid, in order to match common practice for most games.
(main): Check if we are running sgid.  Pass appropriate file
permission bits to 'write_scores'.
(write_scores): New 'mode' argument, instead of hardcoding 0644.
(get_prefix): Update error message.
* lib-src/Makefile.in (gamegroup): New variable, set by configure.
($(DESTDIR)${archlibdir}): Handle both suid or sgid when
installing the 'update-game-score' program.
* lisp/play/gamegrid.el (gamegrid-add-score-with-update-game-score):
Allow the 'update-game-score' helper program to run suid or sgid.
This commit is contained in:
Ulrich Müller 2015-01-16 09:25:25 +01:00
parent 59e7fe6d0c
commit 20f6648552
8 changed files with 85 additions and 25 deletions

View file

@ -21,8 +21,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
/* This program allows a game to securely and atomically update a
score file. It should be installed setuid, owned by an appropriate
user like `games'.
score file. It should be installed either setuid or setgid, owned
by an appropriate user or group like `games'.
Alternatively, it can be compiled without HAVE_SHARED_GAME_DIR
defined, and in that case it will store scores in the user's home
@ -88,7 +88,7 @@ static int push_score (struct score_entry **scores, ptrdiff_t *count,
ptrdiff_t *size, struct score_entry const *newscore);
static void sort_scores (struct score_entry *scores, ptrdiff_t count,
bool reverse);
static int write_scores (const char *filename,
static int write_scores (const char *filename, mode_t mode,
const struct score_entry *scores, ptrdiff_t count);
static _Noreturn void
@ -122,18 +122,19 @@ get_user_id (void)
}
static const char *
get_prefix (bool running_suid, const char *user_prefix)
get_prefix (bool privileged, const char *user_prefix)
{
if (!running_suid && user_prefix == NULL)
lose ("Not using a shared game directory, and no prefix given.");
if (running_suid)
if (privileged)
{
#ifdef HAVE_SHARED_GAME_DIR
return HAVE_SHARED_GAME_DIR;
#else
lose ("This program was compiled without HAVE_SHARED_GAME_DIR,\n and should not be suid.");
lose ("This program was compiled without HAVE_SHARED_GAME_DIR,\n"
"and should not run with elevated privileges.");
#endif
}
if (user_prefix == NULL)
lose ("Not using a shared game directory, and no prefix given.");
return user_prefix;
}
@ -173,7 +174,7 @@ int
main (int argc, char **argv)
{
int c;
bool running_suid;
bool running_suid, running_sgid;
void *lockstate;
char *scorefile;
char *end, *nl, *user, *data;
@ -214,8 +215,11 @@ main (int argc, char **argv)
usage (EXIT_FAILURE);
running_suid = (getuid () != geteuid ());
running_sgid = (getgid () != getegid ());
if (running_suid && running_sgid)
lose ("This program can run either suid or sgid, but not both.");
prefix = get_prefix (running_suid, user_prefix);
prefix = get_prefix (running_suid || running_sgid, user_prefix);
scorefile = malloc (strlen (prefix) + strlen (argv[optind]) + 2);
if (!scorefile)
@ -270,7 +274,8 @@ main (int argc, char **argv)
scores += scorecount - max_scores;
scorecount = max_scores;
}
if (write_scores (scorefile, scores, scorecount) < 0)
if (write_scores (scorefile, running_sgid ? 0664 : 0644,
scores, scorecount) < 0)
{
unlock_file (scorefile, lockstate);
lose_syserr ("Failed to write scores file");
@ -421,8 +426,8 @@ sort_scores (struct score_entry *scores, ptrdiff_t count, bool reverse)
}
static int
write_scores (const char *filename, const struct score_entry *scores,
ptrdiff_t count)
write_scores (const char *filename, mode_t mode,
const struct score_entry *scores, ptrdiff_t count)
{
int fd;
FILE *f;
@ -435,7 +440,7 @@ write_scores (const char *filename, const struct score_entry *scores,
if (fd < 0)
return -1;
#ifndef DOS_NT
if (fchmod (fd, 0644) != 0)
if (fchmod (fd, mode) != 0)
return -1;
#endif
f = fdopen (fd, "w");