diff options
| author | Ulrich Müller | 2015-01-16 09:25:25 +0100 |
|---|---|---|
| committer | Ulrich Müller | 2015-01-21 21:33:17 +0100 |
| commit | 20f66485526b69eb26f2e70bd835a5e1333559d5 (patch) | |
| tree | 2571c73468acb238fbae55f3655e757ff284319f /lib-src/update-game-score.c | |
| parent | 59e7fe6d0c6988687b53c279941c9ebb3f887eed (diff) | |
| download | emacs-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.c | 33 |
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); |
| 89 | static void sort_scores (struct score_entry *scores, ptrdiff_t count, | 89 | static void sort_scores (struct score_entry *scores, ptrdiff_t count, |
| 90 | bool reverse); | 90 | bool reverse); |
| 91 | static int write_scores (const char *filename, | 91 | static 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 | ||
| 94 | static _Noreturn void | 94 | static _Noreturn void |
| @@ -122,18 +122,19 @@ get_user_id (void) | |||
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | static const char * | 124 | static const char * |
| 125 | get_prefix (bool running_suid, const char *user_prefix) | 125 | get_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 | |||
| 173 | main (int argc, char **argv) | 174 | main (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 | ||
| 423 | static int | 428 | static int |
| 424 | write_scores (const char *filename, const struct score_entry *scores, | 429 | write_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"); |