######################################################################
##
## SEEK-for-Android Add-On Terminal Vunerability patch
## see CVE-2015-6606 (Google internal bug# ANDROID-22301786)
##
######################################################################

This patch removes a vulnerability of SEEK-for-Android that permits
an attacker to load arbitrary code into the execution context of the
smartcard system service.

Add-on terminals are no longer supported after this patch is applied.

Detailed information on the SEEK add-on terminal vulnerability and
possible exploits can be found in the report "Executing Arbitrary
Code in the Context of the Smartcard System Service" by Michael Roland

This patch applies to version 3.0.0 of SEEK-for-Android.

Copyright (c) 2015 Michael Roland, FH OÖ Forschungs & Entwicklungs GmbH

######################################################################
## University of Applied Sciences Upper Austria
## Josef Ressel Center u'smile
## Visit us at https://usmile.at/
######################################################################

Apply with "patch -p1 <seek_3_0_0_CVE-2015-6606.patch" from the root
of the Android source tree.

diff -ruN seek_3_0_0/packages/apps/SmartCardService/src/org/simalliance/openmobileapi/service/AddonTerminal.java seek_3_0_0_patched/packages/apps/SmartCardService/src/org/simalliance/openmobileapi/service/AddonTerminal.java
--- seek_3_0_0/packages/apps/SmartCardService/src/org/simalliance/openmobileapi/service/AddonTerminal.java
+++ seek_3_0_0_patched/packages/apps/SmartCardService/src/org/simalliance/openmobileapi/service/AddonTerminal.java
@@ -1,247 +0,0 @@
-/*
- * 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.
- */
-/*
- * Contributed by: Giesecke & Devrient GmbH.
- */
-
-package org.simalliance.openmobileapi.service;
-
-import android.content.Context;
-import android.content.pm.PackageInfo;
-
-import java.lang.reflect.Method;
-import java.util.LinkedList;
-import java.util.List;
-
-public class AddonTerminal extends Terminal {
-
-    private Object mInstance = null;
-
-    private Method mIsCardPresent = null;
-
-    private Method mInternalConnect = null;
-
-    private Method mInternalDisconnect = null;
-
-    private Method mInternalTransmit = null;
-
-    private Method mInternalOpenLogicalChannel = null;
-
-    private Method mInternalOpenLogicalChannelAID = null;
-
-    private Method mInternalCloseLogicalChannel = null;
-
-    private Method mGetName = null;
-
-    private Method mGetAtr = null;
-    
-    private Method mGetSelectResponse = null;
-
-    public static String[] getPackageNames(Context context) {
-        List<String> packageNameList = new LinkedList<String>();
-        List<PackageInfo> pis = context.getPackageManager().getInstalledPackages(0);
-        for (PackageInfo p : pis) {
-            if (p.packageName.startsWith("org.simalliance.openmobileapi.service.terminals.")
-                    || p.packageName.startsWith("org.simalliance.openmobileapi.cts")) {
-                packageNameList.add(p.packageName);
-            }
-        }
-        String[] rstrings = new String[packageNameList.size()];
-        packageNameList.toArray(rstrings);
-        return rstrings;
-    }
-
-    public AddonTerminal(Context context, String packageName, String className) {
-        super("Addon", context);
-
-        try {
-            Context ctx = context.createPackageContext(packageName, Context.CONTEXT_IGNORE_SECURITY
-                    | Context.CONTEXT_INCLUDE_CODE);
-            ClassLoader cl = ctx.getClassLoader();
-            Class<?> cls = cl.loadClass(className);
-            mInstance = cls.getConstructor(new Class[] {
-                Context.class
-            }).newInstance(new Object[] {
-                context
-            });
-            if (mInstance != null) {
-                mGetAtr = mInstance.getClass().getDeclaredMethod("getAtr", (Class<?>[]) null);
-                mGetName = mInstance.getClass().getDeclaredMethod("getName", (Class<?>[]) null);
-                mIsCardPresent = mInstance.getClass().getDeclaredMethod("isCardPresent",
-                        (Class<?>[]) null);
-                mInternalConnect = mInstance.getClass().getDeclaredMethod("internalConnect",
-                        (Class<?>[]) null);
-                mInternalDisconnect = mInstance.getClass().getDeclaredMethod("internalDisconnect",
-                        (Class<?>[]) null);
-                mInternalTransmit = mInstance.getClass().getDeclaredMethod("internalTransmit",
-                        new Class[] {
-                            byte[].class
-                        });
-                mInternalOpenLogicalChannel = mInstance.getClass().getDeclaredMethod(
-                        "internalOpenLogicalChannel", (Class<?>[]) null);
-                mInternalOpenLogicalChannelAID = mInstance.getClass().getDeclaredMethod(
-                        "internalOpenLogicalChannel", new Class[] {
-                            byte[].class
-                        });
-                mInternalCloseLogicalChannel = mInstance.getClass().getDeclaredMethod(
-                        "internalCloseLogicalChannel", new Class[] {
-                            int.class
-                        });
-                mGetSelectResponse = mInstance.getClass().getDeclaredMethod("getSelectResponse",
-                        (Class<?>[]) null);
-            }
-        } catch (Exception e) {
-            throw new IllegalStateException("plugin internal error: " + e);
-        }
-    }
-
-    /**
-     * Returns the ATR of the connected card or null if the ATR is not
-     * available.
-     * 
-     * @return the ATR of the connected card or null if the ATR is not
-     *         available.
-     */
-    public byte[] getAtr() {
-        if (mGetAtr == null) {
-            throw new IllegalStateException("plugin error: Function String getAtr() not found");
-        }
-        try {
-            byte[] resp = (byte[]) mGetAtr.invoke(mInstance, (Object[]) null);
-            return resp;
-        } catch (Exception e) {
-            throw new IllegalStateException("plugin internal error: getAtr() execution: "
-                    + e.getCause());
-        }
-    }
-
-    public String getName() {
-        if (mGetName == null) {
-            throw new IllegalStateException("plugin error: Function String getName() not found");
-        }
-        try {
-            String s = (String) mGetName.invoke(mInstance, (Object[]) null);
-            return s;
-        } catch (Exception e) {
-            throw new IllegalStateException("plugin internal error: getName() execution: "
-                    + e.getCause());
-        }
-    }
-
-    public boolean isCardPresent() throws CardException {
-        if (mIsCardPresent == null) {
-            throw new IllegalStateException(
-                    "plugin error: Function String isCardPresent() not found");
-        }
-        try {
-            Boolean v = (Boolean) mIsCardPresent.invoke(mInstance, (Object[]) null);
-            return v.booleanValue();
-        } catch (Exception e) {
-            throw new CardException("plugin internal error: isCardPresent() execution: "
-                    + e.getCause());
-        }
-    }
-
-    protected void internalConnect() throws CardException {
-        if (mInternalConnect == null) {
-            throw new IllegalStateException(
-                    "plugin error: Function String internalConnect() not found");
-        }
-        try {
-            mInternalConnect.invoke(mInstance, (Object[]) null);
-            mIsConnected = true;
-        } catch (Exception e) {
-            throw new CardException("plugin internal error: internalConnect() execution: "
-                    + e.getCause());
-        }
-    }
-
-    protected void internalDisconnect() throws CardException {
-        if (mInternalDisconnect == null) {
-            throw new IllegalStateException(
-                    "plugin error: Function String internalDisconnect() not found");
-        }
-        try {
-            mInternalDisconnect.invoke(mInstance, (Object[]) null);
-            mIsConnected = false;
-        } catch (Exception e) {
-            throw new CardException("plugin internal error: internalDisconnect() execution");
-        }
-    }
-
-    protected byte[] internalTransmit(byte[] command) throws CardException {
-        if (mInternalTransmit == null) {
-            throw new IllegalStateException(
-                    "plugin error: Function String internalTransmit() not found");
-        }
-        try {
-            byte[] resp = (byte[]) mInternalTransmit.invoke(mInstance, new Object[] {
-                command
-            });
-            return resp;
-        } catch (Exception e) {
-            throw new CardException("plugin internal error: internalTransmit() execution: "
-                    + e.getCause());
-        }
-    }
-
-    protected int internalOpenLogicalChannel() throws Exception {
-        if (mInternalOpenLogicalChannel == null) {
-            throw new IllegalStateException(
-                    "plugin error: Function String internalOpenLogicalChannel() not found");
-        }
-        try {
-            Integer channel = (Integer) mInternalOpenLogicalChannel.invoke(mInstance,
-                    (Object[]) null);
-            return channel.intValue();
-        } catch (Exception e) {
-            throw (Exception) e.getCause();
-        }
-    }
-
-    protected int internalOpenLogicalChannel(byte[] aid) throws Exception {
-        if (mInternalOpenLogicalChannelAID == null) {
-            throw new IllegalStateException(
-                    "plugin error: Function internalOpenLogicalChannelAID() not found");
-        }
-        try {
-            Integer channel = (Integer) mInternalOpenLogicalChannelAID.invoke(mInstance,
-                    new Object[] {
-                        aid
-                    });
-            mSelectResponse = (byte[]) mGetSelectResponse.invoke(mInstance, (Object[]) null);
-            return channel.intValue();
-        } catch (Exception e) {
-            throw (Exception) e.getCause();
-        }
-    }
-
-    protected void internalCloseLogicalChannel(int channelNumber) throws CardException {
-        if (mInternalCloseLogicalChannel == null) {
-            throw new IllegalStateException(
-                    "plugin error: Function internalCloseLogicalChannel not found");
-        }
-        try {
-            mInternalCloseLogicalChannel.invoke(mInstance, new Object[] {
-                channelNumber
-            });
-        } catch (Exception e) {
-            throw new CardException(
-                    "plugin internal error: internalOpenLogicalChannel() execution: "
-                            + e.getCause());
-        }
-    }
-}
diff -ruN seek_3_0_0/packages/apps/SmartCardService/src/org/simalliance/openmobileapi/service/SmartcardService.java seek_3_0_0_patched/packages/apps/SmartCardService/src/org/simalliance/openmobileapi/service/SmartcardService.java
--- seek_3_0_0/packages/apps/SmartCardService/src/org/simalliance/openmobileapi/service/SmartcardService.java
+++ seek_3_0_0_patched/packages/apps/SmartCardService/src/org/simalliance/openmobileapi/service/SmartcardService.java
@@ -98,12 +98,6 @@
      */
     private Map<String, ITerminal> mTerminals = new TreeMap<String, ITerminal>();
 
