From 93ce2986e020130da1f40197039edd68704b3707 Mon Sep 17 00:00:00 2001 From: Adam Shanks Date: Mon, 2 Jan 2012 15:11:53 +0000 Subject: [PATCH 01/45] Check that the socket comes from the right UID to prevent forged sockets --- .../noshufou/android/su/SuRequestActivity.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/com/noshufou/android/su/SuRequestActivity.java b/src/com/noshufou/android/su/SuRequestActivity.java index 3a612008..3a008b3c 100644 --- a/src/com/noshufou/android/su/SuRequestActivity.java +++ b/src/com/noshufou/android/su/SuRequestActivity.java @@ -27,7 +27,10 @@ import android.content.IntentFilter; import android.content.IntentFilter.MalformedMimeTypeException; import android.content.SharedPreferences; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager.NameNotFoundException; import android.graphics.Color; +import android.net.Credentials; import android.net.LocalSocket; import android.net.LocalSocketAddress; import android.nfc.NdefMessage; @@ -119,6 +122,18 @@ public void onCreate(Bundle savedInstanceState) { mSocket = new LocalSocket(); mSocket.connect(new LocalSocketAddress(socketPath, LocalSocketAddress.Namespace.FILESYSTEM)); + Credentials creds= mSocket.getPeerCredentials(); + ApplicationInfo appInfo; + try { + appInfo = getPackageManager().getApplicationInfo(getPackageName(), 0); + } catch (NameNotFoundException e) { + Log.e(TAG, "Divided by zero..."); + return; + } + if (creds.getUid() != appInfo.uid || creds.getGid() != appInfo.uid) { + throw new SecurityException("Potential forged socket"); + } + readRequestDetails(); } catch (IOException e) { // If we can't connect to the socket, there's no point in // being here. Log it and quit From fc6942f400943fdc13c2815a7086cad03baf679e Mon Sep 17 00:00:00 2001 From: Adam Shanks Date: Mon, 2 Jan 2012 15:13:26 +0000 Subject: [PATCH 02/45] Read all data regarding the request directly from the socket instead of the intent This commit requires su-binary version 3.1 or higher. Currently the source for this binary is in the gc branch of the su-binary repository. --- .../android/su/SuRequestActivity.java | 45 ++++++++++++++++--- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/src/com/noshufou/android/su/SuRequestActivity.java b/src/com/noshufou/android/su/SuRequestActivity.java index 3a008b3c..cabd9ebd 100644 --- a/src/com/noshufou/android/su/SuRequestActivity.java +++ b/src/com/noshufou/android/su/SuRequestActivity.java @@ -51,6 +51,7 @@ import android.widget.TextView; import android.widget.ViewFlipper; +import java.io.DataInputStream; import java.io.IOException; import java.io.OutputStream; @@ -89,9 +90,6 @@ public void onCreate(Bundle savedInstanceState) { mPrefs = PreferenceManager.getDefaultSharedPreferences(this); Intent intent = this.getIntent(); - mCallerUid = intent.getIntExtra(SuRequestReceiver.EXTRA_CALLERUID, 0); - mDesiredUid = intent.getIntExtra(SuRequestReceiver.EXTRA_UID, 0); - mDesiredCmd = intent.getStringExtra(SuRequestReceiver.EXTRA_CMD); socketPath = intent.getStringExtra(SuRequestReceiver.EXTRA_SOCKET); mSuVersionCode = intent.getIntExtra(SuRequestReceiver.EXTRA_VERSION_CODE, 0); @@ -117,7 +115,7 @@ public void onCreate(Bundle savedInstanceState) { ((Button)findViewById(R.id.allow)).setOnClickListener(this); ((Button)findViewById(R.id.deny)).setOnClickListener(this); } - + try { mSocket = new LocalSocket(); mSocket.connect(new LocalSocketAddress(socketPath, @@ -260,8 +258,45 @@ public void onClick(View view) { } }; + private void readRequestDetails() throws IOException { + DataInputStream is = new DataInputStream(mSocket.getInputStream()); + + int protocolVersion = is.readInt(); + Log.d(TAG, "INT32:PROTO VERSION = " + protocolVersion); + + int exeSizeMax = is.readInt(); + Log.d(TAG, "UINT32:FIELD7MAX = " + exeSizeMax); + int cmdSizeMax = is.readInt(); + Log.d(TAG, "UINT32:FIELD9MAX = " + cmdSizeMax); + mCallerUid = is.readInt(); + Log.d(TAG, "UINT32:CALLER = " + mCallerUid); + mDesiredUid = is.readInt(); + Log.d(TAG, "UINT32:TO = " + mDesiredUid); + + int exeSize = is.readInt(); + Log.d(TAG, "UINT32:EXESIZE = " + exeSize); + if (exeSize > exeSizeMax) { + throw new IOException("Incomming string bigger than allowed"); + } + byte[] buf = new byte[exeSize]; + is.read(buf); + String callerBin = new String(buf, 0, exeSize - 1); + Log.d(TAG, "STRING:EXE = " + callerBin); + + int cmdSize = is.readInt(); + Log.d(TAG, "UINT32:CMDSIZE = " + cmdSize); + if (cmdSize > cmdSizeMax) { + throw new IOException("Incomming string bigger than allowed"); + } + buf = new byte[cmdSize]; + is.read(buf); + mDesiredCmd = new String(buf, 0, cmdSize - 1); + Log.d(TAG, "STRING:CMD = " + mDesiredCmd); + + } + private void sendResult(boolean allow, boolean remember) { - String resultCode = allow ? "ALLOW" : "DENY"; + String resultCode = allow ? "socket:ALLOW" : "socket:DENY"; if (remember) { ContentValues values = new ContentValues(); From 0efb8bf8b6cafd2a67a29060f4fb79db350b5443 Mon Sep 17 00:00:00 2001 From: Adam Shanks Date: Mon, 2 Jan 2012 16:36:17 +0000 Subject: [PATCH 03/45] Use Holo style for Request window when available --- res/values-v11/styles.xml | 3 +++ res/values/styles.xml | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/res/values-v11/styles.xml b/res/values-v11/styles.xml index f16f9cbb..3de2dba5 100644 --- a/res/values-v11/styles.xml +++ b/res/values-v11/styles.xml @@ -40,4 +40,7 @@ 0dp gone + + - From 46b7a25b6382d35e4dd7230a286636ebc6ef6101 Mon Sep 17 00:00:00 2001 From: Adam Shanks Date: Sun, 5 Feb 2012 18:06:41 +0000 Subject: [PATCH 04/45] Delete backup files --- .gitignore | 1 + res/values-sl/arrays.xml~ | 54 ---------- res/values-sl/strings.xml~ | 216 ------------------------------------- res/values-tr/arrays.xml~ | 54 ---------- res/values-tr/strings.xml~ | 216 ------------------------------------- 5 files changed, 1 insertion(+), 540 deletions(-) create mode 100644 .gitignore delete mode 100644 res/values-sl/arrays.xml~ delete mode 100644 res/values-sl/strings.xml~ delete mode 100644 res/values-tr/arrays.xml~ delete mode 100644 res/values-tr/strings.xml~ diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..496ee2ca --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store \ No newline at end of file diff --git a/res/values-sl/arrays.xml~ b/res/values-sl/arrays.xml~ deleted file mode 100644 index e039dbce..00000000 --- a/res/values-sl/arrays.xml~ +++ /dev/null @@ -1,54 +0,0 @@ - - - - - Poziv - Zavrni - Dovoli - - - prompt - deny - allow - - - Pika - Čustveni simbol - - - dot - emote - - - Sistemsko privzeto - 12/31/2011 - 31/12/2011 - 2011/12/31 - - - default - MM/dd/yyyy - dd/MM/yyyy - yyyy/MM/dd - - - Opozorilno okno - Statusna vrstica - - - toast - status - - - Privzeto - Vrh - Sredina - Dno - - - 0 - 48 - 17 - 80 - - diff --git a/res/values-sl/strings.xml~ b/res/values-sl/strings.xml~ deleted file mode 100644 index 5b448393..00000000 --- a/res/values-sl/strings.xml~ +++ /dev/null @@ -1,216 +0,0 @@ - - - - Superuser - Superuser Request - Home - Dnevnik - Preferences - Extras - aplikacije - dnevnik - Extras - Preferences - Clear - Clear log - Superuser Permissions - Permissions related to Superuser - respond to superuser requests - Allows the application to respond to requests for superuser access. - Read Superuser Data - Allows the application to read data from the Superuser ContentProvider - Write Superuser Data - Allows the application to write data to the Superuser ContentProvider - Recent activity - Da - Ne - Okay - nalaganje - Dovoli - Prekliči - Zavrni - Nastavi - Zapomni - Remembering disabled until su is updated - %1$s kot %2$s (uid: %3$d) - Neznano ime - Dovoljeno - Zavrnjeno - Ustvarjeno - Preklopljeno - Ni aplikacij v seznamu - Ni dnevnikov - Showing %d entries - Last accessed on %1$s at %2$s - Last allowed on %1$s at %2$s - Last denied on %1$s at %2$s - Last toggled on %1$s at %2$s - Created on %1$s at %2$s - Package - App UID - Requested UID - Command - Status - %1$s zahteva Superuser dostop.\n\nČe niste pričeli to dejanje, ali ne razumete te zahteve, je najboljše, da ga zavrnete. - Pritisnite za več informacij - Pritisnite za manj informacij - App - Nastavitve - Security - Use PIN - Permissions prompt will require PIN - Permissions prompt will not require PIN - Change PIN - Access timeout - Apps that are not remembered will have access for %1$d seconds after the prompt - Automatic response - Set the way Superuser handles new requests - Ghost mode - Dial secret code to launch Superuser - Ghost mode deactivated - Ghost mode hides the Superuser icon from the launcher. The icon will be hidden the next time the launcher is restarted. Once the icon is hidden you can access Superuser by dialing a secret code in the dialer. The default secret code is *#*#787378737#*#* (*#*#superuser#*#*), but the digits can be changed.\n\nNote that if your device does not have a dialer, you probably shouldn\'t enable Ghost mode.\n\nEnable Ghost mode? - Ghost mode enabled. Please restart your launcher or reboot your phone to see the change. - Secret code - Secret code is *#*#%1$s#*#* - Apps list - Show status icons - Show icon for status of each app - Do not show icon for status of each app - Status icon type - Style of status icon to show - Show log data - Show log data in App list - Do not show log data in app list - Log - Enable logging - Permission creation and access will be logged - Permission creation and access will not be logged - Delete old log entries - Delete old log entries when limit is reached - Do not delete old log entries when limit is reached - Log entry limit - %1$d log entries - Set the number of log entries to save - Use 24-hour format - Log times will be shown in 24 hour format - Log times will be shown in 12 hour format - Show seconds - Log times will include seconds - Log times will not include seconds - Select date format - Format used to display date in all logs - Clear log - Clearing log - Please wait - Notifications - Notifications - Show notification when an app is granted Su permissions - Do not show notification when an app is granted Su permissions - Notification type - Type of notification to show when an app is granted SU permissions - Toast location - Where the notification will show on the screen - NFC - Use NFC tag to allow - Enter PIN or scan tag to allow - Enter PIN only to allow - Write new allow tag - Zapiši novo oznako, s katero se dovoli - Varnostna kopija/Obnovi - Varnostno kopiranje aplikacij/nastavitev - Varnostna kopija zapisana na SD kartico - Obnovi aplikacije/nastavitve - Preferences restored - Splošno - Superuser v%1$s (%2$d) - Database version %s - Loading su binary version - Su binary v%s - Tap to check for updates - Outdated binary notification - Show notification when binary is outdated - Do not show notification when binary is outdated - Use advanced prompt - Do not show warning on request prompts - Show warning on request prompts - Changelog - Display the changelog - Go Elite! - Buy Elite to unlock all the options - Binary Updater - New version of su binary found. Update now? - Current version already installed. No action required. - Update - Update anyway - That was cool, do it again - Working... - http://downloads.androidsu.com/superuser/su/manifest-legacy.json - http://downloads.androidsu.com/superuser/su/manifest.json - v redu! - fail! - not found - Update failed. Try again? - Napaka pri prenosu manifesta. Preverite internetno povezavo - Try again - su binary updated successfully - Downloading manifest...\u0020 - Parsing manifest...\u0020 - Latest version =\u0020 - Checking installed version =\u0020 - Fixing database...\u0020 - Checking for busybox...\u0020 - Downloading custom busybox...\u0020 - Checking md5sum...\u0020 - Preverjam trenutno namestitveno pot...\u0020 - Downloading new binary...\u0020 - Gaining root access...\u0020 - Remounting /system as rw...\u0020 - Copying su to /system...\u0020 - Changing su file mode to 06755...\u0020 - Premikam su na končno lokacijo...\u0020 - Remounting /system as ro...\u0020 - Cleaning up...\u0020 - Ponovno vpetje sistema samo za branje ni uspelo, prosimo ponovno zaženite telefon za dokončanje posodobitve - Ni bilo mogoče najti trenutno nameščen su binary. Posodobitve ni mogoče nadaljevati - su binary je trenutno nameščen v /sbin. Ni možno izvesti posodobitve. Prosimo poiščite nov ROM za vašo napravo. - This updater is incapable of updating your su binary since it is installed in /sbin. This is not an error in the updater, it is an error on the behalf of your ROM or kernel developer. You can continue to use Superuser with your outdated binary. - This updater cannot update the su binary on phones that have some kind of write protection on the system partition like S-ON. You can continue to use Superuser with your outdated binary, or update su with ROM Manager. - %s has been granted Superuser permissions - %s has been denied Superuser permissions - Your su binary is outdated - su binary outdated - Tap to update su binary - Enter PIN - Enter new PIN - Confirm PIN - PINs don\'t match, try again - Vnesite skrivno kodo - Skeniraj oznako za pisanje - Warning - Apps are market as malicious because they contain elements that indicate they are attempting to grant root access, possibly without your consent. It is highly recommended you uninstall them immediately. - Uninstall - Prezri - Potentially malicious app detected - %s je verjetno zlonamerna. Pritisnite za odstranitev. - deli UID s Superuser - zahteva dovoljenje odziva - zahteva dovoljenje za pisanje v dovoljenja ponudnika - Seznam sprememb - Novosti - - Ena aplikacija in nastavitev obnovljena - %1$d aplikacij in nastavitev obnovljenih - - - En dnevnik izbrisan - %1$d dnevnikov izbrisanih - - - Zadnja priložnost - Napačen vnos - na voljo še %d poskusov - - - Ugotovljeno je bilo, da je naslednji paket zlonameren: - Ugotovljeno je bilo, da so naslednji paketi zlonamerni: - - diff --git a/res/values-tr/arrays.xml~ b/res/values-tr/arrays.xml~ deleted file mode 100644 index 0a29bc53..00000000 --- a/res/values-tr/arrays.xml~ +++ /dev/null @@ -1,54 +0,0 @@ - - - - - Sor - Reddet - İzin ver - - - prompt - deny - allow - - - Nokta - İfade - - - dot - emote - - - Sistem varsayılanı - 12/31/2011 - 31/12/2011 - 2011/12/31 - - - default - MM/dd/yyyy - dd/MM/yyyy - yyyy/MM/dd - - - Kutu - Durum çubuğu - - - toast - status - - - Standart - Üst - Orta - Alt - - - 0 - 48 - 17 - 80 - - diff --git a/res/values-tr/strings.xml~ b/res/values-tr/strings.xml~ deleted file mode 100644 index b5108813..00000000 --- a/res/values-tr/strings.xml~ +++ /dev/null @@ -1,216 +0,0 @@ - - - - Superuser - Superuser İsteği - Ana sayfa - İşlem Kaydı - Tercihler - Ekstralar - uygulamalar - işlem kaydı - Ekstralar - Tercihler - Temizle - İşlem kaydını temizle - Superuser İzinleri - Permissions related to Superuser - respond to superuser requests - Allows the application to respond to requests for superuser access. - Superuser Verisi Oku - Allows the application to read data from the Superuser ContentProvider - Superuser Verisi Yaz - Allows the application to write data to the Superuser ContentProvider - Son etkinlik - Evet - Hayır - Tamam - yükleniyor - İzin ver - İptal - Reddet - Ayarla - Hatırla - Remembering disabled until su is updated - %1$s as %2$s (uid: %3$d) - Bilinmeyen isim - İzin verilen - Reddedildi - Oluşturulma - Toggled - Listede uygulama yok - İşlem kaydı bilgileri yok - Showing %d entries - Last accessed on %1$s at %2$s - Last allowed on %1$s at %2$s - Last denied on %1$s at %2$s - Last toggled on %1$s at %2$s - Created on %1$s at %2$s - Paket - App UID - Requested UID - Komut - Durum - %1$s is requesting Superuser access.\n\nWarning: If you did not initiate this action, or if you do not understand this request, it\'s generally a good idea to deny it. - Tap for more info - Tap for less info - Uygulama - Tercihler - Güvenlik - PIN kullan - Permissions prompt will require PIN - Permissions prompt will not require PIN - PIN\'i Değiştir - Access timeout - Apps that are not remembered will have access for %1$d seconds after the prompt - Otomatik yanıt - Set the way Superuser handles new requests - Hayalet modu - Dial secret code to launch Superuser - Hayalet modu devre dışı - Ghost mode hides the Superuser icon from the launcher. The icon will be hidden the next time the launcher is restarted. Once the icon is hidden you can access Superuser by dialing a secret code in the dialer. The default secret code is *#*#787378737#*#* (*#*#superuser#*#*), but the digits can be changed.\n\nNote that if your device does not have a dialer, you probably shouldn\'t enable Ghost mode.\n\nEnable Ghost mode? - Ghost mode enabled. Please restart your launcher or reboot your phone to see the change. - Gizli kod - Gizli kod: *#*#%1$s#*#* - Uygulama listesi - Durum simgeleri göster - Show icon for status of each app - Do not show icon for status of each app - Durum simgesi türü - Style of status icon to show - İşlem kaydını göster - Uygulama listesinde işlem kaydını göster - Uygulama listesinde işlem kaydını gösterme - İşlem Kaydı - İşlem kaydını etkinleştir - İzin oluşturma ve erişimi kaydedilecek - İzin oluşturma ve erişimi kaydedilmeyecek - Eski işlem kaydı girileirini sil - Limite ulaşıldığında eski işlem kaydı girilerini sil - Do not delete old log entries when limit is reached - İşlem kaydı giri limiti - %1$d log entries - Kaydedilecek işlem kaydı giri sayısını ayarla - 24 Saatlik biçimi kullan - Kayıtlar 24 saat formatında gösterilecek - Kayıtlar 12 saat formatında gösterilecek - Saniyeleri göster - İşlem kaydı zamanları saniyeleri içerecek - İşlem kaydı zamanları saniyeleri içermeyecek - Tarih biçimini seçin - Format used to display date in all logs - İşlem kaydını temizle - İşlem kaydı temizleniyor - Lütfen bekleyin - Bildirimler - Bildirimler - Uygulamaya root yetkisi verilince bildirim göster - Uygulamaya root yetkisi verilince bildirim gösterme - Bildirim türü - Type of notification to show when an app is granted SU permissions - Toast location - Where the notification will show on the screen - NFC - Use NFC tag to allow - Enter PIN or scan tag to allow - Enter PIN only to allow - Write new allow tag - Write a new tag to be used to allow - Backup/Restore - Backup apps/preferences - Backup written to sdcard - Restore apps/preferences - Preferences restored - General - Superuser v%1$s (%2$d) - Veritabanı sürümü %s - Loading su binary version - su dosyası v%s - Güncelleştirmeleri denetlemek için dokunun - Outdated binary notification - Show notification when binary is outdated - Do not show notification when binary is outdated - Use advanced prompt - Do not show warning on request prompts - Show warning on request prompts - Dğişiklik Listesi - Değişiklik listesini görüntüle - Go Elite! - Buy Elite to unlock all the options - Binary Updater - su dosyasının yeni versiyonu bulundu. Şimdi Güncelle? - Güncel sürüm zaten yüklü. Herhangi bir işlem gerekli değil. - Güncelle - Yine de güncelle - Güzeldi, tekrar yap - Çalışıyor ... - http://downloads.androidsu.com/superuser/su/manifest-legacy.json - http://downloads.androidsu.com/superuser/su/manifest.json - tamam! - başarısız! - not found - Güncelleme başarısız. Tekrar deneyin? - Failed to download manifest. Check internet connection - Tekrar deneyin - su dosyası başarıyla güncelleştirildi - Downloading manifest...\u0020 - Parsing manifest...\u0020 - Latest version =\u0020 - Checking installed version =\u0020 - Fixing database...\u0020 - Checking for busybox...\u0020 - Downloading custom busybox...\u0020 - Checking md5sum...\u0020 - Checking current install path...\u0020 - Downloading new binary...\u0020 - Gaining root access...\u0020 - Remounting /system as rw...\u0020 - Copying su to /system...\u0020 - Changing su file mode to 06755...\u0020 - Moving su to it\'s final location...\u0020 - Remounting /system as ro...\u0020 - Cleaning up...\u0020 - Failed to remount the system as read-only, please reboot to finish the update - Yüklenmiş su dosyası bulunamıyor. Güncelleme devam edemez - Bu güncelleyici su dosyaları /sbin klasöründe yüklü olduğu için güncelleme yapamıyor. Lütfen cihazınız için yeni bir ROM bulun. - This updater is incapable of updating your su binary since it is installed in /sbin. This is not an error in the updater, it is an error on the behalf of your ROM or kernel developer. You can continue to use Superuser with your outdated binary. - This updater cannot update the su binary on phones that have some kind of write protection on the system partition like S-ON. You can continue to use Superuser with your outdated binary, or update su with ROM Manager. - %s has been granted Superuser permissions - %s has been denied Superuser permissions - su dosyanız eski - su dosyası eski - su dosyasını güncellemek için dokunun - Enter PIN - Enter new PIN - PIN\'i Onayla - PINs don\'t match, try again - Gizli kodu girin - Scan tag to write - Uyarı - Apps are market as malicious because they contain elements that indicate they are attempting to grant root access, possibly without your consent. It is highly recommended you uninstall them immediately. - Uninstall - Ignore - Kötü amaçlı olabilecek uygulama tespit edildi - %s is probably malicious. Tap to uninstall. - shares UID with Superuser - requests respond permission - requests permission to write to permissions provider - Dğişiklik Listesi - Neler Yeni - - One app and preferences restored - %1$d apps and preferences restored - - - One log deleted - %1$d logs deleted - - - Son şans - Nope - %d tries left - - - The following package was found to be malicious: - The following packages were found to be malicious: - - From 793459b39f1c7f0cc5df92a011df53196a63b5ca Mon Sep 17 00:00:00 2001 From: Gavin Chapman Date: Tue, 31 Jan 2012 17:34:07 +0000 Subject: [PATCH 05/45] Fix superuser build to be same as market version Change-Id: I42a57e29ee4cec0a55582f209aa7e7936216cd7e --- Android.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Android.mk b/Android.mk index f322fee0..cbef431e 100644 --- a/Android.mk +++ b/Android.mk @@ -5,6 +5,8 @@ LOCAL_STATIC_JAVA_LIBRARIES := libarity android-support-v4 LOCAL_PACKAGE_NAME := Superuser LOCAL_SRC_FILES := $(call all-java-files-under,src) +LOCAL_AAPT_INCLUDE_ALL_RESOURCES := true + LOCAL_CERTIFICATE := superuser include $(BUILD_PACKAGE) From 172a13e442525b415523e6d5112a0eaff0dd68c3 Mon Sep 17 00:00:00 2001 From: Pawit Pornkitprasan Date: Fri, 27 Jan 2012 23:44:28 +0700 Subject: [PATCH 06/45] Superuser: Fix FC when checking for su binary update Proguard strips out UpdaterFragment because it was never referenced from code. This patch adds a proguard flag file to prevent that. Change-Id: I8d884d81cb6729a46a2dcaf0da1a68dbb4eef651 --- Android.mk | 1 + proguard.flags | 1 + 2 files changed, 2 insertions(+) create mode 100644 proguard.flags diff --git a/Android.mk b/Android.mk index cbef431e..3826f88d 100644 --- a/Android.mk +++ b/Android.mk @@ -4,6 +4,7 @@ include $(CLEAR_VARS) LOCAL_STATIC_JAVA_LIBRARIES := libarity android-support-v4 LOCAL_PACKAGE_NAME := Superuser LOCAL_SRC_FILES := $(call all-java-files-under,src) +LOCAL_PROGUARD_FLAG_FILES := proguard.flags LOCAL_AAPT_INCLUDE_ALL_RESOURCES := true diff --git a/proguard.flags b/proguard.flags new file mode 100644 index 00000000..6bcc1e19 --- /dev/null +++ b/proguard.flags @@ -0,0 +1 @@ +-keep class com.noshufou.android.su.UpdaterFragment From 5dc278376076b7fa474594257242e38903795d7f Mon Sep 17 00:00:00 2001 From: Adam Shanks Date: Sun, 12 Feb 2012 14:29:47 +0000 Subject: [PATCH 07/45] Fix ANR caused by faulty date calculation in DateIndexer --- .../android/su/widget/DateIndexer.java | 81 +++++++++++++++---- 1 file changed, 64 insertions(+), 17 deletions(-) diff --git a/src/com/noshufou/android/su/widget/DateIndexer.java b/src/com/noshufou/android/su/widget/DateIndexer.java index 8dbae143..3be186f7 100644 --- a/src/com/noshufou/android/su/widget/DateIndexer.java +++ b/src/com/noshufou/android/su/widget/DateIndexer.java @@ -1,17 +1,17 @@ package com.noshufou.android.su.widget; import java.text.SimpleDateFormat; +import java.util.Calendar; import java.util.GregorianCalendar; import android.content.Context; import android.database.Cursor; -import android.util.Log; import android.widget.SectionIndexer; import com.noshufou.android.su.util.Util; public class DateIndexer implements SectionIndexer { - private static final String TAG = "Su.DateIndexer"; +// private static final String TAG = "Su.DateIndexer"; private Cursor mCursor; private int mColumnIndex; @@ -32,9 +32,11 @@ public DateIndexer(Context context, Cursor cursor, int sortedColumnIndex) { mCursor.moveToLast(); long lastDateLong = mCursor.getLong(mColumnIndex); - int firstDateInt = Integer.parseInt(mIntFormat.format(firstDateLong)); - int lastDateInt = Integer.parseInt(mIntFormat.format(lastDateLong)); - mSectionCount = (firstDateInt - lastDateInt) + 1; + Calendar startDate = Calendar.getInstance(); + startDate.setTimeInMillis(lastDateLong); + Calendar endDate = Calendar.getInstance(); + endDate.setTimeInMillis(firstDateLong); + mSectionCount = daysBetween(startDate, endDate); mSections = new String[mSectionCount]; mSectionDates = new int[mSectionCount]; @@ -64,10 +66,10 @@ public int getPositionForSection(int section) { } if (mSectionPositions[section] > 0) { - return mSectionPositions[section]; + return mSectionPositions[section]; } - int start = 0; + int start = section; int end = mCursor.getCount(); for (int i = section - 1; i > 0; i--) { @@ -80,37 +82,36 @@ public int getPositionForSection(int section) { int savedCursorPos = mCursor.getPosition(); long date; int dateInt; + int result = 0; for (int i = start; i < end; i++) { if (mCursor.moveToPosition(i)) { date = mCursor.getLong(mColumnIndex); dateInt = Integer.parseInt(mIntFormat.format(date)); if (mSectionDates[section] >= dateInt) { mSectionPositions[section] = i; - return i; + result = i; + break; } } } mCursor.moveToPosition(savedCursorPos); - - return 0; + return result; } @Override public int getSectionForPosition(int position) { + // Find the date for the position int savedCursorPos = mCursor.getPosition(); mCursor.moveToPosition(position); long date = mCursor.getLong(mColumnIndex); mCursor.moveToPosition(savedCursorPos); + int dateInt = Integer.parseInt(mIntFormat.format(date)); - // Simple linear search since there aren't that many sections. - // May optimize this later if necessary. for (int i = 0; i < mSectionCount; i++) { - if (dateInt == mSectionDates[i]) { - return i; - } + if (dateInt == mSectionDates[i]) { + return i; + } } - // If it wasn't found, something went very wrong. Log it - Log.e(TAG, "Section not found for date " + dateInt); return 0; } @@ -118,5 +119,51 @@ public int getSectionForPosition(int position) { public Object[] getSections() { return mSections; } + + public static int daysBetween(final Calendar startDate, final Calendar endDate) { + Calendar sDate = (Calendar) startDate.clone(); + int daysBetween = 0; + + int y1 = sDate.get(Calendar.YEAR); + int y2 = endDate.get(Calendar.YEAR); + int m1 = sDate.get(Calendar.MONTH); + int m2 = endDate.get(Calendar.MONTH); + + // Year optimization + while (((y2 - y1) * 12 + (m2 - m1)) > 12) { + + // Move to Jan 01 + if (sDate.get(Calendar.MONTH) == Calendar.JANUARY + && sDate.get(Calendar.DAY_OF_MONTH) == + sDate.getActualMinimum(Calendar.DAY_OF_MONTH)) { + daysBetween += sDate.getActualMaximum(Calendar.DAY_OF_YEAR); + sDate.add(Calendar.YEAR, 1); + } else { + int diff = 1 + sDate.getActualMaximum(Calendar.DAY_OF_YEAR) + - sDate.get(Calendar.DAY_OF_YEAR); + sDate.add(Calendar.DAY_OF_YEAR, diff); + daysBetween += diff; + } + y1 = sDate.get(Calendar.YEAR); + } + + // Month optimization + while ((m2 - m1) % 12 > 1) { + daysBetween += sDate.getActualMaximum(Calendar.DAY_OF_MONTH); + sDate.add(Calendar.MONTH, 1); + m1 = sDate.get(Calendar.MONTH); + } + // process the remainder date + while (sDate.before(endDate)) { + sDate.add(Calendar.DAY_OF_MONTH, 1); + daysBetween++; + } + + // Add one more day to include the end date + daysBetween++; + + return daysBetween; + } + } From 1dabbda16320b3d27b6fa3a7f6c2b907c84cf82c Mon Sep 17 00:00:00 2001 From: Adam Shanks Date: Sun, 12 Feb 2012 14:31:55 +0000 Subject: [PATCH 08/45] Clean up LogAdapter --- .../noshufou/android/su/widget/LogAdapter.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/com/noshufou/android/su/widget/LogAdapter.java b/src/com/noshufou/android/su/widget/LogAdapter.java index 8046c5d0..fcdca8d7 100644 --- a/src/com/noshufou/android/su/widget/LogAdapter.java +++ b/src/com/noshufou/android/su/widget/LogAdapter.java @@ -7,9 +7,9 @@ import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; +import android.widget.AbsListView.OnScrollListener; import android.widget.SectionIndexer; import android.widget.TextView; -import android.widget.AbsListView.OnScrollListener; import com.noshufou.android.su.R; import com.noshufou.android.su.provider.PermissionsProvider.Logs; @@ -117,8 +117,7 @@ private void bindSectionHeader(View itemView, int position, boolean displaySecti } else { final int section = getSectionForPosition(position); if (getPositionForSection(section) == position) { - String title = (String)mIndexer.getSections()[section]; - view.setSectionHeader(title); + view.setSectionHeader(getHeaderTitle(position)); } else { view.setDividerVisible(false); view.setSectionHeader(null); @@ -204,10 +203,7 @@ public void configurePinnedHeader(View header, int position, int alpha) { header.setTag(cache); } - int section = getSectionForPosition(position); - - String title = (String)mIndexer.getSections()[section]; - cache.titleView.setText(title); + cache.titleView.setText(getHeaderTitle(position)); if (alpha == 255) { // Opaque, use the default background and original text color @@ -224,5 +220,13 @@ public void configurePinnedHeader(View header, int position, int alpha) { Color.red(textColor), Color.green(textColor), Color.blue(textColor))); } } + + private String getHeaderTitle(int position) { + int savedPosition = mCursor.getPosition(); + mCursor.moveToPosition(position); + String title = Util.formatDate(mContext, mCursor.getLong(LOG_COLUMN_DATE)); + mCursor.moveToPosition(savedPosition); + return title; + } } From 9d2fa0a1cbde450866ad5de44dc8c81c9e1e7265 Mon Sep 17 00:00:00 2001 From: Adam Shanks Date: Sun, 12 Feb 2012 14:50:40 +0000 Subject: [PATCH 09/45] Only read request details from socket if the su binary supports it --- .../android/su/SuRequestActivity.java | 83 ++++++++++--------- 1 file changed, 44 insertions(+), 39 deletions(-) diff --git a/src/com/noshufou/android/su/SuRequestActivity.java b/src/com/noshufou/android/su/SuRequestActivity.java index cabd9ebd..52a65042 100644 --- a/src/com/noshufou/android/su/SuRequestActivity.java +++ b/src/com/noshufou/android/su/SuRequestActivity.java @@ -78,7 +78,6 @@ public class SuRequestActivity extends Activity implements OnClickListener { @Override public void onCreate(Bundle savedInstanceState) { - String socketPath; super.onCreate(savedInstanceState); if (this.getCallingPackage() != null) { @@ -90,8 +89,8 @@ public void onCreate(Bundle savedInstanceState) { mPrefs = PreferenceManager.getDefaultSharedPreferences(this); Intent intent = this.getIntent(); - socketPath = intent.getStringExtra(SuRequestReceiver.EXTRA_SOCKET); - mSuVersionCode = intent.getIntExtra(SuRequestReceiver.EXTRA_VERSION_CODE, 0); + String socketPath = intent.getStringExtra(SuRequestReceiver.EXTRA_SOCKET); + int suVersionCode = intent.getIntExtra(SuRequestReceiver.EXTRA_VERSION_CODE, 0); mUsePin = mPrefs.getBoolean(Preferences.PIN, false); if (mUsePin) { @@ -131,7 +130,7 @@ public void onCreate(Bundle savedInstanceState) { if (creds.getUid() != appInfo.uid || creds.getGid() != appInfo.uid) { throw new SecurityException("Potential forged socket"); } - readRequestDetails(); + readRequestDetails(suVersionCode, intent); } catch (IOException e) { // If we can't connect to the socket, there's no point in // being here. Log it and quit @@ -139,7 +138,7 @@ public void onCreate(Bundle savedInstanceState) { finish(); } - if (mSuVersionCode < 10) { + if (suVersionCode < 10) { Util.showOutdatedNotification(this); } @@ -258,40 +257,46 @@ public void onClick(View view) { } }; - private void readRequestDetails() throws IOException { - DataInputStream is = new DataInputStream(mSocket.getInputStream()); - - int protocolVersion = is.readInt(); - Log.d(TAG, "INT32:PROTO VERSION = " + protocolVersion); - - int exeSizeMax = is.readInt(); - Log.d(TAG, "UINT32:FIELD7MAX = " + exeSizeMax); - int cmdSizeMax = is.readInt(); - Log.d(TAG, "UINT32:FIELD9MAX = " + cmdSizeMax); - mCallerUid = is.readInt(); - Log.d(TAG, "UINT32:CALLER = " + mCallerUid); - mDesiredUid = is.readInt(); - Log.d(TAG, "UINT32:TO = " + mDesiredUid); - - int exeSize = is.readInt(); - Log.d(TAG, "UINT32:EXESIZE = " + exeSize); - if (exeSize > exeSizeMax) { - throw new IOException("Incomming string bigger than allowed"); - } - byte[] buf = new byte[exeSize]; - is.read(buf); - String callerBin = new String(buf, 0, exeSize - 1); - Log.d(TAG, "STRING:EXE = " + callerBin); - - int cmdSize = is.readInt(); - Log.d(TAG, "UINT32:CMDSIZE = " + cmdSize); - if (cmdSize > cmdSizeMax) { - throw new IOException("Incomming string bigger than allowed"); - } - buf = new byte[cmdSize]; - is.read(buf); - mDesiredCmd = new String(buf, 0, cmdSize - 1); - Log.d(TAG, "STRING:CMD = " + mDesiredCmd); + private void readRequestDetails(int suVersion, Intent intent) throws IOException { + if (suVersion > 15) { + DataInputStream is = new DataInputStream(mSocket.getInputStream()); + + int protocolVersion = is.readInt(); + Log.d(TAG, "INT32:PROTO VERSION = " + protocolVersion); + + int exeSizeMax = is.readInt(); + Log.d(TAG, "UINT32:FIELD7MAX = " + exeSizeMax); + int cmdSizeMax = is.readInt(); + Log.d(TAG, "UINT32:FIELD9MAX = " + cmdSizeMax); + mCallerUid = is.readInt(); + Log.d(TAG, "UINT32:CALLER = " + mCallerUid); + mDesiredUid = is.readInt(); + Log.d(TAG, "UINT32:TO = " + mDesiredUid); + + int exeSize = is.readInt(); + Log.d(TAG, "UINT32:EXESIZE = " + exeSize); + if (exeSize > exeSizeMax) { + throw new IOException("Incomming string bigger than allowed"); + } + byte[] buf = new byte[exeSize]; + is.read(buf); + String callerBin = new String(buf, 0, exeSize - 1); + Log.d(TAG, "STRING:EXE = " + callerBin); + + int cmdSize = is.readInt(); + Log.d(TAG, "UINT32:CMDSIZE = " + cmdSize); + if (cmdSize > cmdSizeMax) { + throw new IOException("Incomming string bigger than allowed"); + } + buf = new byte[cmdSize]; + is.read(buf); + mDesiredCmd = new String(buf, 0, cmdSize - 1); + Log.d(TAG, "STRING:CMD = " + mDesiredCmd); + } else { + mCallerUid = intent.getIntExtra(SuRequestReceiver.EXTRA_CALLERUID, 0); + mDesiredUid = intent.getIntExtra(SuRequestReceiver.EXTRA_UID, 0); + mDesiredCmd = intent.getStringExtra(SuRequestReceiver.EXTRA_CMD); + } } From 6612fd183b43f74fdf09563c85b4e4380cb628fb Mon Sep 17 00:00:00 2001 From: Adam Shanks Date: Sun, 12 Feb 2012 14:52:37 +0000 Subject: [PATCH 10/45] Remove unnecessary version code field --- src/com/noshufou/android/su/SuRequestActivity.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/com/noshufou/android/su/SuRequestActivity.java b/src/com/noshufou/android/su/SuRequestActivity.java index 52a65042..e6e42571 100644 --- a/src/com/noshufou/android/su/SuRequestActivity.java +++ b/src/com/noshufou/android/su/SuRequestActivity.java @@ -64,7 +64,6 @@ public class SuRequestActivity extends Activity implements OnClickListener { private int mCallerUid = 0; private int mDesiredUid = 0; private String mDesiredCmd = ""; - private int mSuVersionCode = 0; private boolean mUsePin = false; private int mAttempts = 3; From 261be332642896aef92ce068e4e860448305a76f Mon Sep 17 00:00:00 2001 From: Adam Shanks Date: Sun, 12 Feb 2012 14:55:51 +0000 Subject: [PATCH 11/45] Code cleanup --- src/com/noshufou/android/su/LogFragment.java | 13 ++++++------- .../android/su/provider/PermissionsProvider.java | 4 ++-- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/com/noshufou/android/su/LogFragment.java b/src/com/noshufou/android/su/LogFragment.java index aef57011..d79d6e90 100644 --- a/src/com/noshufou/android/su/LogFragment.java +++ b/src/com/noshufou/android/su/LogFragment.java @@ -1,26 +1,25 @@ package com.noshufou.android.su; -import com.noshufou.android.su.provider.PermissionsProvider.Logs; -import com.noshufou.android.su.widget.LogAdapter; -import com.noshufou.android.su.widget.PinnedHeaderListView; - import android.database.Cursor; import android.os.Bundle; import android.support.v4.app.ListFragment; import android.support.v4.app.LoaderManager; import android.support.v4.content.CursorLoader; import android.support.v4.content.Loader; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; -import android.view.ViewGroup; import android.view.View.OnClickListener; +import android.view.ViewGroup; import android.widget.ListView; import android.widget.TextView; +import com.noshufou.android.su.provider.PermissionsProvider.Logs; +import com.noshufou.android.su.widget.LogAdapter; +import com.noshufou.android.su.widget.PinnedHeaderListView; + public class LogFragment extends ListFragment implements LoaderManager.LoaderCallbacks, FragmentWithLog, OnClickListener { - private static final String TAG = "Su.LogFragment"; +// private static final String TAG = "Su.LogFragment"; private LogAdapter mAdapter = null; private TextView mLogCountTextView = null; diff --git a/src/com/noshufou/android/su/provider/PermissionsProvider.java b/src/com/noshufou/android/su/provider/PermissionsProvider.java index 0f157f76..83ede605 100644 --- a/src/com/noshufou/android/su/provider/PermissionsProvider.java +++ b/src/com/noshufou/android/su/provider/PermissionsProvider.java @@ -15,7 +15,7 @@ ******************************************************************************/ package com.noshufou.android.su.provider; -import com.noshufou.android.su.util.Util; +import java.util.HashMap; import android.content.ContentProvider; import android.content.ContentUris; @@ -32,7 +32,7 @@ import android.text.TextUtils; import android.util.Log; -import java.util.HashMap; +import com.noshufou.android.su.util.Util; public class PermissionsProvider extends ContentProvider { private static final String TAG = "Su.PermissionsProvider"; From a97f7b394ccde53ea6df5acdcd36300e35bd2a7a Mon Sep 17 00:00:00 2001 From: Adam Shanks Date: Sat, 21 Apr 2012 02:01:44 +0100 Subject: [PATCH 12/45] Switch to ActionBarSherlock Use ActionBarSherlock(http://abs.io) to handle the ActionBar on pre ICS/HC devices. Provides a uniform interface across all supported Android versions, but drops support for 1.6. Also update the UpdateFragment to use the new manifest format. Since 1.6 will no longer be supported, there is no need to look for legacy binaries. --- AndroidManifest.xml | 15 +- res/drawable-hdpi/bottom_bar.png | Bin 389 -> 0 bytes res/drawable-large-land/panel_content.9.png | Bin 2839 -> 2867 bytes res/layout-land/fragment_app_details.xml | 39 --- res/layout-large-port/activity_home.xml | 7 - res/layout-large/activity_home.xml | 7 - res/layout-large/fragment_app_details.xml | 100 +++---- res/layout-large/fragment_log.xml | 53 ++-- res/layout/activity_home.xml | 6 - res/layout/activity_preferences.xml | 13 - res/layout/fragment_app_details.xml | 53 ---- res/layout/fragment_updater.xml | 32 +-- res/values-large/styles.xml | 9 + res/values-v11/styles.xml | 17 -- res/values/colors.xml | 1 + res/values/dimens.xml | 1 + res/values/strings.xml | 9 +- res/values/styles.xml | 102 +++---- .../android/su/AppDetailsActivity.java | 4 +- .../android/su/AppDetailsFragment.java | 249 +++++++++--------- .../noshufou/android/su/AppListFragment.java | 27 +- src/com/noshufou/android/su/HomeActivity.java | 112 ++++---- src/com/noshufou/android/su/LogFragment.java | 47 ++-- .../noshufou/android/su/UpdaterActivity.java | 8 +- .../noshufou/android/su/UpdaterFragment.java | 81 +++--- .../su/preferences/PreferencesActivity.java | 62 ++--- src/com/noshufou/android/su/util/Util.java | 11 + 27 files changed, 430 insertions(+), 635 deletions(-) delete mode 100644 res/drawable-hdpi/bottom_bar.png diff --git a/AndroidManifest.xml b/AndroidManifest.xml index ffee3f1d..57520f41 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -20,8 +20,9 @@ android:versionName="3.0.7"> + android:logo="@drawable/ic_logo" + android:hardwareAccelerated="true" + android:debuggable="true"> + android:theme="@style/Theme.Superuser.Details" + android:label="Details" + android:uiOptions="splitActionBarWhenNarrow" /> - - + diff --git a/res/drawable-hdpi/bottom_bar.png b/res/drawable-hdpi/bottom_bar.png deleted file mode 100644 index 1f38f3c805d7da158886d43246c79de241715b04..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 389 zcmeAS@N?(olHy`uVBq!ia0y~yV0-{%2XQa~N#?^7IDnL7iEBhjaDG}zd16s2gJVj5 zQmTSyZen_BP-eHa!HQ5 zh}FASzhYW2zr5!m7Xz=YAH#($3!cwe$FN`l5mwIX52``qYS7SXeyT!P{#vD z<|77$Amd;Q-zHAle?1lr9d1#|{b8Ip^DmRk_vfj1FMJPdaQ W3QJmUe%T5PR|Zd4KbLh*2~7a)Zgm3y diff --git a/res/drawable-large-land/panel_content.9.png b/res/drawable-large-land/panel_content.9.png index 1faa93abf995091d2977c0eefd026e0ec46c28ca..f5647a67e1451ed08b7398a1e2c93739159e9872 100644 GIT binary patch delta 191 zcmbO(wpmQEGr-TCmrII^fq{Y7)59eQNQ2m-9Be?cepCJDjf(YL^>>(r#kn}S_ciR?K`FHCAu{BN$RCo=Pn*6W4y-%JDA&fw|l=d#Wzp$P!8PDbPa delta 162 zcmdliHeF1yGr-TCmrII^fq{Y7)59eQNV5X5Cvxv0zr`{8# zK+#Z77sn8Z%V#GX - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - + + android:layout_weight="1" + android:gravity="center_vertical" + android:paddingLeft="20dp" + android:text="@string/loading" /> + + + + - - - - - - - - - diff --git a/res/layout-large/fragment_log.xml b/res/layout-large/fragment_log.xml index 9ff75431..81a43296 100644 --- a/res/layout-large/fragment_log.xml +++ b/res/layout-large/fragment_log.xml @@ -17,38 +17,21 @@ - - - - - - - - - - \ No newline at end of file + android:paddingLeft="20dp" + android:paddingTop="20dp" + android:paddingRight="20dp" + android:orientation="vertical" + android:background="@drawable/panel_content"> + + + + diff --git a/res/layout/activity_home.xml b/res/layout/activity_home.xml index 48213ee0..81b6208c 100644 --- a/res/layout/activity_home.xml +++ b/res/layout/activity_home.xml @@ -21,12 +21,6 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/res/layout/fragment_updater.xml b/res/layout/fragment_updater.xml index 09e4cfa7..ad291b9e 100644 --- a/res/layout/fragment_updater.xml +++ b/res/layout/fragment_updater.xml @@ -21,24 +21,11 @@ android:layout_height="fill_parent" android:background="@android:color/white"> - - - - - - - - @@ -46,12 +33,12 @@ - - + android:background="@color/title_split_background">