Home | History | Annotate | Download | only in src-ex
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 import art.Redefinition;
     18 import java.util.Base64;
     19 
     20 public class DexCacheSmash {
     21   static class Transform {
     22     public void foo() {}
     23     public void bar() {}
     24     public String getId() {
     25       return "TRANSFORM_INITIAL";
     26     }
     27   }
     28 
     29   static class Transform2 {
     30     public String getId() {
     31       return "TRANSFORM2_INITIAL";
     32     }
     33   }
     34 
     35   /**
     36    * A base64 encoding of the dex/class file of the Transform class above.
     37    */
     38   static final  Redefinition.CommonClassDefinition TRANSFORM_INITIAL =
     39       new Redefinition.CommonClassDefinition(Transform.class,
     40           Base64.getDecoder().decode(
     41             "yv66vgAAADQAFwoABAAPCAAQBwASBwAVAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1i" +
     42             "ZXJUYWJsZQEAA2ZvbwEAA2JhcgEABWdldElkAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAApTb3Vy" +
     43             "Y2VGaWxlAQASRGV4Q2FjaGVTbWFzaC5qYXZhDAAFAAYBABFUUkFOU0ZPUk1fSU5JVElBTAcAFgEA" +
     44             "F0RleENhY2hlU21hc2gkVHJhbnNmb3JtAQAJVHJhbnNmb3JtAQAMSW5uZXJDbGFzc2VzAQAQamF2" +
     45             "YS9sYW5nL09iamVjdAEADURleENhY2hlU21hc2gAIAADAAQAAAAAAAQAAAAFAAYAAQAHAAAAHQAB" +
     46             "AAEAAAAFKrcAAbEAAAABAAgAAAAGAAEAAAATAAEACQAGAAEABwAAABkAAAABAAAAAbEAAAABAAgA" +
     47             "AAAGAAEAAAAUAAEACgAGAAEABwAAABkAAAABAAAAAbEAAAABAAgAAAAGAAEAAAAVAAEACwAMAAEA" +
     48             "BwAAABsAAQABAAAAAxICsAAAAAEACAAAAAYAAQAAABcAAgANAAAAAgAOABQAAAAKAAEAAwARABMA" +
     49             "CA=="),
     50           Base64.getDecoder().decode(
     51             "ZGV4CjAzNQDhg9CfghG1SRlLClguRuFYsqihr4F7NsGQAwAAcAAAAHhWNBIAAAAAAAAAAOQCAAAS" +
     52             "AAAAcAAAAAcAAAC4AAAAAgAAANQAAAAAAAAAAAAAAAUAAADsAAAAAQAAABQBAABcAgAANAEAAKgB" +
     53             "AACwAQAAxAEAAMcBAADiAQAA8wEAABcCAAA3AgAASwIAAF8CAAByAgAAfQIAAIACAACNAgAAkgIA" +
     54             "AJcCAACeAgAApAIAAAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAsAAAACAAAABQAAAAAAAAALAAAA" +
     55             "BgAAAAAAAAAAAAEAAAAAAAAAAQANAAAAAAABAA4AAAAAAAAADwAAAAQAAQAAAAAAAAAAAAAAAAAE" +
     56             "AAAAAAAAAAEAAACYAQAAzgIAAAAAAAACAAAAvwIAAMUCAAABAAEAAQAAAKsCAAAEAAAAcBAEAAAA" +
     57             "DgABAAEAAAAAALACAAABAAAADgAAAAEAAQAAAAAAtQIAAAEAAAAOAAAAAgABAAAAAAC6AgAAAwAA" +
     58             "ABoACQARAAAANAEAAAAAAAAAAAAAAAAAAAY8aW5pdD4AEkRleENhY2hlU21hc2guamF2YQABTAAZ" +
     59             "TERleENhY2hlU21hc2gkVHJhbnNmb3JtOwAPTERleENhY2hlU21hc2g7ACJMZGFsdmlrL2Fubm90" +
     60             "YXRpb24vRW5jbG9zaW5nQ2xhc3M7AB5MZGFsdmlrL2Fubm90YXRpb24vSW5uZXJDbGFzczsAEkxq" +
     61             "YXZhL2xhbmcvT2JqZWN0OwASTGphdmEvbGFuZy9TdHJpbmc7ABFUUkFOU0ZPUk1fSU5JVElBTAAJ" +
     62             "VHJhbnNmb3JtAAFWAAthY2Nlc3NGbGFncwADYmFyAANmb28ABWdldElkAARuYW1lAAV2YWx1ZQAT" +
     63             "AAcOABUABw4AFAAHDgAXAAcOAAICAREYAQIDAgwECBAXCgAAAQMAgIAEwAIBAdgCAQHsAgEBgAMO" +
     64             "AAAAAAAAAAEAAAAAAAAAAQAAABIAAABwAAAAAgAAAAcAAAC4AAAAAwAAAAIAAADUAAAABQAAAAUA" +
     65             "AADsAAAABgAAAAEAAAAUAQAAAxAAAAEAAAA0AQAAASAAAAQAAABAAQAABiAAAAEAAACYAQAAAiAA" +
     66             "ABIAAACoAQAAAyAAAAQAAACrAgAABCAAAAIAAAC/AgAAACAAAAEAAADOAgAAABAAAAEAAADkAgAA"));
     67 
     68   /**
     69    * A base64 encoding of the following (invalid) class.
     70    *
     71    *  .class LDexCacheSmash$Transform2;
     72    *  .super Ljava/lang/Object;
     73    *  .source "DexCacheSmash.java"
     74    *
     75    *  # annotations
     76    *  .annotation system Ldalvik/annotation/EnclosingClass;
     77    *      value = LDexCacheSmash;
     78    *  .end annotation
     79    *
     80    *  .annotation system Ldalvik/annotation/InnerClass;
     81    *      accessFlags = 0x8
     82    *      name = "Transform2"
     83    *  .end annotation
     84    *
     85    *
     86    *  # direct methods
     87    *  .method constructor <init>()V
     88    *      .registers 1
     89    *
     90    *      .prologue
     91    *      .line 26
     92    *      invoke-direct {p0}, Ljava/lang/Object;-><init>()V
     93    *
     94    *      return-void
     95    *  .end method
     96    *
     97    *
     98    *  # virtual methods
     99    *  .method public getId()Ljava/lang/String;
    100    *      .registers 2
    101    *
    102    *      .prologue
    103    *      .line 28
    104    *      # NB Fails verification due to this function not returning a String.
    105    *      return-void
    106    *  .end method
    107    */
    108   static final  Redefinition.CommonClassDefinition TRANSFORM2_INVALID =
    109       new Redefinition.CommonClassDefinition(Transform2.class,
    110           Base64.getDecoder().decode(
    111             "yv66vgAAADQAEwcAEgcAEQEABjxpbml0PgEAAygpVgEABENvZGUKAAIAEAEAD0xpbmVOdW1iZXJU" +
    112             "YWJsZQEABWdldElkAQAUKClMamF2YS9sYW5nL1N0cmluZzsBAApTb3VyY2VGaWxlAQASRGV4Q2Fj" +
    113             "aGVTbWFzaC5qYXZhAQAMSW5uZXJDbGFzc2VzBwAPAQAKVHJhbnNmb3JtMgEADURleENhY2hlU21h" +
    114             "c2gMAAMABAEAEGphdmEvbGFuZy9PYmplY3QBABhEZXhDYWNoZVNtYXNoJFRyYW5zZm9ybTIAIAAB" +
    115             "AAIAAAAAAAIAAAADAAQAAQAFAAAAHQABAAEAAAAFKrcABrEAAAABAAcAAAAGAAEAAAAaAAEACAAJ" +
    116             "AAEABQAAABkAAQABAAAAAbEAAAABAAcAAAAGAAEAAAAcAAIACgAAAAIACwAMAAAACgABAAEADQAO" +
    117             "AAg="),
    118           Base64.getDecoder().decode(
    119             "ZGV4CjAzNQCFcegr6Ns+I7iEF4uLRkUX4yGrLhP6soEgAwAAcAAAAHhWNBIAAAAAAAAAAHQCAAAP" +
    120             "AAAAcAAAAAcAAACsAAAAAgAAAMgAAAAAAAAAAAAAAAMAAADgAAAAAQAAAPgAAAAIAgAAGAEAABgB" +
    121             "AAAgAQAANAEAADcBAABTAQAAZAEAAIgBAACoAQAAvAEAANABAADcAQAA3wEAAOwBAADzAQAA+QEA" +
    122             "AAMAAAAEAAAABQAAAAYAAAAHAAAACAAAAAoAAAACAAAABQAAAAAAAAAKAAAABgAAAAAAAAAAAAEA" +
    123             "AAAAAAAAAAAMAAAABAABAAAAAAAAAAAAAAAAAAQAAAAAAAAAAQAAACACAABmAgAAAAAAAAY8aW5p" +
    124             "dD4AEkRleENhY2hlU21hc2guamF2YQABTAAaTERleENhY2hlU21hc2gkVHJhbnNmb3JtMjsAD0xE" +
    125             "ZXhDYWNoZVNtYXNoOwAiTGRhbHZpay9hbm5vdGF0aW9uL0VuY2xvc2luZ0NsYXNzOwAeTGRhbHZp" +
    126             "ay9hbm5vdGF0aW9uL0lubmVyQ2xhc3M7ABJMamF2YS9sYW5nL09iamVjdDsAEkxqYXZhL2xhbmcv" +
    127             "U3RyaW5nOwAKVHJhbnNmb3JtMgABVgALYWNjZXNzRmxhZ3MABWdldElkAARuYW1lAAV2YWx1ZQAC" +
    128             "AwILBAgNFwkCAgEOGAEAAAAAAAIAAAAJAgAAAAIAABQCAAAAAAAAAAAAAAAAAAAaAAcOABwABw4A" +
    129             "AAABAAEAAQAAADACAAAEAAAAcBACAAAADgACAAEAAAAAADUCAAABAAAADgAAAAEBAICABLwEAQHU" +
    130             "BA4AAAAAAAAAAQAAAAAAAAABAAAADwAAAHAAAAACAAAABwAAAKwAAAADAAAAAgAAAMgAAAAFAAAA" +
    131             "AwAAAOAAAAAGAAAAAQAAAPgAAAACIAAADwAAABgBAAAEIAAAAgAAAAACAAADEAAAAgAAABACAAAG" +
    132             "IAAAAQAAACACAAADIAAAAgAAADACAAABIAAAAgAAADwCAAAAIAAAAQAAAGYCAAAAEAAAAQAAAHQC" +
    133             "AAA="));
    134 
    135   public static void run() throws Exception {
    136     try {
    137       Redefinition.doMultiClassRedefinition(TRANSFORM2_INVALID);
    138     } catch (Exception e) {
    139       if (!e.getMessage().endsWith("JVMTI_ERROR_FAILS_VERIFICATION")) {
    140         throw new Error(
    141             "Unexpected error: Expected failure due to JVMTI_ERROR_FAILS_VERIFICATION", e);
    142       }
    143     }
    144     // Doing this redefinition after a redefinition that failed due to FAILS_VERIFICATION could
    145     // cause a use-after-free of the Transform2's DexCache by the redefinition code if it happens
    146     // that the native pointer of the art::DexFile created for the Transform redefinition aliases
    147     // the one created for Transform2's failed redefinition.
    148     //
    149     // Due to the order of checks performed by the redefinition code FAILS_VERIFICATION is the only
    150     // failure mode that can cause Use-after-frees in this way.
    151     //
    152     // This should never throw any exceptions (except perhaps OOME in very strange circumstances).
    153     Redefinition.doMultiClassRedefinition(TRANSFORM_INITIAL);
    154   }
    155 }
    156