aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src/update-game-score.c
diff options
context:
space:
mode:
authorUlrich Müller2015-01-16 09:25:25 +0100
committerUlrich Müller2015-01-21 21:33:17 +0100
commit20f66485526b69eb26f2e70bd835a5e1333559d5 (patch)
tree2571c73468acb238fbae55f3655e757ff284319f /lib-src/update-game-score.c
parent59e7fe6d0c6988687b53c279941c9ebb3f887eed (diff)
downloademacs-20f66485526b69eb26f2e70bd835a5e1333559d5.tar.gz
emacs-20f66485526b69eb26f2e70bd835a5e1333559d5.zip
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.
Diffstat (limited to 'lib-src/update-game-score.c')
-rw-r--r--lib-src/update-game-score.c33
1 files changed, 19 insertions, 14 deletions
diff --git a/lib-src/update-game-score.c b/lib-src/update-game-score.c
index d3354af2783..4f154832c81 100644
--- a/lib-src/update-game-score.c
+++ b/lib-src/update-game-score.c
@@ -21,8 +21,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 21
22 22
23/* This program allows a game to securely and atomically update a 23/* This program allows a game to securely and atomically update a
24 score file. It should be installed setuid, owned by an appropriate 24 score file. It should be installed either setuid or setgid, owned
25 user like `games'. 25 by an appropriate user or group like `games'.
26 26
27 Alternatively, it can be compiled without HAVE_SHARED_GAME_DIR 27 Alternatively, it can be compiled without HAVE_SHARED_GAME_DIR
28 defined, and in that case it will store scores in the user's home 28 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,
88 ptrdiff_t *size, struct score_entry const *newscore); 88 ptrdiff_t *size, struct score_entry const *newscore);
89static void sort_scores (struct score_entry *scores, ptrdiff_t count, 89static void sort_scores (struct score_entry *scores, ptrdiff_t count,
90 bool reverse); 90 bool reverse);
91static int write_scores (const char *filename, 91static int write_scores (const char *filename, mode_t mode,
92 const struct score_entry *scores, ptrdiff_t count); 92 const struct score_entry *scores, ptrdiff_t count);
93 93
94static _Noreturn void 94static _Noreturn void
@@ -122,18 +122,19 @@ get_user_id (void)
122} 122}
123 123
124static const char * 124static const char *
125get_prefix (bool running_suid, const char *user_prefix) 125get_prefix (bool privileged, const char *user_prefix)
126{ 126{
127 if (!running_suid && user_prefix == NULL) 127 if (privileged)
128 lose ("Not using a shared game directory, and no prefix given.");
129 if (running_suid)
130 { 128 {
131#ifdef HAVE_SHARED_GAME_DIR 129#ifdef HAVE_SHARED_GAME_DIR
132 return HAVE_SHARED_GAME_DIR; 130 return HAVE_SHARED_GAME_DIR;
133#else 131#else
134 lose ("This program was compiled without HAVE_SHARED_GAME_DIR,\n and should not be suid."); 132 lose ("This program was compiled without HAVE_SHARED_GAME_DIR,\n"
133 "and should not run with elevated privileges.");
135#endif 134#endif
136 } 135 }
136 if (user_prefix == NULL)
137 lose ("Not using a shared game directory, and no prefix given.");
137 return user_prefix; 138 return user_prefix;
138} 139}
139 140
@@ -173,7 +174,7 @@ int
173main (int argc, char **argv) 174main (int argc, char **argv)
174{ 175{
175 int c; 176 int c;
176 bool running_suid; 177 bool running_suid, running_sgid;
177 void *lockstate; 178 void *lockstate;
178 char *scorefile; 179 char *scorefile;
179 char *end, *nl, *user, *data; 180 char *end, *nl, *user, *data;
@@ -214,8 +215,11 @@ main (int argc, char **argv)
214 usage (EXIT_FAILURE); 215 usage (EXIT_FAILURE);
215 216
216 running_suid = (getuid () != geteuid ()); 217 running_suid = (getuid () != geteuid ());
218 running_sgid = (getgid () != getegid ());
219 if (running_suid && running_sgid)
220 lose ("This program can run either suid or sgid, but not both.");
217 221
218 prefix = get_prefix (running_suid, user_prefix); 222 prefix = get_prefix (running_suid || running_sgid, user_prefix);
219 223
220 scorefile = malloc (strlen (prefix) + strlen (argv[optind]) + 2); 224 scorefile = malloc (strlen (prefix) + strlen (argv[optind]) + 2);
221 if (!scorefile) 225 if (!scorefile)
@@ -270,7 +274,8 @@ main (int argc, char **argv)
270 scores += scorecount - max_scores; 274 scores += scorecount - max_scores;
271 scorecount = max_scores; 275 scorecount = max_scores;
272 } 276 }
273 if (write_scores (scorefile, scores, scorecount) < 0) 277 if (write_scores (scorefile, running_sgid ? 0664 : 0644,
278 scores, scorecount) < 0)
274 { 279 {
275 unlock_file (scorefile, lockstate); 280 unlock_file (scorefile, lockstate);
276 lose_syserr ("Failed to write scores file"); 281 lose_syserr ("Failed to write scores file");
@@ -421,8 +426,8 @@ sort_scores (struct score_entry *scores, ptrdiff_t count, bool reverse)
421} 426}
422 427
423static int 428static int
424write_scores (const char *filename, const struct score_entry *scores, 429write_scores (const char *filename, mode_t mode,
425 ptrdiff_t count) 430 const struct score_entry *scores, ptrdiff_t count)
426{ 431{
427 int fd; 432 int fd;
428 FILE *f; 433 FILE *f;
@@ -435,7 +440,7 @@ write_scores (const char *filename, const struct score_entry *scores,
435 if (fd < 0) 440 if (fd < 0)
436 return -1; 441 return -1;
437#ifndef DOS_NT 442#ifndef DOS_NT
438 if (fchmod (fd, 0644) != 0) 443 if (fchmod (fd, mode) != 0)
439 return -1; 444 return -1;
440#endif 445#endif
441 f = fdopen (fd, "w"); 446 f = fdopen (fd, "w");