[BUG] DoS system backup: NullPointerException for SharedPreferences
When the Android system is trying to back up the app to one of its backup transports (e.g. Google Backup or Seedvault), Orbot crashes and with it the entire backup, essentially DoSing system backup.
09-24 14:24:33.980 10200 19444 19444 E AndroidRuntime: Process: org.torproject.android, PID: 19444
09-24 14:24:33.980 10200 19444 19444 E AndroidRuntime: java.lang.RuntimeException: Unable to create service org.torproject.android.service.OrbotService: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.String android.content.SharedPreferences.getString(java.lang.String, java.lang.String)' on a null object reference
09-24 14:24:33.980 10200 19444 19444 E AndroidRuntime: at android.app.ActivityThread.handleCreateService(ActivityThread.java:4925)
09-24 14:24:33.980 10200 19444 19444 E AndroidRuntime: at android.app.ActivityThread.-$$Nest$mhandleCreateService(Unknown Source:0)
09-24 14:24:33.980 10200 19444 19444 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2407)
09-24 14:24:33.980 10200 19444 19444 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:107)
09-24 14:24:33.980 10200 19444 19444 E AndroidRuntime: at android.os.Looper.loopOnce(Looper.java:232)
09-24 14:24:33.980 10200 19444 19444 E AndroidRuntime: at android.os.Looper.loop(Looper.java:317)
09-24 14:24:33.980 10200 19444 19444 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:8592)
09-24 14:24:33.980 10200 19444 19444 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
09-24 14:24:33.980 10200 19444 19444 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:580)
09-24 14:24:33.980 10200 19444 19444 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:878)
09-24 14:24:33.980 10200 19444 19444 E AndroidRuntime: Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'java.lang.String android.content.SharedPreferences.getString(java.lang.String, java.lang.String)' on a null object reference
09-24 14:24:33.980 10200 19444 19444 E AndroidRuntime: at org.torproject.android.service.util.Prefs.getDefaultLocale(Prefs.java:126)
09-24 14:24:33.980 10200 19444 19444 E AndroidRuntime: at org.torproject.android.service.OrbotService.configLanguage(OrbotService.java:592)
09-24 14:24:33.980 10200 19444 19444 E AndroidRuntime: at org.torproject.android.service.OrbotService.onCreate(OrbotService.java:506)
09-24 14:24:33.980 10200 19444 19444 E AndroidRuntime: at android.app.ActivityThread.handleCreateService(ActivityThread.java:4912)
09-24 14:24:33.980 10200 19444 19444 E AndroidRuntime: ... 9 more
The SharedPreferences seem to be a static field in a helper class that is not initialized when the OrbotService gets started for some reason. See https://github.com/guardianproject/orbot/blob/939ce1d58db6810f51f833cb33dd51235f1eed69/orbotservice/src/main/java/org/torproject/android/service/util/Prefs.java#L50
The prefs are only initialized here: https://github.com/guardianproject/orbot/blob/939ce1d58db6810f51f833cb33dd51235f1eed69/app/src/main/java/org/torproject/android/OrbotApp.kt#L26
which maybe isn't called when invoked from a backup agent?
When backup is set up, should be reproducible when running
adb shell bmgr backupnow org.torproject.android
The docs are saying about Application#onCreate():
Called when the application is starting, before any activity, service, or receiver objects (excluding content providers) have been created.
Implementations should be as quick as possible (for example using lazy initialization of state) since the time spent in this function directly impacts the performance of starting the first activity, service, or receiver in a process.
However, it seems that this isn't always true when services are launched. Maybe a platform bug :shrug:
Yeah, confusing, but something we can address.
Attempt to address at 2eb6841987154bac4ca4802e4ce579ec24d84573