OSDN Git Service

Add settings toggles for superuser global policies: apps only, adb only, apps + adb...
authorKoushik Dutta <koushd@gmail.com>
Mon, 4 Mar 2013 06:41:48 +0000 (22:41 -0800)
committerKoushik Dutta <koushd@gmail.com>
Mon, 4 Mar 2013 06:41:48 +0000 (22:41 -0800)
su: fix binary so Superuser always gets access, even if root is disabled. Obviously need this to reenabled root.
Check superuser binary version.

Change-Id: I39a667a001cb8f1e3e1f2876f4e4c874579cdc81

15 files changed:
Superuser/jni/su/su.c
Superuser/jni/su/su.h
Superuser/res/drawable-hdpi/ic_toggle.png [new file with mode: 0644]
Superuser/res/drawable-hdpi/ic_toggle_dark.png [new file with mode: 0644]
Superuser/res/drawable-mdpi/ic_toggle.png [new file with mode: 0644]
Superuser/res/drawable-mdpi/ic_toggle_dark.png [new file with mode: 0644]
Superuser/res/drawable-xhdpi/ic_toggle.png [new file with mode: 0644]
Superuser/res/drawable-xhdpi/ic_toggle_dark.png [new file with mode: 0644]
Superuser/res/values/attrs.xml
Superuser/res/values/strings.xml
Superuser/res/values/styles.xml
Superuser/src/com/koushikdutta/superuser/SettingsFragmentInternal.java
Superuser/src/com/koushikdutta/superuser/db/SuDatabaseHelper.java
Superuser/src/com/koushikdutta/superuser/util/Settings.java
Superuser/src/com/koushikdutta/superuser/util/SuHelper.java

