Op 04-05-11 14:53, Jon Dowland schreef:
On Wed, May 04, 2011 at 10:13:28AM +0200, Hans de Goede wrote:
- /usr/bin versus /usr/games
(I think) we've taken the opposite route and put them all in /usr/games. /usr/games is in the default $PATH on Debian.
Yes, but not for root. I think the main feature of using /usr/games is that it is possible to make it unaccessible for a group, thereby locking that group out of gaming. I know of people who have an account set up like that exactly because they don't want to play games while studying. (So for study, they log in as the non-game account, but for leisure, they log in as their "normal" account.
- /usr/share/<gamename> versus /usr/share/games/<gamename>
FHS: /usr/share/games Static data files for /usr/games (optional)
Again we seem to have gone the opposite route and followed the FHS.
AIUI both are following the FHS. It seems to make sense to use both /usr/games and /usr/share/games, or none of them. OTOH while I do like /usr/games, I quite dislike /usr/share/games, because I expect package data to be in /usr/(share|lib)/packagename/.
I agree with Sylvain that getting rid of special data dirs for games would be a Good Thing. However, I'm not so sure about $(bindir).
Having sgid binaries brings certain security issues with it, and as we all know most games have not been written really robust when it comes to dealing with unexpected input / error handling.
The attack vector you describe requires two bugs: one which allows you to take over a random game, and one in the highscore parsing code of the target game.
But I disagree that this would be a problem. Root doesn't run games (or at least (s)he shouldn't, which is why /usr/games is not in the root $PATH). So the security issue is that one normal user would be able to execute arbitrary code (in the worst case) as another normal user. The fact that this other user also is sgid games is irrelevant. The original bug which allowed the attacker to write the invalid high score data already provided sgid games access, so nothing new is lost.
Your solution (opening the high score file early and dropping rights) sounds nice (and solves a real problem), but not optimal. Best would be to let the game run without any special rights from the start. Instead of getting the file handle for the high score file from open(), it should get it from its parent process. The game should be started by a sgid games game starter, like this: game-start /usr/share/games/mygame/highscores /usr/games/mygame This program (game-start) would be sgid games, it opens the first argument, drops sgid rights, and execs into its second arguments (optionally with parameters). That way, we only need to secure start-game; the games binaries are just as safe as other games without special rights.
Actually, such an executable would also solve a problem I had with the pioneers meta-server. It runs as a daemon and wants to write into /var/run/. It must be setuid root for that. I don't like that at all. I would be much more comfortable with a separate start-daemon program which gives me a handle to the file in /var/run (start-stop-daemon doesn't seem to do that, unfortunately. Perhaps the best approach is to create a patch for it).
Thanks, Bas
On Wed, May 4, 2011 at 16:48, Bas Wijnen wijnen@debian.org wrote:
I know of people who have an account set up like that exactly because they don't want to play games while studying. (So for study, they log in as the non-game account, but for leisure, they log in as their "normal" account.
Seriously? I always wondered if there's anybody who is using this distinction.
Personally, I have always thought that separate directories are a bad idea. There is no /bin/X/ or /bin/networking , either. And for good reason.
One could argue that data dirs are special. With some games having huge data dirs and SSDs on the rise, this could make sense for some scenarios.
Overall, I prefer Fedora's approach. Maybe it's worth bouncing this off of debian-devel to get more input? _If_ this is changed, it should be changed globally, preferably at the same time for a lot of packages at once and become a release goal for next stable.
Richard
2011/5/4 Richard Hartmann richih.mailinglist@gmail.com:
On Wed, May 4, 2011 at 16:48, Bas Wijnen wijnen@debian.org wrote:
I know of people who have an account set up like that exactly because they don't want to play games while studying. (So for study, they log in as the non-game account, but for leisure, they log in as their "normal" account.
Seriously? I always wondered if there's anybody who is using this distinction.
Personally, I have always thought that separate directories are a bad idea. There is no /bin/X/ or /bin/networking , either. And for good reason.
I agree with you. Even though I can think of some scenarios that might benefit from the current directory separation, they are too exceptional to be considered as a serious reason.
One could argue that data dirs are special. With some games having huge data dirs and SSDs on the rise, this could make sense for some scenarios.
That might make sense if the distinction was between big data and small data. There are a lot of games with very small data dirs, and there are other packages -not games- with big data chunks. If that is the reason, it seems pretty arbitrary. I guess the reason might be more along the lines of thinking that games are second class citizens that are not as important as other packages, and thu the separation in directories makes it easier to handle their storage differently. As I say, I can only think of exceptional situations in which that could be useful, and I know of no one -I knew of no one until now- using that used that separation for anything.
Overall, I prefer Fedora's approach. Maybe it's worth bouncing this off of debian-devel to get more input? _If_ this is changed, it should be changed globally, preferably at the same time for a lot of packages at once and become a release goal for next stable.
If there are no serious reasons against it, I'd go for that too.
Greetings, Miry
On Wed, May 4, 2011 at 23:43, Miriam Ruiz miriam@debian.org wrote:
That might make sense if the distinction was between big data and small data.
Good point. I seem to remember Ganneff talking about creating special repositories for large data sets (mainly games and scientific data) a few years ago, but this went nowhere.
Unless Debian as a whole decides to act on this, it's prolly not worth pursuing a split.
Richard
Hi all,
On 05/04/2011 04:48 PM, Bas Wijnen wrote:
Op 04-05-11 14:53, Jon Dowland schreef:
<snip>
Having sgid binaries brings certain security issues with it, and as we all know most games have not been written really robust when it comes to dealing with unexpected input / error handling.
The attack vector you describe requires two bugs: one which allows you to take over a random game, and one in the highscore parsing code of the target game.
Correct.
But I disagree that this would be a problem. Root doesn't run games (or at least (s)he shouldn't, which is why /usr/games is not in the root $PATH). So the security issue is that one normal user would be able to execute arbitrary code (in the worst case) as another normal user.
Agreed, which is still an issue.
fact that this other user also is sgid games is irrelevant. The original bug which allowed the attacker to write the invalid high score data already provided sgid games access, so nothing new is lost.
The separation between users is lost, one user can now get access to another users files, like say private ssh / gpg keys...
Your solution (opening the high score file early and dropping rights) sounds nice (and solves a real problem), but not optimal. Best would be to let the game run without any special rights from the start. Instead of getting the file handle for the high score file from open(), it should get it from its parent process. The game should be started by a sgid games game starter, like this: game-start /usr/share/games/mygame/highscores /usr/games/mygame This program (game-start) would be sgid games, it opens the first argument, drops sgid rights, and execs into its second arguments (optionally with parameters). That way, we only need to secure start-game; the games binaries are just as safe as other games without special rights.
An interesting approach, but likely more work then my solution, for both our solutions the game needs to be reworked to keep the file open until it exits, rather then open/close it each read/write. Once that is done, adding one fopen and a dropping of right at the top of main, is quite easy, and approx. the same amount of code as inheriting an fd from a parent. This approach is just as safe as yours, once the rights have been unrevokably dropped, nothing bad can be done any more other then what can be done through the fd. If there are bugs somewhere in the kernel / libc which still allow some exploit, there are much bigger suid / sgid targets then some game.
So I think the safety of the 2 approaches is about equal, where mine approach does not require an external helper, modified desktop files/ launch scripts, etc. Not to mention Fedora already has patches for my solution for quite a large number of games.
Regards,
Hans
On Thu, May 5, 2011 at 10:32, Hans de Goede hdegoede@redhat.com wrote:
This approach is just as safe as yours, once the rights have been unrevokably dropped, nothing bad can be done any more other then what can be done through the fd.
Not quite true as with Bas' approach there is exactly one binary that needs to be secured whereas with your approach every single game binary needs to be patched and audited. While I am not agreeing with the people who created a setuid-free Linux distro, it's still good practice to limit the number of binaries that are setuid.
Richard
Hi,
On 05/05/2011 10:46 AM, Richard Hartmann wrote:
On Thu, May 5, 2011 at 10:32, Hans de Goedehdegoede@redhat.com wrote:
This approach is just as safe as yours, once the rights have been unrevokably dropped, nothing bad can be done any more other then what can be done through the fd.
Not quite true as with Bas' approach there is exactly one binary that needs to be secured whereas with your approach every single game binary needs to be patched and audited.
With Bas' approach every game binary (or rather the sources it is build from) still needs to be patches to use the passed in fd, rather then trying to open the highscore file itself.
As for auditing: 1) The highscore parsing code should still be audited in either case, since someone subverting the game will still be able to write malicious content to it in either case
2) The rest of the code will be a simple standardizes snippet directly at the start of main, and once control is passed this snippet all elevated rights are permanently gone, see here for the snippet Fedora is using: http://fedoraproject.org/wiki/SIGs/Games/Packaging
Regards,
Hans
On Thu, May 5, 2011 at 10:58, Hans de Goede hdegoede@redhat.com wrote:
With Bas' approach every game binary (or rather the sources it is build from) still needs to be patches to use the passed in fd, rather then trying to open the highscore file itself.
Correct. This is inevitable unless upstreams adopt either patch.
As for auditing:
- The highscore parsing code should still be audited in either case, since
someone subverting the game will still be able to write malicious content to it in either case
Correct, but that still means fewer places to audit.
- The rest of the code will be a simple standardizes snippet directly at
the start of main, and once control is passed this snippet all elevated rights are permanently gone, see here for the snippet Fedora is using: http://fedoraproject.org/wiki/SIGs/Games/Packaging
The other approach would also result in one single snippet (unless I am forgetting something)?
Richard
Hi,
On 05/05/2011 11:04 AM, Richard Hartmann wrote:
On Thu, May 5, 2011 at 10:58, Hans de Goedehdegoede@redhat.com wrote:
With Bas' approach every game binary (or rather the sources it is build from) still needs to be patches to use the passed in fd, rather then trying to open the highscore file itself.
Correct. This is inevitable unless upstreams adopt either patch.
As for auditing:
- The highscore parsing code should still be audited in either case, since someone subverting the game will still be able to write malicious content to it in either case
Correct, but that still means fewer places to audit.
- The rest of the code will be a simple standardizes snippet directly at the start of main, and once control is passed this snippet all elevated rights are permanently gone, see here for the snippet Fedora is using: http://fedoraproject.org/wiki/SIGs/Games/Packaging
The other approach would also result in one single snippet (unless I am forgetting something)?
Right, so from a security pov and needed patching pov both approaches are equal, except that having a special right helper also requires: -adding launcher scripts / modifying .desktop files -writing such a helper
More importantly, Fedora has already been using the approach I advocate for a few years, and has patches for many games for this already and has been feeding these upstream where possible.
So on one hand we have this approach which looks good on paper, and on the other hand we've this approach which looks equally good on paper, and which is actually implemented already for a lot of games. Which to me makes it really easy to decided which approach to choose.
Regards,
Hans
On Fri, May 6, 2011 at 09:02, Hans de Goede hdegoede@redhat.com wrote:
So on one hand we have this approach which looks good on paper, and on the other hand we've this approach which looks equally good on paper, and which is actually implemented already for a lot of games. Which to me makes it really easy to decided which approach to choose.
I still disagree about the relative security, but code wins, we agree on that :)
Richard
Hi,
Op 06-05-11 09:02, Hans de Goede schreef:
On 05/05/2011 11:04 AM, Richard Hartmann wrote:
On Thu, May 5, 2011 at 10:58, Hans de Goedehdegoede@redhat.com wrote:
With Bas' approach every game binary (or rather the sources it is build from) still needs to be patches to use the passed in fd, rather then trying to open the highscore file itself.
Correct. This is inevitable unless upstreams adopt either patch.
Plus, both approaches are almost identical when it comes to this patch. The only difference for the upstream code is what happens at the start. However, that is a significant difference IMO:
- Your code is 14 lines (excluding comments) of non-trivial (IMO) code. What you would need for my solution is 2 lines, and it is trivial:
/* At global level. */ FILE *scoreboard_filehandle;
/* In main. */ /* The scoreboard file is opened by game-helper as fd #3. */ scoreboard_filehandle = fdopen (3, "r+");
This means that the executable must be started from the helper, unless it allows an invalid file handle. For this, the helper package could provide a script to which the games packages can put a link in /usr/bin:
#!/bin/sh game="`basename "$0"`" game-helper /usr/share/$game/highscores /usr/share/$game/$game
game-helper must then of course check that everything is right (the highscore file exists and is group-writable and the executable exists.
- The rest of the code will be a simple standardizes snippet
directly at the start of main, and once control is passed this snippet all elevated rights are permanently gone, see here for the snippet Fedora is using: http://fedoraproject.org/wiki/SIGs/Games/Packaging
The other approach would also result in one single snippet (unless I am forgetting something)?
Right, so from a security pov and needed patching pov both approaches are equal, except that having a special right helper also requires: -adding launcher scripts / modifying .desktop files -writing such a helper
Actually, with the launcher script above included in game-helper, .desktop files don't need to be modified, and adding the script comes down to adding a symlink.
Your approach requires: - sgid rights on every game with highscores, making it harder to see which executables require extra auditing attention. - a significant amount of identical code at the start of each game, which must all be changed if something is wrong, or something extra is desired. It really comes down to including a tiny static library in the source, and has all the problems that come with it.
One such extra feature I'm thinking of right now, is to implement a standard highscore file format which games can use. Then game-helper can check if the file is in that format (by reading the header), and if so, it can check that there is no nonsense in it. That way, it will become harder to attack a game by writing malicious code into the highscore file.
This just illustrates that my approach is similar to using an external shared library, with all the benefits that come with it. Of course, when adding such extra features to game-helper, it should do: - Open highscore file - Drop priviledges - Do extra stuff - Start game
More importantly, Fedora has already been using the approach I advocate for a few years, and has patches for many games for this already and has been feeding these upstream where possible.
That's really good!
So on one hand we have this approach which looks good on paper, and on the other hand we've this approach which looks equally good on paper,
Not equally good, IMO.
and which is actually implemented already for a lot of games.
Which means that the bulk of the work for the other approach is already done as well.
I'm happy to write the game-helper. The rest that would be required is: - Replace your code snippet with my single line. - Change the packaging to put the executable in /usr/lib(/games)?/foo/foo and highscores in /usr/share(/games)?/foo/highscores - Let the package make a link to /usr/(bin|games)/game-helper from /usr/(bin|games)/foo and depend on game-helper.
I agree that this is some work, especially with the packaging. Per game it's not much, though, and I do think it's worth it.
Which to me makes it really easy to decided which approach to choose.
To me, the downsides of your approach are significant. Of course, they are even more present in the game without any of these patches. So for two reasons I'm very happy with the work you've done on this so far: - It makes things better - Most of the work you did is usable for what is IMO the best approach, so your work is not lost if we go there.
Thanks, Bas
Just replying to my own post with a new idea I got from myself. :-)
Your approach ... really comes down to including a tiny static library in the source, and has all the problems that come with it.
...
[M]y approach is similar to using an external shared library, with all the benefits that come with it.
We can also use a real shared library[1]. This has several benefits and one major drawback:
Benefits: - No special code is required at the start of the game. - Other functionality is easier to add, such as using a highscore server (locally or on the net). - Highscore parsing code is taken out of the game to a central place, which allows us to really close the security hole of badly written games (as far as high score files are concerned).
Drawback: - The current code that has already been written by the Fedora people is not usable, and must be replaced by calls into the library. In fact, this may mean significant rewriting work for each game.
The benefits are nice, but the drawback is huge. I would like to agree the following about games with a central highscore file: - New games and games for which this is initially implemented should be written to use the shared library. - Games which already use their own system should be patched using the method Fedory uses. - It is considered an improvement, but not a priority, to patch games to use the shared library instead of their own handling, and thus to move from the sgid-safe patch to the shared library patch.
I've updated the wiki page on freedesktop.org about upstream to talk about this: http://www.freedesktop.org/wiki/Games/Upstream Please feel free to change it.
The library interface I am proposing there is: * Get the current list of highscores. * Register a callback to be notified of changes to a list of highscores. * Unregister the callback. * Free the list. * Send a new score, which is potentially a highscore. Returns: position in the high score list.
Thanks, Bas
[1] This shared library will need to talk to a setgid games program to open the actual highscore file. This is an implementation detail.
Hi,
On 05/06/2011 02:03 PM, Bas Wijnen wrote:
Just replying to my own post with a new idea I got from myself. :-)
Your approach ... really comes down to including a tiny static library in the source, and has all the problems that come with it.
...
[M]y approach is similar to using an external shared library, with all the benefits that come with it.
We can also use a real shared library[1]. This has several benefits and one major drawback:
Benefits:
- No special code is required at the start of the game.
- Other functionality is easier to add, such as using a highscore server
(locally or on the net).
- Highscore parsing code is taken out of the game to a central place,
which allows us to really close the security hole of badly written games (as far as high score files are concerned).
Drawback:
- The current code that has already been written by the Fedora people is
not usable, and must be replaced by calls into the library. In fact, this may mean significant rewriting work for each game.
The benefits are nice, but the drawback is huge. I would like to agree the following about games with a central highscore file:
- New games and games for which this is initially implemented should be
written to use the shared library.
- Games which already use their own system should be patched using the
method Fedory uses.
- It is considered an improvement, but not a priority, to patch games to
use the shared library instead of their own handling, and thus to move from the sgid-safe patch to the shared library patch.
I like +1
I've updated the wiki page on freedesktop.org about upstream to talk about this: http://www.freedesktop.org/wiki/Games/Upstream Please feel free to change it.
Ooh you've actually started a wiki page +1 for that too :)
The library interface I am proposing there is:
- Get the current list of highscores.
- Register a callback to be notified of changes to a list of highscores.
- Unregister the callback.
- Free the list.
- Send a new score, which is potentially a highscore. Returns: position
in the high score list.
Did you check if we're not re-inventing the wheel here? IOW if there not already is some generic highscore sharing server + client-lib somewhere already ?
Regards,
Hans
On Fri, May 6, 2011 at 15:42, Hans de Goede hdegoede@redhat.com wrote:
Did you check if we're not re-inventing the wheel here? IOW if there not already is some generic highscore sharing server + client-lib somewhere already ?
"server" as in "daemon"? That would be overkill, imo.
Richard
Hi,
On 05/06/2011 03:43 PM, Richard Hartmann wrote:
On Fri, May 6, 2011 at 15:42, Hans de Goedehdegoede@redhat.com wrote:
Did you check if we're not re-inventing the wheel here? IOW if there not already is some generic highscore sharing server + client-lib somewhere already ?
"server" as in "daemon"? That would be overkill, imo.
Not for the internet case it wouldn't and if such a thing already exists it would be a good starting place, and we can extend it to support local shared files with a sgid helper.
Regards,
Hans
Hi,
Op 06-05-11 15:42, Hans de Goede schreef:
Did you check if we're not re-inventing the wheel here? IOW if there not already is some generic highscore sharing server + client-lib somewhere already ?
I didn't check. I'm usually reinventing the wheel. :-) That, and I thought someone here would already know about it and yell if something like this existed. :-)
A quick scan using google didn't give me any generic results, only some for specific games.
Thanks, Bas
On Sat, May 7, 2011 at 2:50 AM, Bas Wijnen wijnen@debian.org wrote:
I didn't check. I'm usually reinventing the wheel. :-) That, and I thought someone here would already know about it and yell if something like this existed. :-)
There is the GNU Gaming Zone stuff.
AFAICT most games reinvent the wheel when it comes to storing high-scores on a central server. One game (Primrose) that does this even uploads the game history when saving your highscore, so that others can watch how you got that high score.