-    /**
-     * For now this list is setup in onCreate(), not changed later and therefore
-     * not synchronized.
-     */
-    private Map<String, ITerminal> mAddOnTerminals = new TreeMap<String, ITerminal>();
-
 
 
     public SmartcardService() {
@@ -262,36 +256,12 @@
 
 			}
         }
-        col = this.mAddOnTerminals.values();
-        iter = col.iterator();
-        while(iter.hasNext()){
-        	ITerminal terminal = iter.next();
-        	if( terminal == null ){
-
-        		continue;
-        	}
-
-        	try {
-        		if( se == null || terminal.getName().startsWith(se)) {
-        			if(terminal.isCardPresent() ) {
-				    	Log.i(_TAG, "Initializing Access Control for " + terminal.getName());
-        				terminal.initializeAccessControl(true, callback);
-        			} else {
-				    	Log.i(_TAG, "NOT initializing Access Control for " + terminal.getName() + " SE not present.");
-        			}
-        		}
-			} catch (CardException e) {
-
-			}
-        }
 	}
 
 	public void onDestroy() {
         Log.v(_TAG, " smartcard service onDestroy ...");
         for (ITerminal terminal : mTerminals.values())
             terminal.closeChannels();
-        for (ITerminal terminal : mAddOnTerminals.values())
-            terminal.closeChannels();
 
         Log.v(_TAG, Thread.currentThread().getName()
                 + " ... smartcard service onDestroy");
@@ -304,10 +274,7 @@
         }
         ITerminal terminal = mTerminals.get(reader);
         if (terminal == null) {
-            terminal = mAddOnTerminals.get(reader);
-            if (terminal == null) {
-                setError(error, IllegalArgumentException.class, "unknown reader");
-            }
+            setError(error, IllegalArgumentException.class, "unknown reader");
         }
         return terminal;
     }
