tkashkin / GameHub

All your games in one place
https://tkashkin.github.io/projects/gamehub
GNU General Public License v3.0
2.23k stars 128 forks source link

Filesystem overlays (for DLCs and mods) #120

Open tkashkin opened 5 years ago

tkashkin commented 5 years ago

Extracted into separate issue from https://github.com/tkashkin/GameHub/issues/118#issuecomment-435532905:

I have one interesting idea for DLCs, patches and mods management:

Base game, patches, DLCs and mods are installed in separate directories (let's call them "overlays"). Each overlay except base game can be disabled. All enabled overlays are layered on top of each other.

That should be useful and make installed DLC tracking easy while allowing to disable and remove them at any time.

I have implemented similar thing before on Windows using symlinks. For Linux it should be even easier with OverlayFS.

tkashkin commented 5 years ago

@neuromancer any suggestions?

tkashkin commented 5 years ago

It actually works!

image

image

image

tkashkin commented 5 years ago

Implemented in 2071a8e. May be (and probably is) extremely buggy. Needs testing.

neuromancer commented 5 years ago

@neuromancer any suggestions?

Are most of the DLCs supported using this overlay approach? they don't require any installation? (I don't have experience with DLCs, so that's why I'm asking :confused: ). Maybe we should investigate how Steam handle them.

tkashkin commented 5 years ago

@neuromancer I think Steam (and probably GOG Galaxy) will just check hashes of existing files and download files that don't match if game/DLC is installed/removed/updated.

GOG DLCs are packed in installer and should be installed in game folder. Installer can probably check some game files to know if game is installed and can replace some game files.

Overlays are based on OverlayFS. Game overlay will be mounted as lowerdir and DLC overlay will be mounted as upperdir. Any changes made by DLC installer will be saved to DLC overlay.

hogarthj commented 5 years ago

Hmm something is up with the policykit stuff on Fedora ... it's prompting for permission for the mount/umount when going by config I don't think it should be ... I'll try and dig into it more.

hogarthj commented 5 years ago

Got an answer ... the policy is annotating /bin/mount and /bin/umount but in Fedora /bin is a symlink to /usr/bin but polkit then doesn't match the annotation correctly.

I could patch the policy actions xml in the Fedora spec ... but it'd be cleaner to handle this directly in the project code somehow

tkashkin commented 5 years ago

@hogarthj is it possible to use multiple <annotate key="org.freedesktop.policykit.exec.path"> in the same action?

hogarthj commented 5 years ago

A quick test doesn't look like it ... I think it is the last entry of it that "wins" ...

So either in the build process /bin as a symlink should be detected and use /usr/bin as the base instead ... or perhaps some build variable to declare the path would do ...

or as a worst case, I'll do a small patch or just sed it as part of the RPM build

tkashkin commented 5 years ago

@hogarthj a few ideas:

hogarthj commented 5 years ago

I really dislike that last one as it feels very much like a security hole, allows privileged execution of env with gamehub installed ...

You could do a custom script and pkexec on that ... that might actually be the nicest way forward, if you don't want to do a build time configuration of the policy xml.

tkashkin commented 5 years ago

Does it mean that any process can pkexec anything from any installed policy? If so, current (u)mount can also be considered a security hole.

Do you think that helper script that only allow (u)mount will be more secure?

tkashkin commented 5 years ago

Also does that seem a bit too permissive? (I didn't work with polkit before)

<defaults>
    <allow_any>yes</allow_any>
    <allow_inactive>yes</allow_inactive>
    <allow_active>yes</allow_active>
</defaults>
hogarthj commented 5 years ago

This article I wrote a few years back might help you: https://www.hogarthuk.com/?q=node/10

And yes, the shipped policy right now allows anything on the system to execute mount via pkexec without any checks.

A helper script that can validate the path is gamehub related etc etc would be way more secure.

tkashkin commented 5 years ago

@hogarthj how does 09c458a look?

Lucki commented 5 years ago

I've tried this feature and can reliably get a segmentation fault with this. To test this I've installed Zeus + Poseidon (Acropolis) from gog with innoextract. Activated the overlays and copied the widescreen patch files into the created overlay folder. Try to start the game with proton, which doesn't start (don't know why). Now as soon as I do a right click on the games list item to access the overlay menu I get a segmentation fault. Even after a restart of gamehub. This doesn't happen with wine chosen instead of proton. --debug does not give any additional output before the crash.

Changing between wine and proton gets gamehub completely confused. It's using the wrong prefix and the game files are in the main folder again.

tkashkin commented 5 years ago

@Lucki try to run it with --gdb --log-workers --verbose.

Lucki commented 5 years ago

First segfault after installing the game and starting with proton, right click on game entry -> crash: https://gist.github.com/Lucki/7814d2c4cfaa698cbab350d6935a4cd7

Second run, right click on game entry -> crash: https://gist.github.com/Lucki/6fddf05f6b79feb81862ae0d74c0434e

