containers / fuse-overlayfs

FUSE implementation for overlayfs
GNU General Public License v2.0
535 stars 85 forks source link

"Operation not permitted" when trying to open file for write #428

Open stsp opened 3 months ago

stsp commented 3 months ago

This may be related to #232 but I prepared a ready-to-use test-case, it is attached: fuse_test.AppImage.gz

After you gunzip it, you'll get the AppImage file called fuse_test.AppImage. All it does is mounts the read-only lower dir and the writable upper dir into the mount-point. Then it does test -r and test -w to check if the file is actually readable and writable. Unfortunately its not writable, in which case it prints the failure message and also prints mount | grep fuse that allows you to inspect the mount params. In fact, its not like the entire dir is not writable - it IS writable. You can create new files there. But the files that come from the lower dir, are themselves not writable for some unclear reason.

I also added the --debug option for you. With that option fuse-overlayfs is started with -d and you can see the logging. I also added the --keep option which just mounts the dirs, prints the mount point and exits without doing any checks and without unmounting. This may be needed if you want to work with the mount-point by hands.

I hope this test-case will help to narrow down the problem.

stsp commented 3 months ago

ovl_tst.tar.gz Here's the completely trivial test-case that doesn't even involve AppImage. Just a trivial script. It mounts the archive with archivemount and then adds a writable overlay. The very interesting thing is that the bug can be reproduced only with SOME archives. The one that is attached, triggers the bug. But if I try to create the similar archive by hands, then bug doesn't trigger... So the problem is probably much deeper than the one could expect.

stsp commented 3 months ago

Found the problem: fuse-overlayfs doesn't make the files writable if in the lowerdir they belong to another user.

stsp commented 3 months ago

In fact, the ownership is propagated from lowerdir to the mountpoint. Maybe fuse-overlayfs should set the ownership to the mount owner, and ignore the ownership in the lowerdir?

probonopd commented 3 months ago

I think what should be done is to do copy-on-write under the user running fuse-overlayfs while not caring about the user of the file in the lowerdir?

stsp commented 3 months ago

I think what should be done is to do copy-on-write under the user running fuse-overlayfs while not caring about the user of the file in the lowerdir?

I bet the write request doesn't even come to fuse-overlayfs in that case. Kernel's FUSE module has paranoid permission checks, and likely denies the request if the file has another owner. I think the only work-around is for fuse-overlayfs to change the owner explicitly.

stsp commented 3 months ago

Got things working with this hack:

diff --git a/main.c b/main.c
index b5753db..58836c8 100644
--- a/main.c
+++ b/main.c
@@ -971,8 +971,8 @@ rpl_stat (fuse_req_t req, struct ovl_node *node, int fd, con
st char *path, struc
   if (ret < 0)
     return ret;

-  st->st_uid = find_mapping (st->st_uid, data, true, true);
-  st->st_gid = find_mapping (st->st_gid, data, true, false);
+  st->st_uid = find_mapping (getuid(), data, true, true);
+  st->st_gid = find_mapping (getgid(), data, true, false);

   st->st_ino = node->tmp_ino;
   st->st_dev = node->tmp_dev;
@@ -3186,12 +3186,14 @@ copyup (struct ovl_data *lo, struct ovl_node *node)
   if (dfd < 0)
     goto exit;

+#if 0
   if (st.st_uid != lo->uid || st.st_gid != lo->gid || get_upper_layer (lo)->stat_override_mode != STAT_OVERRIDE_NONE)
     {
       ret = do_fchown (lo, dfd, st.st_uid, st.st_gid, mode);
       if (ret < 0)
         goto exit;
     }
+#endif

   buf = malloc (buf_size);
   if (buf == NULL)
probonopd commented 3 months ago

Would you be able to send a pull request?

stsp commented 3 months ago

This patch is definitely wrong, it can't be sent as a PR. I'll simply add the hacked-up fuse-overlayfs to my AppImage, and things are good.

stsp commented 3 months ago

Its not like I don't care about an upstream version, but fuse-overlayfs has quite a lot of uid mapping and overriding modes which I am not aware about. Maybe enabling some override mode already achieves the same thing, I've no idea. So I'll just take a short-cut and package the hacked-up version.

probonopd commented 3 months ago

It would be good if this could be fixed properly by the maintainer of this repo, so that it would be fixed for everyone. Thanks!