@@ -323,14 +290,6 @@
         if(list.remove(_UICC_TERMINAL + " - UICC")) 
         	list.add(0, _UICC_TERMINAL + " - UICC");
 
-        createAddonTerminals();
-        names = mAddOnTerminals.keySet();
-        for (String name : names) {
-            if (!list.contains(name)) {
-                list.add(name);
-            }
-        }
-        
         return list.toArray(new String[list.size()]);
     }
 
@@ -343,14 +302,6 @@
         if(list.remove(_UICC_TERMINAL + " - UICC")) 
         	list.add(0, _UICC_TERMINAL + " - UICC");
         
-        updateAddonTerminals();
-        names = mAddOnTerminals.keySet();
-        for (String name : names) {
-            if (!list.contains(name)) {
-                list.add(name);
-            }
-        }
-        
         return list.toArray(new String[list.size()]);
     }
 
@@ -374,69 +325,6 @@
             } catch (Throwable t) {
                 Log.e(_TAG, Thread.currentThread().getName()
                         + " CreateReaders Error: "
-                        + ((t.getMessage() != null) ? t.getMessage() : "unknown"));
-            }
-        }
-    }
-
-    private void createAddonTerminals() {
-        String[] packageNames = AddonTerminal.getPackageNames(this);
-        for (String packageName : packageNames) {
-            try {
-                String apkName = getPackageManager().getApplicationInfo(packageName, 0).sourceDir;
-                DexFile dexFile = new DexFile(apkName);
-                Enumeration<String> classFileNames = dexFile.entries();
-                while (classFileNames.hasMoreElements()) {
-                    String className = classFileNames.nextElement();
-                    if (className.endsWith("Terminal")) {
-                        ITerminal terminal = new AddonTerminal(this, packageName, className);
-                        mAddOnTerminals.put(terminal.getName(), terminal);
-                        Log.v(_TAG, Thread.currentThread().getName() + " adding "
-                                + terminal.getName());
-                    }
-                }
-            } catch (Throwable t) {
-                Log.e(_TAG, Thread.currentThread().getName()
-                        + " CreateReaders Error: "
-                        + ((t.getMessage() != null) ? t.getMessage() : "unknown"));
-            }
-        }
-    }
-
-    private void updateAddonTerminals() {
-        Set<String> names = mAddOnTerminals.keySet();
-        ArrayList<String> namesToRemove = new ArrayList<String>();
-        for (String name : names) {
-            ITerminal terminal = mAddOnTerminals.get(name);
-            if (!terminal.isConnected()) {
-                namesToRemove.add(terminal.getName());
-            }
-        }
-        for (String name : namesToRemove) {
-            mAddOnTerminals.remove(name);
-        }
-
-        String[] packageNames = AddonTerminal.getPackageNames(this);
-        for (String packageName : packageNames) {
-            try {
-                String apkName = getPackageManager().getApplicationInfo(packageName, 0).sourceDir;
-                DexFile dexFile = new DexFile(apkName);
-                Enumeration<String> classFileNames = dexFile.entries();
-                while (classFileNames.hasMoreElements()) {
-                    String className = classFileNames.nextElement();
-                    if (className.endsWith("Terminal")) {
-                        ITerminal terminal = new AddonTerminal(this, packageName, className);
-                        if (!mAddOnTerminals.containsKey(terminal.getName())) {
-                            mAddOnTerminals.put(terminal.getName(), terminal);
-                            Log.v(_TAG, Thread.currentThread().getName()
-                                    + " adding " + terminal.getName());
-                        }
-                    }
-                }
-
-            } catch (Throwable t) {
-                Log.e(_TAG, Thread.currentThread().getName()
-                        + " CreateReaders Error: "
                         + ((t.getMessage() != null) ? t.getMessage() : "unknown"));
             }
         }