Edit: Just verified that the game runs without overlays with proton. Segfault only happens with overlays and proton (game doesn't run). Complete log from installation to crash: https://gist.github.com/Lucki/6df6d60c8a46cd276589126bb201d36c

tkashkin commented 5 years ago

@Lucki it seems to be fixed in 678b18e.

Lucki commented 5 years ago

Yes, the crash is fixed.

But when I disable the mod so that only the base is active the game gets unlisted from the installed section because the merged directory is empty and the executable is no longer present. Both overlays are still in the folders, but I'm unable to do anything with them in gamehub because it's marked as uninstalled.

tkashkin commented 5 years ago

But when I disable the mod so that only the base is active the game gets unlisted from the installed section because the merged directory is empty and the executable is no longer present. Both overlays are still in the folders, but I'm unable to do anything with them in gamehub because it's marked as uninstalled.

It can happen sometimes. Overlay will be (re)mounted when you open game's details. Select any other game then select this game again and it should work.

Lucki commented 5 years ago

Doesn't get remounted on change. Instead I get mount: /mnt/gamehub/gamehub/gog/Zeus__Poseidon_Acropolis/_gamehub/_overlay/merged: mount(2) system call failed: Stale file handle. Same message on every gamehub restart until I delete the folders.

tkashkin commented 5 years ago

@Lucki

Are any overlays mounted? (See with mount | grep gamehub_overlay). If there are, umount them manually and try again.

If it doesn't help, try solutions from https://unix.stackexchange.com/questions/433051.

Or just reboot and it should be fixed.

Lucki commented 5 years ago

There's nothing mounted by gamehub (your command returns nothing). Will report back after a reboot. (probably tomorrow)

tkashkin commented 5 years ago

@Lucki

I don't think that it can be fixed in app and I have no idea what exactly causes this. It can be related to many factors (kernel, distro, mounted filesystems, FS you store games on, etc.).

If it's related to kernel caches, this may fix it (from https://unix.stackexchange.com/questions/433051):

# To free pagecache
echo 1 > /proc/sys/vm/drop_caches
# To free dentries and inodes
echo 2 > /proc/sys/vm/drop_caches
# To free pagecache, dentries and inodes
echo 3 > /proc/sys/vm/drop_caches
Lucki commented 5 years ago

I'm not sure. Even after a reboot I get that stale file handle.

Maybe it's my setup but I can't use this feature in a convenient way.

tkashkin commented 5 years ago

@Lucki

I don't think anything can be done if mount -t overlay doesn't work on your system.

Try this to see if it works at all:

mkdir overlay_test && cd overlay_test
mkdir -p base/test overlay/test2 workdir merged
touch base/test/base && touch overlay/overlay

sudo mount -t overlay testoverlay -o lowerdir=`pwd`/base,upperdir=`pwd`/overlay,workdir=`pwd`/workdir `pwd`/merged
Lucki commented 5 years ago

Yes, that works.

$ tree /mnt/gamehub/gamehub/overlay_test 
/mnt/gamehub/gamehub/overlay_test
├── base
│   └── test
│       └── base
├── merged
│   ├── overlay
│   ├── test
│   │   └── base
│   └── test2
├── overlay
│   ├── overlay
│   └── test2
└── workdir
    ├── index [error opening dir]
    └── work [error opening dir]

10 directories, 4 files
tkashkin commented 5 years ago

That's weird. Does it work if you try to do the same thing in game's directory?

Lucki commented 5 years ago

The same thing I've done above also works inside the game folder. Even unmounting and remounting. But when I've manually unmount the overlays created by gamehub and try to remount them I get the same stale file error message gamehub complains about.

tkashkin commented 5 years ago

Is there anything useful in dmesg when overlay is mounted?

Lucki commented 5 years ago

I'm not sure what I did at which time but these are recent error messages related to overlayfs:

[Feb14 16:11] overlayfs: failed to verify upper (overlays/test, ino=26083332, err=-116)
[  +0,000001] overlayfs: failed to verify index dir 'upper' xattr
[  +0,000003] overlayfs: try deleting index dir or mounting with '-o index=off' to disable inodes index.
[Feb14 16:26] overlayfs: failed to verify origin (overlays/base, ino=25954348, err=-116)
[  +0,000001] overlayfs: failed to verify upper root origin
[Feb14 16:30] overlayfs: failed to verify upper (overlays/test, ino=25954350, err=-116)
[  +0,000002] overlayfs: failed to verify index dir 'upper' xattr
[  +0,000002] overlayfs: try deleting index dir or mounting with '-o index=off' to disable inodes index.

After deleting the index folder as suggested I can manually mount the overlay again. Also gamehub can remount changed overlays after I delete the index folder manually.

Edit: The folders inside the workdir are owned by root instead of my user, maybe that's causing the problems. Also they seem to be not cleared up if being mounted by gamehub.

Lucki commented 5 years ago

While playing around with overlays I'm missing a way to remove/delete and maybe rename the different overlays.

tkashkin commented 5 years ago

@Lucki there's currently no way to remove/rename existing overlays.

You can remove/rename overlay folder manually and edit overlays.json.

Lucki commented 5 years ago

Yea, maybe it's worth to add something to the userinterface for that.

tkashkin commented 5 years ago

Overlays can now be removed. When base is removed all files are moved back to the install_dir.