aboutsummaryrefslogtreecommitdiff
blob: 1c0f43c219f796dcffc98d556c2a1197eebb13c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
Backport support for update-game-score to run sgid instead of suid.
This comprises parts of the following commits from upstream git:

commit 74ab488ff2e57f31eb5290266f0f3b1995ebf83e
Author: Paul Eggert <eggert@cs.ucla.edu>
Date:   Thu Jan 22 00:39:30 2015 -0800

    Check exit statuses in lib-src/Makefile

commit 7f4e7dd378c456b498c270b47b46aaae365a72ab
Author: Ulrich Müller <ulm@gentoo.org>
Date:   Thu Jan 22 08:24:42 2015 +0100

    Don't fail if chown or chgrp for 'update-game-score' is unsuccessful.

commit 20f66485526b69eb26f2e70bd835a5e1333559d5
Author: Ulrich Müller <ulm@gentoo.org>
Date:   Fri Jan 16 09:25:25 2015 +0100

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

--- emacs-24.4-orig/configure.ac
+++ emacs-24.4/configure.ac
@@ -313,10 +313,25 @@
 fi
 
 AC_ARG_WITH(gameuser,dnl
-[AS_HELP_STRING([--with-gameuser=USER],[user for shared game score files])])
-test "X${with_gameuser}" != X && test "${with_gameuser}" != yes \
-  && gameuser="${with_gameuser}"
-test "X$gameuser" = X && gameuser=games
+[AS_HELP_STRING([--with-gameuser=USER_OR_GROUP],
+		[user for shared game score files.
+		An argument prefixed by ':' specifies a group instead.])])
+gameuser=
+gamegroup=
+case ${with_gameuser} in
+  no) ;;
+  "" | yes)
+    AC_MSG_CHECKING([whether a 'games' user exists])
+    if id -u games >/dev/null 2>&1; then
+      AC_MSG_RESULT([yes])
+      gameuser=games
+    else
+      AC_MSG_RESULT([no])
+    fi
+    ;;
+  :*) gamegroup=`echo "${with_gameuser}" | sed -e "s/://"` ;;
+  *) gameuser=${with_gameuser} ;;
+esac
 
 AC_ARG_WITH([gnustep-conf],dnl
 [AS_HELP_STRING([--with-gnustep-conf=FILENAME],
@@ -4658,6 +4673,7 @@
 AC_SUBST(bitmapdir)
 AC_SUBST(gamedir)
 AC_SUBST(gameuser)
+AC_SUBST(gamegroup)
 ## FIXME? Nothing uses @LD_SWITCH_X_SITE@.
 ## src/Makefile.in did add LD_SWITCH_X_SITE (as a cpp define) to the
 ## end of LIBX_BASE, but nothing ever set it.
--- emacs-24.4-orig/lib-src/Makefile.in
+++ emacs-24.4/lib-src/Makefile.in
@@ -101,6 +101,7 @@
 
 gamedir=@gamedir@
 gameuser=@gameuser@
+gamegroup=@gamegroup@
 
 # ==================== Utility Programs for the Build =================
 
@@ -243,10 +244,25 @@
 	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}"; \
+ifneq ($(gameuser),)
+	if chown ${gameuser} \
+	     "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}" && \
+	   chmod u+s,go-r \
+	     "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}"; \
+	then \
+	  chown ${gameuser} "$(DESTDIR)${gamedir}" && \
+	  chmod u=rwx,g=rx,o=rx "$(DESTDIR)${gamedir}"; \
+	fi
+else ifneq ($(gamegroup),)
+	if chgrp ${gamegroup} \
+	     "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}" && \
+	   chmod g+s,o-r \
+	     "$(DESTDIR)${archlibdir}/update-game-score${EXEEXT}"; \
+	then \
+	  chgrp ${gamegroup} "$(DESTDIR)${gamedir}" && \
 	  chmod u=rwx,g=rwx,o=rx "$(DESTDIR)${gamedir}"; \
 	fi
+endif
 	exp_archlibdir=`cd "$(DESTDIR)${archlibdir}" && /bin/pwd`; \
 	if [ "$$exp_archlibdir" != "`cd ${srcdir} && /bin/pwd`" ]; then \
 	  for file in ${SCRIPTS}; do \
--- emacs-24.4-orig/lib-src/update-game-score.c
+++ emacs-24.4/lib-src/update-game-score.c
@@ -21,8 +21,8 @@
 
 
 /* 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
@@ -89,7 +89,7 @@
 		       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 @@
 }
 
 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;
 }
 
@@ -141,7 +142,7 @@
 main (int argc, char **argv)
 {
   int c;
-  bool running_suid;
+  bool running_suid, running_sgid;
   void *lockstate;
   char *scorefile;
   char *nl;
@@ -183,8 +184,11 @@
     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)
@@ -234,7 +238,8 @@
 	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");
@@ -429,8 +434,8 @@
 }
 
 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;
@@ -444,7 +449,7 @@
   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");
@@ -460,7 +465,7 @@
   if (rename (tempfile, filename) != 0)
     return -1;
 #ifdef DOS_NT
-  if (chmod (filename, 0644) < 0)
+  if (chmod (filename, mode) < 0)
     return -1;
 #endif
   return 0;
--- emacs-24.4-orig/lisp/play/gamegrid.el
+++ emacs-24.4/lisp/play/gamegrid.el
@@ -486,13 +486,13 @@
 	 (not (zerop (logand (file-modes
 			      (expand-file-name "update-game-score"
 						exec-directory))
-			     #o4000)))))
+			     #o6000)))))
     (cond ((file-name-absolute-p file)
 	   (gamegrid-add-score-insecure file score))
 	  ((and gamegrid-shared-game-dir
 		(file-exists-p (expand-file-name file shared-game-score-directory)))
-	   ;; Use the setuid "update-game-score" program to update a
-	   ;; system-wide score file.
+	   ;; Use the setuid (or setgid) "update-game-score" program
+	   ;; to update a system-wide score file.
 	   (gamegrid-add-score-with-update-game-score-1 file
 	    (expand-file-name file shared-game-score-directory) score))
 	  ;; Else: Add the score to a score file in the user's home