[[project @ 2]
koushd**20090106022154
Ignore-this: 74934f2b69b243a765b06e0f24275853
Initial commit.
] adddir ./Superuser
addfile ./Superuser/.classpath
addfile ./Superuser/.project
addfile ./Superuser/AndroidManifest.xml
adddir ./Superuser/assets
adddir ./Superuser/res
adddir ./Superuser/res/drawable
addfile ./Superuser/res/drawable/icon.png
adddir ./Superuser/res/layout
addfile ./Superuser/res/layout/main.xml
addfile ./Superuser/res/layout/superuserrequest.xml
addfile ./Superuser/res/layout/whitelistitem.xml
adddir ./Superuser/res/raw
addfile ./Superuser/res/raw/su
adddir ./Superuser/res/values
addfile ./Superuser/res/values/strings.xml
adddir ./Superuser/src
adddir ./Superuser/src/koushikdutta
adddir ./Superuser/src/koushikdutta/superuser
addfile ./Superuser/src/koushikdutta/superuser/R.java
addfile ./Superuser/src/koushikdutta/superuser/SuperuserActivity.java
addfile ./Superuser/src/koushikdutta/superuser/SuperuserRequestActivity.java
adddir ./su
addfile ./su/Android.mk
addfile ./su/MODULE_LICENSE_APACHE2
addfile ./su/su.c
hunk ./Superuser/.classpath 1
+
+
+
+
+
+
hunk ./Superuser/.project 1
+
+
+ Superuser
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
hunk ./Superuser/AndroidManifest.xml 1
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
binary ./Superuser/res/drawable/icon.png
oldhex
*
newhex
*89504e470d0a1a0a0000000d49484452000000300000003008060000005702f987000000046741
*4d410000b18f0bfc61050000001874455874536f667477617265005061696e742e4e4554207633
*2e3336a9e7e225000001c4494441546843ed5ac10dc2300c2ccbc0002cc02ef063033e88372bc0
*0a5d8229e832604b45042be462a781425da94228b6e3d817e71c9835159ef9be3991d945607add
*1d9aeedd54243fa7b173307e25f94d05d7f24c92431dbdb7fe7debf8c31ac9ed0279d6dbe5cd54
*418a265f0a672e681a92bf089d25d2a9361e89e6114da6cd18b257341e89e62a65d092b1220791
*b2369a8e7f1451cd3845732b36e3cfe1bf150b981cfe61c6348850c9f2693a40fd4f664ce59056
*d8f14fa7b1366859f214d9555fab99afa4de17fe43b247202f373cd38994fd6d96c3522872d03c
*48daa73f6d19f2053c697569c6cc19e0d395f1997a43e7782fa0fd22f1cf3a680e6e92867f2c6c
*9274e40246c5ff6137a565acc3873db0a8eda62c2776ed0568fb5fc95861c6aa2dc0f14fb717d5
*a29b63585b4dfe11ff3fc7ff551d5b0e0acc3211fe0fabc9d8eabfea34fd28fefbcd89b889e4ff
*88ff9c44cb89f84f5b028fd0b9521669d5b797588155ab03a57ad35e00c2b316ff72c3f3773407
*ac6aa63d62e43f7eff6f8a764c29c2ff2777ff5907db392972fc8f80ffcb6ae2f8cf81ee20328e
*7fc77f2190b4dd54e456fbabf59f7fff0a1b1c78d14af2dcc0843afc8f147f6404eebc93fef738
*45f7430000000049454e44ae426082
hunk ./Superuser/res/layout/main.xml 1
+
+
+
+
+
+
+
+
hunk ./Superuser/res/layout/superuserrequest.xml 1
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
hunk ./Superuser/res/layout/whitelistitem.xml 1
+
+
+
+
+
+
+
+
+
+
+
binary ./Superuser/res/raw/su
oldhex
*
newhex
*7f454c460101010000000000000000000200280001000000008700003400000020120000020000
*0434002000060028001500140001000070c00b0000c08b0000c08b000020000000200000000400
*00000400000006000000340000003480000034800000c0000000c0000000050000000400000003
*000000f4000000f4800000f4800000130000001300000004000000010000000100000000000000
*0080000000800000e00b0000e00b00000500000000100000010000000010000000900000009000
*006401000068010000060000000010000002000000201000002090000020900000e8000000e800
*000006000000040000002f73797374656d2f62696e2f6c696e6b6572000011000000220000000a
*0000001a0000001d00000019000000080000001800000015000000000000000600000021000000
*17000000140000000d0000001c0000001f0000000c000000200000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000900
*00000100000003000000000000000000000007000000040000000000000000000000120000000f
*0000000b0000001000000000000000050000000e0000001b000000110000000200000016000000
*130000001e00000000000000000000000000000000000000b10000002486000020000000120000
*005c0000003086000074010000120000001f010000e08b0000000000001000f1ff7b0000000000
*00000400000011000000c7000000000000001800000012000000a90000003c8600000c00000012
*0000005a01000068910000000000001000f1ff0c010000488600005000000012000000eb000000
*54860000cc00000012000000f20000006086000038000000120000004b01000064910000000000
*001000f1ff11010000c08b0000000000001000f1ff6a0000006c860000b8000000120000002b00
*0000788600001c00000012000000ba000000848600001c00000012000000590100006891000000
*0000001000f1fff8000000908600000000000012000000c200000000000000fc00000011000000
*060100009c86000024000000120000003f01000064910000000000001000f1ffde000000a88600
*0000000000120000006501000068910000000000001000f1ff47000000b48600004c0000001200
*000037000000c08600000c00000012000000e6000000cc86000000000000120000003801000064
*910000000000001000f1ff2601000068910000000000001000f1ffa4000000d886000010000000
*120000008d0000000000000018000000120000006d01000000000800000000001000f1ff2b0100
*0064910000000000001000f1ffff000000e486000000000000120000004f000000f08600000c02
*000012000000006c696273716c6974652e736f006c6962632e736f006c6962737464632b2b2e73
*6f006c69626d2e736f005f5f6c6962635f696e69740073716c697465335f6f70656e5f76320073
*7072696e74660073716c697465335f657865630073716c697465335f636c6f7365005f5f737461
*636b5f63686b5f6661696c005f5f737461636b5f63686b5f6775617264005f5f61656162695f75
*6e77696e645f6370705f7072310061746f69005f5f6572726e6f007374726572726f7200667072
*696e7466005f5f7346005f5f61656162695f756e77696e645f6370705f70723000676574707069
*6400737461740073797374656d00736c6565700073657467696400736574756964006578656376
*0070757473005f5f65786964785f7374617274005f5f65786964785f656e64005f5f646174615f
*7374617274005f6564617461005f5f6273735f7374617274005f5f6273735f73746172745f5f00
*5f5f6273735f656e645f5f005f5f656e645f5f005f737461636b005c9100001504000060910000
*15120000149100001601000018910000160200001c910000160600002091000016080000249100
*001609000028910000160a00002c910000160d000030910000160e000034910000160f00003891
*0000161100003c910000161300004091000016150000449100001617000048910000161800004c
*9100001619000050910000161c00005491000016200000589100001621000004e02de504e09fe5
*0ee08fe008f0bee5e80a000000c68fe200ca8ce2e8fabce500c68fe200ca8ce2e0fabce500c68f
*e200ca8ce2d8fabce500c68fe200ca8ce2d0fabce500c68fe200ca8ce2c8fabce500c68fe200ca
*8ce2c0fabce500c68fe200ca8ce2b8fabce500c68fe200ca8ce2b0fabce500c68fe200ca8ce2a8
*fabce500c68fe200ca8ce2a0fabce500c68fe200ca8ce298fabce500c68fe200ca8ce290fabce5
*00c68fe200ca8ce288fabce500c68fe200ca8ce280fabce500c68fe200ca8ce278fabce500c68f
*e200ca8ce270fabce500c68fe200ca8ce268fabce500c68fe200ca8ce260fabce5000000000d00
*a0e10010a0e304208fe204308fe2d8ffffeab20000ea0090000008900000109000001890000000
*00a0e10000a0e170b5214d214c2249ad44224d224869447d442a592818136802220b6006a90023
*fff7b6ef061c00281cd11c4b1c4807ace9182a58201cfff7a6ef1a49069804966a1803ab05ae21
*1c03900096fff7b8ef069b002801d0181c05e0181cfff750ef049803e00698fff74cef0020074e
*ac59074d6d442a6823689a4201d0fff75eef8421c9008d4470bde0fbffff540000001c040000c4
*090000e8f8ffff28f9ffff5c000000d1f6ffff70b51c4e141c1c4d1c4a7e44ad44051cb0581b49
*036869440b60a068fff770ef6860021c2368012808dc164c16491a1c6c447118201cfff752ef05
*e0134803ac3118201cfff74aef28680c4d0023211c00220093fff760ef094a745900206a441668
*23689e4201d0fff714ef812109018d4470bd22090000f0f7ffff540000000c0800000c04000058
*f9ffff80f9ffff30b581b0051cfff7e6ee0068fff7d6ee084c0949094a7c44031c6058a418211c
*2a1ca830fff7faeefff7d4ee006801b0404230bd8608000058000000b0f9fffff0b5414d414c42
*4ead44424d00af78607d4428596a4639600368f351ba60fff7f0ee3d4a3d49f860bc186918fa68
*201cfff7ecee391c201c1031fff7f4ee3848bb6a2e183360fff71fff00281dd135493c1c7c3469
*183268201cfb68fff7d6ee201cfff7a4ee002801d02f4834e000240120fff7a2eefff707ff0028
*05dc00282ed101340a2c2bd0f2e70020fff7acee002825d1fff7d2ee002821d17c686946a30012
*33de08f200204e891aa300aa1958500a603c688d460a1c0434012002e040cc013016607b680432
*9842f8db18482818fff790ee15482818fff771ff04e0144c2819fff75cee0120084eb968aa598d
*460749cd5913689d4201d0fff762ee0d4cbd46a544f0bd7cfaffff540000007c0500004c080000
*7c040000c4f9ffff5c000000d0f9ffff68faffff90faffff84faffff6cfaffff8405000000c09f
*e51cff2fe1a98800002f646174612f646174612f6b6f757368696b64757474612e737570657275
*7365722f6461746162617365732f7375706572757365722e73716c6974650000000073656c6563
*74202a2066726f6d2077686974656c697374207768657265205f69643d2564206c696d69742031
*3b00000064656c6574652066726f6d2077686974656c697374207768657265205f69643d272573
*273b0000007570646174652077686974656c6973742073657420636f756e743d25642077686572
*65205f69643d272573273b00000073753a2025732e204572726f723a25730a0000002f70726f63
*2f256400000000616d207374617274202d6120616e64726f69642e696e74656e742e616374696f
*6e2e4d41494e202d6e206b6f757368696b64757474612e7375706572757365722f6b6f75736869
*6b64757474612e7375706572757365722e53757065727573657252657175657374416374697669
*7479202d2d656920756964202564202d2d656920706964202564203e202f6465762f6e756c6c00
*000000616d2e0073753a207065726d697373696f6e2064656e6965640000002f73797374656d2f
*62696e2f7368000087b20181b0b0aa010000000083b20181b0b0aa0300000000b2970181b0ab01
*e00000000070fbff7fd8ffff7f10fcff7fdcffff7f98fcff7fb0a90080d0fcff7fd8ffff7f0000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*00ffffffff00000000ffffffff00000000ffffffff00000000ffffffff00000000010000000100
*0000010000000e0000000100000016000000010000002300000020000000009000002100000008
*00000019000000089000001b000000080000001a000000109000001c0000000800000004000000
*0881000005000000fc83000006000000dc8100000a000000740100000b00000010000000150000
*000000000003000000089100000200000090000000140000001100000017000000808500001100
*000070850000120000001000000013000000080000000000000000000000000000000000000000
*000000000000000000000000000000000000000000000000000000000000002090000000000000
*000000001086000010860000108600001086000010860000108600001086000010860000108600
*001086000010860000108600001086000010860000108600001086000010860000108600000000
*000000000000410f0000006165616269000105000000002e726f64617461002e73687374727461
*62002e41524d2e6578746162002e64796e616d6963002e68617368002e64796e73796d002e696e
*74657270002e64796e737472002e41524d2e61747472696275746573002e63746f7273002e6273
*73002e72656c2e706c74002e72656c2e676f74002e74657874002e41524d2e6578696478002e66
*696e695f6172726179002e696e69745f6172726179002e707265696e69745f6172726179000000
*000000000000000000000000000000000000000000000000000000000000000000000000000000
*350000000100000002000000f4800000f400000013000000000000000000000001000000000000
*002700000005000000020000000881000008010000d40000000300000000000000040000000400
*00002d0000000b00000002000000dc810000dc0100002002000004000000000000000400000010
*0000003d0000000300000002000000fc830000fc03000074010000000000000000000001000000
*000000006a00000009000000020000007085000070050000100000000300000011000000040000
*000800000061000000090000000200000080850000800500009000000003000000070000000400
*0000080000006500000001000000060000001086000010060000ec000000000000000000000004
*000000040000007300000001000000060000000087000000070000f00200000000000000000000
*1000000000000000010000000100000032000000f0890000f0090000ac01000000000000000000
*0004000000010000001300000001000000020000009c8b00009c0b000024000000000000000000
*00000400000000000000790000000100007082000000c08b0000c00b0000200000000800000000
*00000004000000000000009c000000100000000300000000900000001000000800000000000000
*000000000100000000000000900000000e00000003000000089000000810000008000000000000
*00000000000100000000000000840000000f000000030000001090000010100000080000000000
*000000000000010000000000000055000000010000000300000018900000181000000800000000
*0000000000000001000000000000001e00000006000000030000002090000020100000e8000000
*040000000000000004000000080000006e000000010000000300000008910000081100005c0000
*00000000000000000004000000040000005c000000080000000300000064910000641100000400
*000000000000000000000400000000000000450000000300007000000000000000006411000010
*000000000000000000000001000000000000000900000003000000000000000000000074110000
*ab00000000000000000000000100000000000000
hunk ./Superuser/res/values/strings.xml 1
+
+
+
+ Superuser
+Superuser permissions grants the application full (root) access to all the phone's capabilties.
+Superuser Permissions
+
hunk ./Superuser/src/koushikdutta/superuser/R.java 1
+/* AUTO-GENERATED FILE. DO NOT MODIFY.
+ *
+ * This class was automatically generated by the
+ * aapt tool from the resource data it found. It
+ * should not be modified by hand.
+ */
+
+package koushikdutta.superuser;
+
+public final class R {
+ public static final class attr {
+ }
+ public static final class drawable {
+ public static final int icon=0x7f020000;
+ }
+ public static final class id {
+ public static final int AlwaysButton=0x7f060007;
+ public static final int EmptyWhitelistText=0x7f060001;
+ public static final int LinearLayout01=0x7f060000;
+ public static final int LinearLayout02=0x7f060008;
+ public static final int NoButton=0x7f060006;
+ public static final int ScrollView01=0x7f060002;
+ public static final int WhitelistItemText=0x7f060009;
+ public static final int WhitelistPackageText=0x7f06000a;
+ public static final int YesButton=0x7f060005;
+ public static final int requestorprocesses=0x7f060004;
+ public static final int requestoruid=0x7f060003;
+ }
+ public static final class layout {
+ public static final int main=0x7f030000;
+ public static final int superuserrequest=0x7f030001;
+ public static final int whitelistitem=0x7f030002;
+ }
+ public static final class raw {
+ public static final int su=0x7f040000;
+ }
+ public static final class string {
+ public static final int app_name=0x7f050000;
+ public static final int superuser_permissions_description=0x7f050001;
+ public static final int superuser_permissions_name=0x7f050002;
+ }
+}
hunk ./Superuser/src/koushikdutta/superuser/SuperuserActivity.java 1
-
+package koushikdutta.superuser;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import android.app.ListActivity;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteOpenHelper;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.CursorAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
+import android.widget.AdapterView.OnItemLongClickListener;
+
+public class SuperuserActivity extends ListActivity
+{
+ LayoutInflater mInflater;
+ ListView mListView;
+ WhitelistAdapter mAdapter;
+ TextView mEmptyText;
+ SQLiteDatabase mDatabase;
+ Cursor mCursor;
+
+ protected static class DatabaseHelper extends SQLiteOpenHelper
+ {
+ public DatabaseHelper(Context context)
+ {
+ super(context, "superuser.sqlite", null, 1);
+ }
+
+ @Override
+ public void onCreate(SQLiteDatabase db)
+ {
+ String ddlWhitelist = "create table whitelist (_id integer primary key, name text, count integer);";
+ db.execSQL(ddlWhitelist);
+ }
+
+ @Override
+ public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
+ {
+ }
+ }
+
+ public class WhitelistAdapter extends CursorAdapter
+ {
+ public WhitelistAdapter(Context context, Cursor c)
+ {
+ super(context, c);
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor)
+ {
+ TextView whitelistPackageText = (TextView) view.findViewById(R.id.WhitelistPackageText);
+ int uid = cursor.getInt(0);
+ String packageName = cursor.getString(1);
+ whitelistPackageText.setText(packageName);
+ TextView whitelistItemText = (TextView) view.findViewById(R.id.WhitelistItemText);
+ whitelistItemText.setText("User ID: " + new Integer(uid).toString());
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent)
+ {
+ View view = mInflater.inflate(R.layout.whitelistitem, null);
+ bindView(view, context, cursor);
+ return view;
+ }
+ }
+
+ /** Called when the activity is first created. */
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+
+ prepareSu();
+
+ mEmptyText = (TextView) findViewById(R.id.EmptyWhitelistText);
+ mListView = (ListView) findViewById(android.R.id.list);
+ mInflater = getLayoutInflater();
+
+ DatabaseHelper hlp = new DatabaseHelper(this);
+ mDatabase = hlp.getWritableDatabase();
+
+ refreshCursor();
+
+ Toast toast = Toast.makeText(this, "Click and hold an application to to remove it from the whitelist", Toast.LENGTH_LONG);
+ toast.show();
+
+ mListView.setOnItemLongClickListener(new OnItemLongClickListener()
+ {
+ @Override
+ public boolean onItemLongClick(AdapterView> parent, View view, int position, long id)
+ {
+ mCursor.moveToPosition(position);
+ int uid = mCursor.getInt(0);
+ String command = "delete from whitelist where _id=" + uid + ";";
+ mDatabase.execSQL(command);
+ refreshCursor();
+ return true;
+ }
+ });
+
+ updateEmptyText();
+ }
+
+ private void refreshCursor()
+ {
+ mCursor = mDatabase.query(false, "whitelist", new String[] { "_id", "name" }, null, null, null, null, null, null);
+ mAdapter = new WhitelistAdapter(this, mCursor);
+ setListAdapter(mAdapter);
+ updateEmptyText();
+ }
+
+ private void updateEmptyText()
+ {
+ mEmptyText.setVisibility(mCursor.getCount() != 0 ? View.GONE : View.VISIBLE);
+ }
+
+ public static int getUidForPackage(String packageName) throws Exception
+ {
+ // parse the uid given a package name (which should be visible in ps)
+ Process p = Runtime.getRuntime().exec("ps");
+ InputStream reader = p.getInputStream();
+ Thread.sleep(200);
+ byte[] buff = new byte[10000];
+ int read = reader.read(buff, 0, buff.length);
+ String str = new String(buff);
+ String pattern = String.format("app_(\\d+).*?%s", packageName);
+ Pattern regex = Pattern.compile(pattern);
+ Matcher match = regex.matcher(str);
+ if (match.find())
+ return Integer.parseInt(match.group(1)) + 10000;
+
+ throw new Exception("Unable to determine uid for package");
+ }
+
+ private static void remountFileSystem(String suCommand) throws Exception
+ {
+ // this function remounts the file system for permission changes with either su or superuser, depending on whether
+ // superuser is set up already or not
+ String command = String.format("echo \"mount -oremount,rw /dev/block/mtdblock3 /system\" | %s\nexit\n", suCommand);
+ Process p = Runtime.getRuntime().exec("sh");
+ OutputStream writer = p.getOutputStream();
+ writer.write(command.getBytes("ASCII"));
+ Thread.sleep(500);
+ }
+
+ private void prepareSu()
+ {
+ try
+ {
+ File su = new File("/system/bin/su");
+ if (!su.exists())
+ {
+ Toast toast = Toast.makeText(this, "Unable to find /system/bin/su.", Toast.LENGTH_LONG);
+ toast.show();
+ return;
+ }
+
+ InputStream suStream = getResources().openRawResource(R.raw.su);
+
+ if (su.length() == suStream.available())
+ {
+ suStream.close();
+ return;
+ }
+
+ File superuser = new File("/system/bin/superuser");
+
+ if (superuser.exists())
+ {
+ // return device to original state
+ Process process = Runtime.getRuntime().exec("superuser");
+ DataOutputStream os = new DataOutputStream(process.getOutputStream());
+
+ os.writeBytes("mount -oremount,rw /dev/block/mtdblock3 /system\n");
+ os.writeBytes("busybox cp /system/bin/superuser /system/bin/su\n");
+ os.writeBytes("busybox chown 0:0 /system/bin/su\n");
+ os.writeBytes("chmod 4755 /system/bin/su\n");
+ os.writeBytes("rm /system/bin/superuser\n");
+ os.writeBytes("exit\n");
+ os.flush();
+ }
+
+ byte[] bytes = new byte[suStream.available()];
+ DataInputStream dis = new DataInputStream(suStream);
+ dis.readFully(bytes);
+ FileOutputStream suOutStream = new FileOutputStream("/data/data/koushikdutta.superuser/su");
+ suOutStream.write(bytes);
+ suOutStream.close();
+
+ Process process = Runtime.getRuntime().exec("su");
+ DataOutputStream os = new DataOutputStream(process.getOutputStream());
+ os.writeBytes("mount -oremount,rw /dev/block/mtdblock3 /system\n");
+ os.writeBytes("busybox cp /data/data/koushikdutta.superuser/su /system/bin/su\n");
+ os.writeBytes("busybox chown 0:0 /system/bin/su\n");
+ os.writeBytes("chmod 4755 /system/bin/su\n");
+ os.writeBytes("exit\n");
+ os.flush();
+ }
+ catch (Exception e)
+ {
+ Toast toast = Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG);
+ toast.show();
+ }
+ }
+}
hunk ./Superuser/src/koushikdutta/superuser/SuperuserRequestActivity.java 1
+package koushikdutta.superuser;
+
+import java.io.InputStream;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.database.Cursor;
+import android.database.sqlite.SQLiteDatabase;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+import android.widget.TextView;
+import android.widget.Toast;
+
+public class SuperuserRequestActivity extends Activity
+{
+ Button mYesButton;
+ Button mNoButton;
+ Button mAlwaysButton;
+ Intent mIntent;
+ SQLiteDatabase mDatabase;
+ int mUid;
+ int mPid;
+ String mName;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.superuserrequest);
+
+ Button yesButton = (Button) findViewById(R.id.YesButton);
+ Button noButton = (Button) findViewById(R.id.NoButton);
+ Button alwaysButton = (Button) findViewById(R.id.AlwaysButton);
+ mIntent = getIntent();
+
+ mUid = mIntent.getIntExtra("uid", -1);
+ mPid = mIntent.getIntExtra("pid", -1);
+
+ if (mUid == -1 || mPid == -1)
+ {
+ Toast toast = Toast.makeText(this, "This intent requires two int parameters: uid pid", Toast.LENGTH_LONG);
+ toast.show();
+ mIntent.putExtra("superuserresult", false);
+ setResult(RESULT_CANCELED, mIntent);
+ finish();
+ return;
+ }
+
+ try
+ {
+ if (mUid >= 10000)
+ {
+ Process p = Runtime.getRuntime().exec("ps");
+ InputStream reader = p.getInputStream();
+ Thread.sleep(200);
+ byte[] buff = new byte[10000];
+ int read = reader.read(buff, 0, buff.length);
+ String str = new String(buff);
+ int id = mUid - 10000;
+ String pattern = String.format("app_%d+(.*?)\n", id);
+ Pattern regex = Pattern.compile(pattern);
+ Matcher match = regex.matcher(str);
+ mName = "";
+ while (match.find())
+ {
+ String[] strings = match.group(1).split(" ");
+ mName += strings[strings.length -1] + "\n";
+ }
+
+ TextView nameText = (TextView) findViewById(R.id.requestorprocesses);
+ mName = mName.replace("'","");
+ nameText.setText(mName);
+ }
+ }
+ catch (Exception e)
+ {
+ Toast toast = Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG);
+ toast.show();
+ finish();
+ return;
+ }
+
+ TextView packageText = (TextView) findViewById(R.id.requestoruid);
+ packageText.setText("User ID: " + mUid);
+
+ // check whitelist
+ mDatabase = new SuperuserActivity.DatabaseHelper(this).getWritableDatabase();
+ Cursor c = mDatabase.query("whitelist", new String[] { "_id", "name" }, "_id = " + mUid, null, null, null, null);
+
+ yesButton.setOnClickListener(new OnClickListener()
+ {
+ @Override
+ public void onClick(View v)
+ {
+ String delete = String.format("delete from whitelist where _id=%d;", mUid);
+ mDatabase.execSQL(delete);
+ String whitelistCommand = String.format("insert into whitelist values (%d, '%s', %d);", mUid, mName, 1);
+ mDatabase.execSQL(whitelistCommand);
+ finish();
+ }
+ });
+
+ noButton.setOnClickListener(new OnClickListener()
+ {
+ @Override
+ public void onClick(View v)
+ {
+ String delete = String.format("delete from whitelist where _id=%d;", mUid);
+ mDatabase.execSQL(delete);
+ String whitelistCommand = String.format("insert into whitelist values (%d, '%s', %d);", mUid, mName, -1);
+ mDatabase.execSQL(whitelistCommand);
+ finish();
+ }
+ });
+
+ alwaysButton.setOnClickListener(new OnClickListener()
+ {
+ @Override
+ public void onClick(View v)
+ {
+ String delete = String.format("delete from whitelist where _id=%d;", mUid);
+ mDatabase.execSQL(delete);
+ String whitelistCommand = String.format("insert into whitelist values (%d, '%s', %d);", mUid, mName, 10000);
+ mDatabase.execSQL(whitelistCommand);
+ finish();
+ }
+ });
+ }
+}
hunk ./su/Android.mk 1
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= su.c
+
+LOCAL_MODULE:= su
+
+LOCAL_STATIC_LIBRARIES := libc
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
+LOCAL_MODULE_TAGS := debug tests
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/../../../external/sqlite/dist \
+ $(LOCAL_PATH)/../../../external/sqlite/android
+
+LOCAL_SHARED_LIBRARIES := \
+ libsqlite
+
+include $(BUILD_EXECUTABLE)
hunk ./su/su.c 1
+/*
+**
+** Copyright 2008, 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.
+*/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+
+#include
+
+#define DBPATH "/data/data/koushikdutta.superuser/databases/superuser.sqlite"
+
+static int g_puid;
+
+static void printRow(int argc, char** argv, char** azColName)
+{
+ int i;
+ for (i = 0; i < argc; i++)
+ {
+ printf("%s: %s\n", azColName[i], argv[i]);
+ }
+}
+
+typedef struct whitelistCallInfo whitelistCallInfo;
+struct whitelistCallInfo
+{
+ sqlite3* db;
+ int count;
+};
+
+static int whitelistCallback(void *data, int argc, char **argv, char **azColName)
+{
+ whitelistCallInfo* callInfo = (whitelistCallInfo*)data;
+ // note the count
+ int count = atoi(argv[2]);
+ callInfo->count = count;
+ // remove whitelist entries that are expired
+ if (count - 1 <= 0)
+ {
+ char remove[1024];
+ sprintf(remove, "delete from whitelist where _id='%s';", argv[0]);
+ sqlite3_exec(callInfo->db, remove, NULL, NULL, NULL);
+ return 0;
+ }
+
+ char update[1024];
+ sprintf(update, "update whitelist set count=%d where _id='%s';", count, argv[0]);
+ sqlite3_exec(callInfo->db, update, NULL, NULL, NULL);
+ return 0;
+}
+
+static int checkWhitelist()
+{
+ sqlite3 *db;
+ int rc = sqlite3_open_v2(DBPATH, &db, SQLITE_OPEN_READWRITE, NULL);
+ if (!rc)
+ {
+ char *errorMessage;
+ char query[1024];
+ sprintf(query, "select * from whitelist where _id=%d limit 1;", g_puid);
+ struct whitelistCallInfo callInfo;
+ callInfo.count = 0;
+ callInfo.db = db;
+ rc = sqlite3_exec(db, query, whitelistCallback, &callInfo, &errorMessage);
+ if (rc != SQLITE_OK)
+ {
+ sqlite3_close(db);
+ return 0;
+ }
+ sqlite3_close(db);
+ return callInfo.count;
+ }
+ sqlite3_close(db);
+ return 0;
+}
+
+static int executionFailure(char *context)
+{
+ fprintf(stderr, "su: %s. Error:%s\n", context, strerror(errno));
+ return -errno;
+}
+
+static int permissionDenied()
+{
+ // the superuser activity couldn't be started
+ printf("su: permission denied\n");
+ return 1;
+}
+
+int main(int argc, char **argv)
+{
+ struct stat stats;
+ struct passwd *pw;
+ int uid = 0;
+ int gid = 0;
+
+ int ppid = getppid();
+ char szppid[256];
+ sprintf(szppid, "/proc/%d", ppid);
+ stat(szppid, &stats);
+ g_puid = stats.st_uid;
+
+ // lets make sure the caller is allowed to execute this
+ if (!checkWhitelist())
+ {
+ char sysCmd[1024];
+ sprintf(sysCmd, "am start -a android.intent.action.MAIN -n koushikdutta.superuser/koushikdutta.superuser.SuperuserRequestActivity --ei uid %d --ei pid %d > /dev/null", g_puid, ppid);
+ if (system(sysCmd))
+ return executionFailure("am.");
+
+ int found = 0;
+ int i;
+ for (i = 0; i < 10; i++)
+ {
+ sleep(1);
+ // 0 means waiting for user input
+ // > 0 means yes/always
+ // < 0 means no
+ int checkResult = checkWhitelist();
+ if (checkResult > 0)
+ {
+ found = 1;
+ break;
+ }
+ else if (checkResult < 0)
+ {
+ // user hit no
+ return permissionDenied();
+ }
+ }
+
+ if (!found)
+ return permissionDenied();
+ }
+
+ if(setgid(gid) || setuid(uid))
+ return permissionDenied();
+
+ char *exec_args[argc + 1];
+ exec_args[argc] = NULL;
+ exec_args[0] = "sh";
+ int i;
+ for (i = 1; i < argc; i++)
+ {
+ exec_args[i] = argv[i];
+ }
+ execv("/system/bin/sh", exec_args);
+ return executionFailure("sh");
+}
+