Skip to content

Avoid unlink/rename when replacing regular files on Android - #245

Merged
chenxiaolong merged 1 commit into
masterfrom
android-sep-2026
Sep 16, 2026
Merged

chenxiaolong merged 1 commit into
masterfrom
android-sep-2026

Conversation

@chenxiaolong

@chenxiaolong chenxiaolong commented Sep 16, 2026

Copy link
Copy Markdown
Owner

Android's September 2026 security patches [0] changed the MediaProvider behavior so that it revokes app permissions on unlink and rename within its FUSE filesystem, which is used for both internal storage (/sdcard) and external storage (SD cards and USB drives). For rename, permissions for both paths are revoked as it does: revoke destination -> rename -> revoke source.

Unfortunately, this means it is now impossible to keep app permissions to files in a shared folder while performing atomic file replacement.

This commit works around the problem by performing in-place overwrites when replacing regular files. This essentially forces the use of the fallback path of osutil.RenameOrCopy() when the destination is on a FUSE filesystem on Android. The statfs magic check is sufficient since the only FUSE filesystem openable by path on Android is MediaProvider's.

[0] https://android.googlesource.com/platform/packages/providers/MediaProvider/+/91dddac65b6ef48ae54302fa852029c2fcf010aa

@chenxiaolong chenxiaolong self-assigned this Sep 16, 2026
Android's September 2026 security patches [0] changed the MediaProvider
behavior so that it revokes app permissions on unlink and rename within
its FUSE filesystem, which is used for both internal storage (/sdcard)
and external storage (SD cards and USB drives). For rename, permissions
for both paths are revoked as it does: revoke destination -> rename ->
revoke source.

Unfortunately, this means it is now impossible to keep app permissions
to files in a shared folder while performing atomic file replacement.

This commit works around the problem by performing in-place overwrites
when replacing regular files. This essentially forces the use of the
fallback path of osutil.RenameOrCopy() when the destination is on a
FUSE filesystem on Android. The statfs magic check is sufficient since
the only FUSE filesystem openable by path on Android is MediaProvider's.

[0] https://android.googlesource.com/platform/packages/providers/MediaProvider/+/91dddac65b6ef48ae54302fa852029c2fcf010aa

Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
chenxiaolong added a commit that referenced this pull request Sep 16, 2026
Signed-off-by: Andrew Gunnerson <accounts+github@chiller3.com>
@chenxiaolong
chenxiaolong merged commit ff60304 into master Sep 16, 2026
1 check passed
@chenxiaolong
chenxiaolong deleted the android-sep-2026 branch September 16, 2026 03:49
@chenxiaolong

Copy link
Copy Markdown
Owner Author

I reported this to upstream Syncthing to see if they have any better ideas for optionally performing in-place file replacements: syncthing/syncthing#10887

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant