/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.security.cts;

import android.content.Context;
import android.content.pm.PackageManager;
import android.net.cts.NetlinkSocket;
import android.os.IBinder;
import android.os.Parcel;
import android.os.RemoteException;
import android.os.storage.StorageManager;
import android.test.AndroidTestCase;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Scanner;
import java.util.Set;

public class VoldExploitTest extends AndroidTestCase {

    /**
     * Try to inject vold commands.
     */
    public void testTryCommandInjection() throws Exception {
        final StorageManager sm = (StorageManager) getContext().getSystemService(
                Context.STORAGE_SERVICE);
        try {
            sm.getMountedObbPath("/dev/null\0asec list");
            fail("able to inject vold commands");
        } catch(IllegalArgumentException e) {
            // expected
        }
    }

    /**
     * Validate that this device isn't vulnerable to the "ZergRush"
     * vold vulnerability (CVE-2011-3874).
     *
     * https://github.com/revolutionary/zergRush/blob/master/zergRush.c
     *
     * Note: If the ZergRush vulnerability is present, the call to
     * {@link StorageManager#getMountedObbPath(String)} below hangs until CTS
     * kills the testsuite (10 minutes). A timeout, while not desirable,
     * is the typical failure for this test.
     */
    public void testZergRushCrash() throws Exception {
        int pid = findVold();

        StorageManager sm = (StorageManager) getContext().getSystemService(Context.STORAGE_SERVICE);
        sm.getMountedObbPath("AAAA AAAA AAAA AAAA "
                + "AAAA AAAA AAAA AAAA "
                + "AAAA AAAA AAAA AAAA "
                + "AAAA AAAA AAAA AAAA"
                + "AAAA AAAA AAAA AAAA"
                + "AAAA AAAA AAAA AAAA"
                + "AAAA AAAA AAAA AAAA"
                + "AAAA AAAA AAAA AAAA");

        Thread.sleep(2000);  // give vold some time to crash

        // Check to see if vold is still alive.
        assertTrue(
                "PID=" + pid + " crashed due to a malformed mount message."
                        + " Detected unpatched ZergRush vulnerability (CVE-2011-3874).",
                new File("/proc/" + pid + "/cmdline").exists());
    }

    /**
     * Validate that this device isn't vulnerable to the "ZergRush"
     * vold vulnerability (CVE-2011-3874).
     *
     * https://github.com/revolutionary/zergRush/blob/master/zergRush.c
     *
     * Note: If the ZergRush vulnerability is present, the call to
     * {@link IBinder#transact(int, android.os.Parcel, android.os.Parcel, int)}}
     * below hangs until CTS kills the testsuite (10 minutes). A timeout,
     * while not desirable, is the typical failure for this test.
     *
     * This test accomplishes the same thing as {@link #testZergRushCrash()}
     */
    public void testZergRushUsingRelection() throws Exception {
        // This test assumes we have the MOUNT_UNMOUNT_FILESYSTEMS permission
        // Check it first so we know we're reaching the vulnerable code.
        assertEquals(PackageManager.PERMISSION_GRANTED,
                getContext().checkCallingOrSelfPermission(
                        android.Manifest.permission.MOUNT_UNMOUNT_FILESYSTEMS));

        int pid = findVold();

        try {
            Object iBinderObj = Class.forName("android.os.ServiceManager")
                    .getDeclaredMethod("getService", String.class)
                    .invoke(null, "mount");
            if (!(iBinderObj instanceof IBinder)) {
                // unexpected return value, return.  Assume not exploitable.
                return;
            }

            String[] names = new String[] {
                    "IMountService",                   // Android 2.3
                    "android.os.storage.IMountService" // Android 2.2
            };

            for (String name : names) {
                IBinder iBinder = (IBinder) iBinderObj;
                Parcel data = Parcel.obtain();
                data.writeInterfaceToken(name);
                data.writeString("AAAA AAAA AAAA AAAA "
                        + "AAAA AAAA AAAA AAAA "
                        + "AAAA AAAA AAAA AAAA "
                        + "AAAA AAAA AAAA AAAA"
                        + "AAAA AAAA AAAA AAAA"
                        + "AAAA AAAA AAAA AAAA"
                        + "AAAA AAAA AAAA AAAA"
                        + "AAAA AAAA AAAA AAAA");

                // If vold crashes, this next line will hang forever.
                iBinder.transact(6, data, null, 0);
            }
        } catch (ClassNotFoundException e) {
            // class doesn't exist. Assume not exploitable.
        } catch (NoSuchMethodException e) {
            // no such method exists. Assume not exploitable.
        } catch (InvocationTargetException e) {
            // can't invoke.  Assume not exploitable.
        } catch (IllegalAccessException e) {
            // can't access.  Assume not exploitable.
        } catch (RemoteException e) {
            // remote failure. Assume not exploitable.
        }

        Thread.sleep(2000);  // give vold some time to crash

        // Check to see if vold is still alive.
        assertTrue(
                "PID=" + pid + " crashed due to a malformed mount message."
                        + " Detected unpatched ZergRush vulnerability (CVE-2011-3874).",
                new File("/proc/" + pid + "/cmdline").exists());
    }

    /**
     * Try to crash the vold program using CVE-2011-1823.
     *
     * This test attempts to send an invalid netlink messages to
     * any process which is listening for the messages.  If we detect
     * that any process crashed as a result of our message, then
     * we know that we found a bug.
     *
     * If this test fails, it's due to CVE-2011-1823
     *
     * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2011-1823
     */
    public void testTryToCrashVold() throws IOException {
        Set<Integer> pids = getPids();
        assertTrue(pids.size() > 1);  // at least vold and netd should exist

        Set<String> devices = new HashSet<String>();
        devices.addAll(getSysFsPath("/etc/vold.fstab"));
        devices.addAll(getSysFsPath("/system/etc/vold.fstab"));
        if (devices.isEmpty()) {
          // This vulnerability is not exploitable if there's
          // no entry in vold.fstab
          return;
        }

        NetlinkSocket ns = NetlinkSocket.create();
        for (int i : pids) {
            for (String j : devices) {
                doAttack(ns, i, j);
            }
        }

        // Check to see if all the processes are still alive.  If
        // any of them have died, we found an exploitable bug.
        for (int i : pids) {
            assertTrue(
                    "PID=" + i + " crashed due to a malformed netlink message."
                    + " Detected unpatched vulnerability CVE-2011-1823.",
                    new File("/proc/" + i + "/cmdline").exists());
        }
    }

    /**
     * Try to actually crash the program, by first sending a fake
     * request to add a new disk, followed by a fake request to add
     * a partition.
     */
    private static void doAttack(NetlinkSocket ns, int pid, String path)
            throws IOException {
        try {
            ns.sendmsg(pid, getDiskAddedMessage(path));
            confirmNetlinkMsgReceived();

            for (int i = -1000; i > -5000; i-=1000) {
                ns.sendmsg(pid, getPartitionAddedMessage(path, i));
                confirmNetlinkMsgReceived();
            }
        } catch (IOException e) {
            // Ignore the exception.  The process either:
            //
            // 1) Crashed
            // 2) Closed the netlink socket and refused further messages
            //
            // If #1 occurs, our PID check in testTryToCrashVold() will
            // detect the process crashed and trigger an error.
            //
            // #2 is not a security bug.  It's perfectly acceptable to
            // refuse messages from someone trying to send you
            // malicious content.
        }
    }

    /**
     * Parse the fstab.vold file, and extract out the "sysfs_path" field.
     */
    private static Set<String> getSysFsPath(String file) throws IOException {
        Set<String> retval = new HashSet<String>();
        File netlink = new File(file);
        if (!netlink.canRead()) {
            return retval;
        }
        Scanner scanner = null;
        try {
            scanner = new Scanner(netlink);
            while(scanner.hasNextLine()) {
                String line = scanner.nextLine().trim();
                if (!line.startsWith("dev_mount")) {
                    continue;
                }

                String[] fields = line.split("\\s+");
                assertTrue(fields.length >= 5);
                // Column 5 and beyond is "sysfs_path"
                retval.addAll(Arrays.asList(fields).subList(4, fields.length));
            }
        } finally {
            if (scanner != null) {
                scanner.close();
            }
        }
        return retval;
    }

    /**
     * Poll /proc/net/netlink until all the "Rmem" fields contain
     * "0" or approximately 10 seconds have passed.
     *
     * This indicates that either the netlink message was received,
     * or the process took too long to process the incoming netlink
     * message.
     *
     * See http://code.google.com/p/android/issues/detail?id=25099
     * for information on why the timeout is needed.
     */
    private static void confirmNetlinkMsgReceived() {
        try {
            for (int ct = 0; ct < 200; ct++) {
                boolean foundAllZeros = true;
                for (List<String> i : parseNetlink()) {
                    // Column 5 is the "Rmem" field, which is the
                    // amount of kernel memory for received netlink messages.
                    if (!i.get(4).equals("0")) {
                        foundAllZeros = false;
                    }
                }
                if (foundAllZeros) {
                    return;
                }
                Thread.sleep(50);
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    private static int findVold() throws IOException {
        File f = new File("/proc");
        for (File d : f.listFiles()) {
            String cmdLineString = d.getAbsolutePath() + "/cmdline";
            File cmdLine = new File(cmdLineString);
            if (cmdLine.exists()) {
                BufferedReader in = null;
                try {
                    in = new BufferedReader(new FileReader(cmdLine));
                    String line = in.readLine();
                    if ((line != null) && line.startsWith("/system/bin/vold")) {
                        return Integer.decode(d.getName());
                    }
                } finally {
                    if (in != null) {
                        in.close();
                    }
                }
            }
        }
        throw new RuntimeException("should never get here");
    }

    /**
     * Extract all the PIDs listening for netlink messages.
     */
    private static Set<Integer> getPids() {
        List<List<String>> netlink = parseNetlink();
        Set<Integer> retval = new HashSet<Integer>();
        for (List<String> i : netlink) {
            // The PID is in column 3
            int pid = Integer.decode(i.get(2));
            if (new File("/proc/" + pid + "/cmdline").exists()) {
                retval.add(pid);
            }
        }
        return retval;
    }

    /**
     * Parse /proc/net/netlink and return a List of lines
     * (excluding the first line)
     */
    private static List<List<String>> parseNetlink() {
        List<List<String>> retval = new ArrayList<List<String>>();
        File netlink = new File("/proc/net/netlink");
        Scanner scanner = null;
        try {
            scanner = new Scanner(netlink);
            while(scanner.hasNextLine()) {
                String line = scanner.nextLine().trim();
                if (line.startsWith("sk")) {
                    continue;
                }

                List<String> lineList = Arrays.asList(line.split("\\s+"));
                retval.add(lineList);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (scanner != null) {
                scanner.close();
            }
        }
        return retval;
    }

    private static byte[] getDiskAddedMessage(String path) {
        try {
            return ("@/foo\0ACTION=add\0SUBSYSTEM=block\0"
                    + "DEVPATH=" + path + "\0MAJOR=179\0MINOR=12345"
                    + "\0DEVTYPE=disk\0").getBytes("ASCII");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    private static byte[] getPartitionAddedMessage(
            String path, int partitionNum) {
        try {
            return ("@/foo\0ACTION=add\0SUBSYSTEM=block\0"
                    + "DEVPATH=" + path + "\0MAJOR=179\0MINOR=12345"
                    + "\0DEVTYPE=blah\0PARTN=" + partitionNum + "\0")
                    .getBytes("ASCII");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }
}
