Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 416d4623 authored by Jeff Sharkey's avatar Jeff Sharkey Committed by Jeff Sharkey
Browse files

Intercept unlink(), remove(), and rename().

Handles cases where apps try deleting paths returned in "_data"
columns, and where they try renaming across bind mounts.

Bug: 124349250
Test: atest android.appsecurity.cts.ExternalStorageHostTest#testExternalStorageRename
Change-Id: I7f4461bcacada80398eb95d051a0d29456f63499
parent cef5e0e7
Loading
Loading
Loading
Loading
+54 −0
Original line number Diff line number Diff line
@@ -182,6 +182,7 @@ import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.nio.file.Files;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
@@ -6961,6 +6962,23 @@ public final class ActivityThread extends ClientTransactionHandler {
            }
        }

        private void deleteDeprecatedDataPath(String path) throws ErrnoException {
            final Uri uri = ContentResolver.translateDeprecatedDataPath(path);
            Log.v(TAG, "Redirecting " + path + " to " + uri);

            final ContentResolver cr = currentActivityThread().getApplication()
                    .getContentResolver();
            try {
                if (cr.delete(uri, null, null) == 0) {
                    throw new FileNotFoundException();
                }
            } catch (SecurityException e) {
                throw new ErrnoException(e.getMessage(), OsConstants.EACCES);
            } catch (FileNotFoundException e) {
                throw new ErrnoException(e.getMessage(), OsConstants.ENOENT);
            }
        }

        @Override
        public boolean access(String path, int mode) throws ErrnoException {
            if (path != null && path.startsWith(DEPRECATE_DATA_PREFIX)) {
@@ -6995,6 +7013,42 @@ public final class ActivityThread extends ClientTransactionHandler {
                return super.stat(path);
            }
        }

        @Override
        public void unlink(String path) throws ErrnoException {
            if (path != null && path.startsWith(DEPRECATE_DATA_PREFIX)) {
                deleteDeprecatedDataPath(path);
            } else {
                super.unlink(path);
            }
        }

        @Override
        public void remove(String path) throws ErrnoException {
            if (path != null && path.startsWith(DEPRECATE_DATA_PREFIX)) {
                deleteDeprecatedDataPath(path);
            } else {
                super.remove(path);
            }
        }

        @Override
        public void rename(String oldPath, String newPath) throws ErrnoException {
            try {
                super.rename(oldPath, newPath);
            } catch (ErrnoException e) {
                if (e.errno == OsConstants.EXDEV) {
                    Log.v(TAG, "Recovering failed rename " + oldPath + " to " + newPath);
                    try {
                        Files.move(new File(oldPath).toPath(), new File(newPath).toPath());
                    } catch (IOException e2) {
                        throw e;
                    }
                } else {
                    throw e;
                }
            }
        }
    }

    public static void main(String[] args) {