aboutsummaryrefslogtreecommitdiffstats
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
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.
-rw-r--r--ChangeLog7
-rw-r--r--configure.ac24
-rw-r--r--etc/NEWS7
-rw-r--r--lib-src/ChangeLog12
-rw-r--r--lib-src/Makefile.in16
-rw-r--r--lib-src/update-game-score.c33
-rw-r--r--lisp/ChangeLog5
-rw-r--r--lisp/play/gamegrid.el6
8 files changed, 85 insertions, 25 deletions
diff --git a/ChangeLog b/ChangeLog
index 309b04f26ab..b02203dbe75 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
12015-01-21 Ulrich Müller <ulm@gentoo.org>
2
3 * configure.ac (gamegroup): New AC_SUBST.
4 (--with-gameuser): Allow to specify a group instead of a user.
5 In the default case, check at configure time if a 'games' user
6 exists.
7
12015-01-16 Paul Eggert <eggert@cs.ucla.edu> 82015-01-16 Paul Eggert <eggert@cs.ucla.edu>
2 9
3 Give up on -Wsuggest-attribute=const 10 Give up on -Wsuggest-attribute=const
diff --git a/configure.ac b/configure.ac
index 9db4bdecfcc..47b36fe1839 100644
--- a/configure.ac
+++ b/configure.ac
@@ -392,10 +392,25 @@ OPTION_DEFAULT_ON([compress-install],
392make GZIP_PROG= install]) 392make GZIP_PROG= install])
393 393
394AC_ARG_WITH(gameuser,dnl 394AC_ARG_WITH(gameuser,dnl
395[AS_HELP_STRING([--with-gameuser=USER],[user for shared game score files])]) 395[AS_HELP_STRING([--with-gameuser=USER_OR_GROUP],
396test "X${with_gameuser}" != X && test "${with_gameuser}" != yes \ 396 [user for shared game score files.
397 && gameuser="${with_gameuser}" 397 An argument prefixed by ':' specifies a group instead.])])
398test "X$gameuser" = X && gameuser=games 398gameuser=
399gamegroup=
400case ${with_gameuser} in
401 no) ;;
402 "" | yes)
403 AC_MSG_CHECKING([whether a 'games' user exists])
404 if id -u games >/dev/null 2>&1; then
405 AC_MSG_RESULT([yes])
406 gameuser=games
407 else
408 AC_MSG_RESULT([no])
409 fi
410 ;;
411 :*) gamegroup=`echo "${with_gameuser}" | sed -e "s/://"` ;;
412 *) gameuser=${with_gameuser} ;;
413esac
399 414
400AC_ARG_WITH([gnustep-conf],dnl 415AC_ARG_WITH([gnustep-conf],dnl
401[AS_HELP_STRING([--with-gnustep-conf=FILENAME], 416[AS_HELP_STRING([--with-gnustep-conf=FILENAME],
@@ -4684,6 +4699,7 @@ AC_SUBST(etcdocdir)
4684AC_SUBST(bitmapdir) 4699AC_SUBST(bitmapdir)
4685AC_SUBST(gamedir) 4700AC_SUBST(gamedir)
4686AC_SUBST(gameuser) 4701AC_SUBST(gameuser)
4702AC_SUBST(gamegroup)
4687## FIXME? Nothing uses @LD_SWITCH_X_SITE@. 4703## FIXME? Nothing uses @LD_SWITCH_X_SITE@.
4688## src/Makefile.in did add LD_SWITCH_X_SITE (as a cpp define) to the 4704## src/Makefile.in did add LD_SWITCH_X_SITE (as a cpp define) to the
4689## end of LIBX_BASE, but nothing ever set it. 4705## end of LIBX_BASE, but nothing ever set it.
diff --git a/etc/NEWS b/etc/NEWS
index 548b54df0da..120d8b920c6 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -46,6 +46,13 @@ and silent rules are now quieter. To get the old behavior where
46build with 'make V=1'. 46build with 'make V=1'.
47 47
48--- 48---
49** The configure option '--with-gameuser' now allows to specify a
50group instead of a user if its argument is prefixed by ':' (a colon).
51This will cause the game score files in ${localstatedir}/games/emacs
52to be owned by that group, and the helper program for updating them to
53be installed setgid.
54
55---
49** The `grep-changelog' script (and its manual page) are no longer included. 56** The `grep-changelog' script (and its manual page) are no longer included.
50It has no particular connection to Emacs and has not changed in years, 57It has no particular connection to Emacs and has not changed in years,
51so if you want to use it, you can always take a copy from an older Emacs. 58so if you want to use it, you can always take a copy from an older Emacs.
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 @@
12015-01-21 Ulrich Müller <ulm@gentoo.org>
2
3 * update-game-score.c: Allow the program to run sgid instead
4 of suid, in order to match common practice for most games.
5 (main): Check if we are running sgid. Pass appropriate file
6 permission bits to 'write_scores'.
7 (write_scores): New 'mode' argument, instead of hardcoding 0644.
8 (get_prefix): Update error message.
9 * Makefile.in (gamegroup): New variable, set by configure.
10 ($(DESTDIR)${archlibdir}): Handle both suid or sgid when
11 installing the 'update-game-score' program.
12
12015-01-16 Eli Zaretskii <eliz@gnu.org> 132015-01-16 Eli Zaretskii <eliz@gnu.org>
2 14
3 * Makefile.in (AM_V_RC, am__v_RC_, am__v_RC_0, am__v_RC_1): New 15 * 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@
122 122
123gamedir=@gamedir@ 123gamedir=@gamedir@
124gameuser=@gameuser@ 124gameuser=@gameuser@
125gamegroup=@gamegroup@
125 126
126# ==================== Utility Programs for the Build ================= 127# ==================== Utility Programs for the Build =================
127 128
@@ -263,10 +264,17 @@ $(DESTDIR)${archlibdir}: all
263 umask 022; ${MKDIR_P} "$(DESTDIR)${gamedir}"; \ 264 umask 022; ${MKDIR_P} "$(DESTDIR)${gamedir}"; \
264 touch "$(DESTDIR)${gamedir}/snake-scores"; \ 265 touch "$(DESTDIR)${gamedir}/snake-scores"; \
265 touch "$(DESTDIR)${gamedir}/tetris-scores" 266 touch "$(DESTDIR)${gamedir}/tetris-scores"
266 -if chown ${gameuser} "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}" && chmod u+s "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}"; then \ 267ifneq ($(gameuser),)
267 chown ${gameuser} "$(DESTDIR)${gamedir}"; \ 268 chown ${gameuser} "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}"
268 chmod u=rwx,g=rwx,o=rx "$(DESTDIR)${gamedir}"; \ 269 chmod u+s,go-r "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}"
269 fi 270 chown ${gameuser} "$(DESTDIR)${gamedir}"
271 chmod u=rwx,g=rx,o=rx "$(DESTDIR)${gamedir}"
272else ifneq ($(gamegroup),)
273 chgrp ${gamegroup} "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}"
274 chmod g+s,o-r "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}"
275 chgrp ${gamegroup} "$(DESTDIR)${gamedir}"
276 chmod u=rwx,g=rwx,o=rx "$(DESTDIR)${gamedir}"
277endif
270 exp_archlibdir=`cd "$(DESTDIR)${archlibdir}" && /bin/pwd`; \ 278 exp_archlibdir=`cd "$(DESTDIR)${archlibdir}" && /bin/pwd`; \
271 if [ "$$exp_archlibdir" != "`cd ${srcdir} && /bin/pwd`" ]; then \ 279 if [ "$$exp_archlibdir" != "`cd ${srcdir} && /bin/pwd`" ]; then \
272 for file in ${SCRIPTS}; do \ 280 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/>. */
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");
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index d13bacfd965..7aa66bf9ad5 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,8 @@
12015-01-21 Ulrich Müller <ulm@gentoo.org>
2
3 * play/gamegrid.el (gamegrid-add-score-with-update-game-score):
4 Allow the 'update-game-score' helper program to run suid or sgid.
5
12015-01-21 Stefan Monnier <monnier@iro.umontreal.ca> 62015-01-21 Stefan Monnier <monnier@iro.umontreal.ca>
2 7
3 * emacs-lisp/eieio.el: Use cl-defmethod. 8 * emacs-lisp/eieio.el: Use cl-defmethod.
diff --git a/lisp/play/gamegrid.el b/lisp/play/gamegrid.el
index 1e265a635a0..b4c3c594731 100644
--- a/lisp/play/gamegrid.el
+++ b/lisp/play/gamegrid.el
@@ -486,13 +486,13 @@ FILE is created there."
486 (not (zerop (logand (file-modes 486 (not (zerop (logand (file-modes
487 (expand-file-name "update-game-score" 487 (expand-file-name "update-game-score"
488 exec-directory)) 488 exec-directory))
489 #o4000))))) 489 #o6000)))))
490 (cond ((file-name-absolute-p file) 490 (cond ((file-name-absolute-p file)
491 (gamegrid-add-score-insecure file score)) 491 (gamegrid-add-score-insecure file score))
492 ((and gamegrid-shared-game-dir 492 ((and gamegrid-shared-game-dir
493 (file-exists-p (expand-file-name file shared-game-score-directory))) 493 (file-exists-p (expand-file-name file shared-game-score-directory)))
494 ;; Use the setuid "update-game-score" program to update a 494 ;; Use the setuid (or setgid) "update-game-score" program
495 ;; system-wide score file. 495 ;; to update a system-wide score file.
496 (gamegrid-add-score-with-update-game-score-1 file 496 (gamegrid-add-score-with-update-game-score-1 file
497 (expand-file-name file shared-game-score-directory) score)) 497 (expand-file-name file shared-game-score-directory) score))
498 ;; Else: Add the score to a score file in the user's home 498 ;; Else: Add the score to a score file in the user's home