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

Commit 1ae7af10 authored by Andreas Gampe's avatar Andreas Gampe Committed by Gerrit Code Review
Browse files

Merge "Zygote: Preserve capabilities in WrapperInit"

parents 7f14b8f0 220aba25
Loading
Loading
Loading
Loading
+59 −0
Original line number Diff line number Diff line
@@ -17,6 +17,11 @@
package com.android.internal.os;

import android.os.Process;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
import android.system.StructCapUserData;
import android.system.StructCapUserHeader;
import android.util.Slog;
import com.android.internal.os.Zygote.MethodAndArgsCaller;
import dalvik.system.VMRuntime;
@@ -119,6 +124,7 @@ public class WrapperInit {
        command.append(' ');
        command.append(targetSdkVersion);
        Zygote.appendQuotedShellArgs(command, args);
        preserveCapabilities();
        Zygote.execShell(command.toString());
    }

@@ -156,4 +162,57 @@ public class WrapperInit {

        RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
    }

    /**
     * Copy current capabilities to ambient capabilities. This is required for apps using
     * capabilities, as execv will re-evaluate the capability set, and the set of sh is
     * empty. Ambient capabilities have to be set to inherit them effectively.
     *
     * Note: This is BEST EFFORT ONLY. In case capabilities can't be raised, this function
     *       will silently return. In THIS CASE ONLY, as this is a development feature, it
     *       is better to return and try to run anyways, instead of blocking the wrapped app.
     *       This is acceptable here as failure will leave the wrapped app with strictly less
     *       capabilities, which may make it crash, but not exceed its allowances.
     */
    private static void preserveCapabilities() {
        StructCapUserHeader header = new StructCapUserHeader(
                OsConstants._LINUX_CAPABILITY_VERSION_3, 0);
        StructCapUserData[] data;
        try {
            data = Os.capget(header);
        } catch (ErrnoException e) {
            Slog.e(RuntimeInit.TAG, "RuntimeInit: Failed capget", e);
            return;
        }

        if (data[0].permitted != data[0].inheritable ||
                data[1].permitted != data[1].inheritable) {
            data[0] = new StructCapUserData(data[0].effective, data[0].permitted,
                    data[0].permitted);
            data[1] = new StructCapUserData(data[1].effective, data[1].permitted,
                    data[1].permitted);
            try {
                Os.capset(header, data);
            } catch (ErrnoException e) {
                Slog.e(RuntimeInit.TAG, "RuntimeInit: Failed capset", e);
                return;
            }
        }

        for (int i = 0; i < 64; i++) {
            int dataIndex = OsConstants.CAP_TO_INDEX(i);
            int capMask = OsConstants.CAP_TO_MASK(i);
            if ((data[dataIndex].inheritable & capMask) != 0) {
                try {
                    Os.prctl(OsConstants.PR_CAP_AMBIENT, OsConstants.PR_CAP_AMBIENT_RAISE, i, 0,
                            0);
                } catch (ErrnoException ex) {
                    // Only log here. Try to run the wrapped application even without this
                    // ambient capability. It may crash after fork, but at least we'll try.
                    Slog.e(RuntimeInit.TAG, "RuntimeInit: Failed to raise ambient capability "
                            + i, ex);
                }
            }
        }
    }
}