diff options
author | Ulrich Müller <ulm@gentoo.org> | 2015-01-16 09:25:25 +0100 |
---|---|---|
committer | Ulrich Müller <ulm@gentoo.org> | 2015-01-21 21:33:17 +0100 |
commit | 20f66485526b69eb26f2e70bd835a5e1333559d5 (patch) | |
tree | 2571c73468acb238fbae55f3655e757ff284319f /lib-src | |
parent | 59e7fe6d0c6988687b53c279941c9ebb3f887eed (diff) | |
download | emacs-20f66485526b69eb26f2e70bd835a5e1333559d5.tar.gz |
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')
-rw-r--r-- | lib-src/ChangeLog | 12 | ||||
-rw-r--r-- | lib-src/Makefile.in | 16 | ||||
-rw-r--r-- | lib-src/update-game-score.c | 33 |
3 files changed, 43 insertions, 18 deletions
diff --git a/lib-src/ChangeLog b/lib-src/ChangeLog index 37f037ef324..b67038ff81a 100644 --- a/lib-src/ChangeLog +++ b/lib-src/ChangeLog @@ -1,3 +1,15 @@ +2015-01-21 Ulrich Müller <ulm@gentoo.org> + + * 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. + * Makefile.in (gamegroup): New variable, set by configure. + ($(DESTDIR)${archlibdir}): Handle both suid or sgid when + installing the 'update-game-score' program. + 2015-01-16 Eli Zaretskii <eliz@gnu.org> * Makefile.in (AM_V_RC, am__v_RC_, am__v_RC_0, am__v_RC_1): New diff --git a/lib-src/Makefile.in b/lib-src/Makefile.in index 01592bd21a5..2997f1b35a8 100644 --- a/lib-src/Makefile.in +++ b/lib-src/Makefile.in @@ -122,6 +122,7 @@ archlibdir=@archlibdir@ gamedir=@gamedir@ gameuser=@gameuser@ +gamegroup=@gamegroup@ # ==================== Utility Programs for the Build ================= @@ -263,10 +264,17 @@ $(DESTDIR)${archlibdir}: all umask 022; ${MKDIR_P} "$(DESTDIR)${gamedir}"; \ touch "$(DESTDIR)${gamedir}/snake-scores"; \ touch "$(DESTDIR)${gamedir}/tetris-scores" - -if chown ${gameuser} "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}" && chmod u+s "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}"; then \ - chown ${gameuser} "$(DESTDIR)${gamedir}"; \ - chmod u=rwx,g=rwx,o=rx "$(DESTDIR)${gamedir}"; \ - fi +ifneq ($(gameuser),) + chown ${gameuser} "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}" + chmod u+s,go-r "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}" + chown ${gameuser} "$(DESTDIR)${gamedir}" + chmod u=rwx,g=rx,o=rx "$(DESTDIR)${gamedir}" +else ifneq ($(gamegroup),) + chgrp ${gamegroup} "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}" + chmod g+s,o-r "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}" + chgrp ${gamegroup} "$(DESTDIR)${gamedir}" + chmod u=rwx,g=rwx,o=rx "$(DESTDIR)${gamedir}" +endif exp_archlibdir=`cd "$(DESTDIR)${archlibdir}" && /bin/pwd`; \ if [ "$$exp_archlibdir" != "`cd ${srcdir} && /bin/pwd`" ]; then \ for file in ${SCRIPTS}; do \ 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/>. */ /* 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"); |