index 53e36de..e9134ff 100644 (file)
@@ -703,36 +703,43 @@ int main(int argc, char *argv[]) {
     read_options(&ctx);
     user_init(&ctx);
     
-    if (ctx.user.multiuser_mode == MULTIUSER_MODE_OWNER_ONLY && ctx.user.android_user_id != 0) {
-        deny(&ctx);
-    }
-
-    if (access_disabled(&ctx.from)) {
-        LOGD("access_disabled");
-        deny(&ctx);
-    }
-
-    ctx.umask = umask(027);
-
-    if (ctx.from.uid == AID_ROOT || ctx.from.uid == AID_SHELL) {
-        LOGD("Allowing root/shell.");
-        allow(&ctx);
-    }
-
+    // verify superuser is installed
     if (stat(ctx.user.base_path, &st) < 0) {
+        // send to market
         silent_run("am start -d market://details?id=" JAVA_PACKAGE_NAME);
         PLOGE("stat %s", ctx.user.base_path);
         deny(&ctx);
     }
 
+    // odd perms on superuser data dir
     if (st.st_gid != st.st_uid) {
         LOGE("Bad uid/gid %d/%d for Superuser Requestor application",
                 (int)st.st_uid, (int)st.st_gid);
         deny(&ctx);
     }
     
+    // always allow if this is the superuser uid
+    // superuser needs to be able to reenable itself when disabled...
     if (ctx.from.uid == st.st_uid) {
-        // automatically grant the superuser app itself
+        allow(&ctx);
+    }
+
+    // check if superuser is disabled completely
+    if (access_disabled(&ctx.from)) {
+        LOGD("access_disabled");
+        deny(&ctx);
+    }
+
+    // deny if this is a non owner request and owner mode only
+    if (ctx.user.multiuser_mode == MULTIUSER_MODE_OWNER_ONLY && ctx.user.android_user_id != 0) {
+        deny(&ctx);
+    }
+
+    ctx.umask = umask(027);
+
+    // TODO: customizable behavior for shell? It can currently be toggled via settings.
+    if (ctx.from.uid == AID_ROOT || ctx.from.uid == AID_SHELL) {
+        LOGD("Allowing root/shell.");
         allow(&ctx);
     }
 
index b7d3f5f..06717d0 100644 (file)
@@ -67,7 +67,7 @@
 #define xstr(a) str(a)
 #define str(a) #a
 
-#define VERSION_CODE 1
+#define VERSION_CODE 2
 #define VERSION xstr(VERSION_CODE) " " REQUESTOR
 
 #define PROTO_VERSION 1
diff --git a/Superuser/res/drawable-hdpi/ic_toggle.png b/Superuser/res/drawable-hdpi/ic_toggle.png
new file mode 100644 (file)
index 0000000..7875eb0
Binary files /dev/null and b/Superuser/res/drawable-hdpi/ic_toggle.png differ
diff --git a/Superuser/res/drawable-hdpi/ic_toggle_dark.png b/Superuser/res/drawable-hdpi/ic_toggle_dark.png
new file mode 100644 (file)
index 0000000..421344b
Binary files /dev/null and b/Superuser/res/drawable-hdpi/ic_toggle_dark.png differ
diff --git a/Superuser/res/drawable-mdpi/ic_toggle.png b/Superuser/res/drawable-mdpi/ic_toggle.png
new file mode 100644 (file)
index 0000000..c3e8031
Binary files /dev/null and b/Superuser/res/drawable-mdpi/ic_toggle.png differ
diff --git a/Superuser/res/drawable-mdpi/ic_toggle_dark.png b/Superuser/res/drawable-mdpi/ic_toggle_dark.png
new file mode 100644 (file)
index 0000000..1286d8f
Binary files /dev/null and b/Superuser/res/drawable-mdpi/ic_toggle_dark.png differ
diff --git a/Superuser/res/drawable-xhdpi/ic_toggle.png b/Superuser/res/drawable-xhdpi/ic_toggle.png
new file mode 100644 (file)
index 0000000..ae5a24d
Binary files /dev/null and b/Superuser/res/drawable-xhdpi/ic_toggle.png differ
diff --git a/Superuser/res/drawable-xhdpi/ic_toggle_dark.png b/Superuser/res/drawable-xhdpi/ic_toggle_dark.png
new file mode 100644 (file)
index 0000000..f7226eb
Binary files /dev/null and b/Superuser/res/drawable-xhdpi/ic_toggle_dark.png differ
index baaf88e..7cf387f 100644 (file)
@@ -4,6 +4,7 @@
     <attr name="bottomButtonBar" format="reference|color" />
     <attr name="bottomButtonBarText" format="reference|color" />
     
+    <attr name="toggleIcon" format="reference|color" />
     <attr name="multiuserIcon" format="reference|color" />
     <attr name="declaredPermissionsIcon" format="reference|color" />
     <attr name="automaticResponseIcon" format="reference|color" />
index a823bbe..5d96c94 100644 (file)
@@ -76,4 +76,9 @@
     <string name="install_error">There was an error installing Superuser. Please send a log of the error to the developer.</string>
     <string name="install_success">Installation of Superuser was successful.</string>
     <string name="su_binary_outdated">The su binary is out of date.</string>
+    <string name="superuser_access">Superuser Access</string>
+    <string name="disabled">Disabled</string>
+    <string name="apps_only">Apps only</string>
+    <string name="adb_only">ADB only</string>
+    <string name="apps_and_adb">Apps and ADB</string>
 </resources>
index 4bcd58d..429347b 100644 (file)
@@ -17,6 +17,7 @@
         <item name="bottomButtonBar">@null</item>
         <item name="bottomButtonBarText">?android:attr/textColorPrimary</item>
 
+        <item name="toggleIcon">@drawable/ic_toggle_dark</item>
         <item name="multiuserIcon">@drawable/ic_users_dark</item>
         <item name="declaredPermissionsIcon">@drawable/ic_declare_dark</item>
         <item name="automaticResponseIcon">@drawable/ic_alert_dark</item>
@@ -30,6 +31,7 @@
         <item name="bottomButtonBar">@color/background_dark</item>
         <item name="bottomButtonBarText">?android:attr/textColorPrimaryInverse</item>
         
+        <item name="toggleIcon">@drawable/ic_toggle</item>
         <item name="multiuserIcon">@drawable/ic_users</item>
         <item name="declaredPermissionsIcon">@drawable/ic_declare</item>
         <item name="automaticResponseIcon">@drawable/ic_alert</item>
index 16b969f..0e05d85 100644 (file)
@@ -42,47 +42,6 @@ public class SettingsFragmentInternal extends BetterListFragmentInternal {
     protected int getListFragmentResource() {
         return R.layout.settings;
     }
-    
-//    static final int containerId = 100001;
-//    public static class MyPinFragment extends DialogFragment {
-//        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-//            FrameLayout ret =  new FrameLayout(getActivity());
-//            ret.setId(containerId);
-//            return ret;
-//        };
-//        
-//        private int title;
-//        public void setTitle(int title) {
-//            this.title = title;
-//        }
-//
-//        Dialog d;
-//        @Override
-//        public Dialog onCreateDialog(Bundle savedInstanceState) {
-//            d = super.onCreateDialog(savedInstanceState);
-//            d.setTitle(title);
-//            PinView pf = new PinView() {
-//                @Override
-//                public void onCancel() {
-//                    super.onCancel();
-//                    d.dismiss();
-//                }
-//                
-//                @Override
-//                public void onEnter(String password) {
-//                    super.onEnter(password);
-//                    MyPinFragment.this.onEnter(password);
-//                }
-//            };
-//            getChildFragmentManager().beginTransaction().add(containerId, pf).commit();
-//
-//            return d;
-//        }
-//        
-//        public void onEnter(String password) {
-//            d.dismiss();
-//        }
-//    };
 
     ListItem pinItem;
     void confirmPin(final String pin) {
@@ -160,6 +119,64 @@ public class SettingsFragmentInternal extends BetterListFragmentInternal {
     protected void onCreate(Bundle savedInstanceState, View view) {
         super.onCreate(savedInstanceState, view);
         
+        // NOTE to future koush
+        // dark icons use the color #f3f3f3
+        
+        addItem(R.string.security, new ListItem(this, R.string.superuser_access, 0, 0) {
+            void update() {
+                switch (Settings.getSuperuserAccess()) {
+                case Settings.SUPERUSER_ACCESS_ADB_ONLY:
+                    setSummary(R.string.adb_only);
+                    break;
+                case Settings.SUPERUSER_ACCESS_APPS_ONLY:
+                    setSummary(R.string.apps_only);
+                    break;
+                case Settings.SUPERUSER_ACCESS_APPS_AND_ADB:
+                    setSummary(R.string.apps_and_adb);
+                    break;
+                case Settings.SUPERUSER_ACCESS_DISABLED:
+                    setSummary(R.string.disabled);
+                    break;
+                default:
+                    setSummary(R.string.apps_and_adb);
+                    break;
+                }
+            }
+            {
+                update();
+            }
+            
+            @Override
+            public void onClick(View view) {
+                super.onClick(view);
+                
+                AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+                builder.setTitle(R.string.superuser_access);
+                String[] items = new String[] { getString(R.string.disabled), getString(R.string.apps_only), getString(R.string.adb_only), getString(R.string.apps_and_adb) };
+                builder.setItems(items, new OnClickListener() {
+                    @Override
+                    public void onClick(DialogInterface dialog, int which) {
+                        switch (which) {
+                        case 0:
+                            Settings.setSuperuserAccess(Settings.SUPERUSER_ACCESS_DISABLED);
+                            break;
+                        case 1:
+                            Settings.setSuperuserAccess(Settings.SUPERUSER_ACCESS_APPS_ONLY);
+                            break;
+                        case 2:
+                            Settings.setSuperuserAccess(Settings.SUPERUSER_ACCESS_ADB_ONLY);
+                            break;
+                        case 3:
+                            Settings.setSuperuserAccess(Settings.SUPERUSER_ACCESS_APPS_AND_ADB);
+                            break;
+                        }
+                        update();
+                    }
+                });
+                builder.create().show();
+            }
+        }).setAttrDrawable(R.attr.toggleIcon);
+        
         if (Settings.getMultiuserMode(getActivity()) != Settings.MULTIUSER_MODE_NONE) {
             addItem(R.string.security, new ListItem(this, R.string.multiuser_policy, 0) {
                 void update() {
index e7c2ec1..1786549 100644 (file)
@@ -114,6 +114,9 @@ public class SuDatabaseHelper extends SQLiteOpenHelper {
     public static ArrayList<UidPolicy> getPolicies(Context context) {
         ArrayList<UidPolicy> ret = new ArrayList<UidPolicy>();
         SQLiteDatabase db = new SuDatabaseHelper(context).getReadableDatabase();
+        
+        db.delete("uid_policy", "until > 0 and until < ?", new String[] { String.valueOf(System.currentTimeMillis()) });
+        
         Cursor c = db.query("uid_policy", null, null, null, null, null, null);
         try {
             while (c.moveToNext()) {
index 7f1d8eb..fb4d14b 100755 (executable)
@@ -8,6 +8,7 @@ import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.reflect.Method;
 import java.security.MessageDigest;
 
 import android.content.ContentValues;
@@ -307,6 +308,45 @@ public class Settings {
         }
     }
     
+    
+    public static final int SUPERUSER_ACCESS_DISABLED = 0;
+    public static final int SUPERUSER_ACCESS_APPS_ONLY = 1;
+    public static final int SUPERUSER_ACCESS_ADB_ONLY = 2;
+    public static final int SUPERUSER_ACCESS_APPS_AND_ADB = 3;
+    public static int getSuperuserAccess() {
+        try {
+            Class c = Class.forName("android.os.SystemProperties");
+            Method m = c.getMethod("get", String.class);
+            String value = (String)m.invoke(null, "persist.sys.root_access");
+            int val = Integer.valueOf(value);
+            switch (val) {
+            case SUPERUSER_ACCESS_DISABLED:
+            case SUPERUSER_ACCESS_APPS_ONLY:
+            case SUPERUSER_ACCESS_ADB_ONLY:
+            case SUPERUSER_ACCESS_APPS_AND_ADB:
+                return val;
+            default:
+                return SUPERUSER_ACCESS_APPS_AND_ADB;
+            }
+        }
+        catch (Exception e) {
+            return SUPERUSER_ACCESS_APPS_AND_ADB;
+        }
+    }
+    
+    public static void setSuperuserAccess(int mode) {
+        // TODO: fallback to using SystemProperties.set if this has system uid (ie, embedded)
+        try {
+            String command = "setprop persist.sys.root_access " + mode;
+            Process p = Runtime.getRuntime().exec("su");
+            p.getOutputStream().write(command.getBytes());
+            p.getOutputStream().close();
+            p.waitFor();
+        }
+        catch (Exception ex) {
+        }
+    }
+    
     private static final String CHECK_SU_QUIET = "check_su_quiet";
     public static final int getCheckSuQuietCounter(Context context) {
         return getInt(context, CHECK_SU_QUIET, 0);
index 3c1573b..afe65b7 100644 (file)
@@ -15,7 +15,10 @@ public class SuHelper {
             throw new Exception("no data");
         if (!result.contains(context.getPackageName()))
             throw new Exception("unknown su");
-        // TODO: upgrades herp derp
+        
+        String[] parts = result.split(" ");
+        if (!"2".equals(parts[0]))
+            throw new Exception("binary is old");
     }
 
 }