欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
【轉】Android 權限控制代碼分析

Android 權限控制代碼分析


前在文章介紹過(guò)android系統管理層次http://blog.csdn.net/andyhuabing/article/details/7030212 ,這里就核心代碼分析一下


android系統充分利用了linux的用戶(hù)權限管理方法,所以如果需要移植到其它系統,這一塊也是一個(gè)相當不小的工作量。那么android系統到底是如何使用這些的有利因素呢?


首先需要知道linux權限的兩個(gè)基本知識:

1、 一個(gè)用戶(hù)可以屬于多個(gè)組.

2、 一個(gè)文件只能屬于某個(gè)組。


這里主要是在AndroidManifest.xml中聲明權限,主要是通過(guò)在AndroidManifest.xml中顯示地聲明應用程序需要的權限,防止應用程序錯誤的使用服務(wù),不恰當訪(fǎng)問(wèn)資源。

Android中每種權限都用一個(gè)獨立的標簽表示.如:

    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

當在安裝(Install) 應用程序時(shí),Android就會(huì )給予一個(gè)UID。這個(gè)UID可連結到該應用程序的 AndroidManifest.xml檔案的內容。所User在安裝你的應用程序時(shí),在屏幕上的窗口里可以檢視這個(gè) AndroidManifest.xml檔案的內容。在檢視時(shí),用戶(hù)會(huì )看到你對應用程序的目的、權限等說(shuō)明。當你接受這支程序的意圖、權限說(shuō)明之后,Android就安裝它,并給它一個(gè)UID。萬(wàn)一在你的應用程序執行期間有越軌(企圖做出非權限范圍)的行為時(shí),用戶(hù)將會(huì )得到Android的警告訊息。

下面是兩個(gè)安裝程序安裝時(shí)的界面



這兩個(gè)應用其實(shí)代碼是一樣的,唯一的不同就是它們的AndroidManifest.xml,圖2AndroidManifest.xml中多了如下內容:

<uses-permission android:name="android.permission.RECORD_AUDIO" />

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

即需要使用存儲設備和錄音設備,在安裝的時(shí)候,就會(huì )提示用戶(hù)它需要的權限。Android里面是怎么去控制的呢?


在安裝apk的時(shí)候,會(huì )解析這個(gè)AndroidManifest.xml,把相應的信息保存起來(lái)。

代碼路徑:frameworks\base\core\java\android\content\pm\PackageParser.java

最終調用的是private Package parsePackage(

        Resources res, XmlResourceParser parser, int flags, String[] outError)

這個(gè)函數,在里面對AndroidManifest.xml進(jìn)行了解析,其中就有

    private Package parsePackage(
        Resources res, XmlResourceParser parser, int flags, String[] outError)
        throws XmlPullParserException, IOException {

       ... 

      String tagName = parser.getName();
      if (tagName.equals("application")) {
       ...
      } else if (tagName.equals("permission-group")) {
          if (parsePermissionGroup(pkg, res, parser, attrs, outError) == null) {
              return null;
          }
      } else if (tagName.equals("permission")) {
          if (parsePermission(pkg, res, parser, attrs, outError) == null) {
              return null;
          }
      } else if (tagName.equals("permission-tree")) {
          if (parsePermissionTree(pkg, res, parser, attrs, outError) == null) {
              return null;
          }
      } else if (tagName.equals("uses-permission")) {
          sa = res.obtainAttributes(attrs,
                  com.android.internal.R.styleable.AndroidManifestUsesPermission);

          // Note: don't allow this value to be a reference to a resource
          // that may change.
          String name = sa.getNonResourceString(
                  com.android.internal.R.styleable.AndroidManifestUsesPermission_name);

          sa.recycle();

          if (name != null && !pkg.requestedPermissions.contains(name)) {
              pkg.requestedPermissions.add(name.intern());
          }

          XmlUtils.skipCurrentTag(parser);
      }

     ...

   }


這里對它使用的權限進(jìn)行了解析。

這里保存的都是"android.permission.WRITE_EXTERNAL_STORAGE"這樣的字符串,在解析完后,會(huì )調用grantPermissionsLP函數獲取對應的group_id,

代碼路徑:frameworks\base\services\java\com\android\server\PackageManagerService.java

private void grantPermissionsLP(PackageParser.Package pkg, boolean replace) {
...
    if (allowed) {
        if (!gp.grantedPermissions.contains(perm)) {
            changedPermission = true;
            gp.grantedPermissions.add(perm);
            gp.gids = appendInts(gp.gids, bp.gids);

        } else if (!ps.haveGids) {
            gp.gids = appendInts(gp.gids, bp.gids);
        }
    } else {
        Slog.w(TAG, "Not granting permission " + perm
                + " to package " + pkg.packageName
                + " because it was previously installed without");
    }
                
...
}

這里把相應的組都保存到了gids中。

當應用程序啟動(dòng)的過(guò)程中會(huì )調用

private final void startProcessLocked(ProcessRecord app,

            String hostingType, String hostingNameStr)

代碼路徑:frameworks\base\services\java\com\android\server\am\ActivityManagerService.java

private final void startProcessLocked(ProcessRecord app,
        String hostingType, String hostingNameStr) {
...
    try {
        int uid = app.info.uid;
        int[] gids = null;
        try {
            gids = mContext.getPackageManager().getPackageGids(
                    app.info.packageName);

        } catch (PackageManager.NameNotFoundException e) {
            Slog.w(TAG, "Unable to retrieve gids", e);
        }
        
...
    int pid = Process.start("android.app.ActivityThread",
          mSimpleProcessManagement ? app.processName : null, uid, uid,
          gids, debugFlags, null);        

}


這里就是獲取前面保存的gids,再后面調用創(chuàng )建了一個(gè)新的進(jìn)程,這里傳的參數就有g(shù)ids

創(chuàng )建新進(jìn)程利用jni最終調用 forkAndSpecializeCommon 函數 (路徑:\dalvik\vm\native\dalvik_system_Zygote.c)


static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer)
{
    pid_t pid;


    uid_t uid = (uid_t) args[0];
    gid_t gid = (gid_t) args[1];
    ArrayObject* gids = (ArrayObject *)args[2];
    u4 debugFlags = args[3];
    ArrayObject *rlimits = (ArrayObject *)args[4];
    int64_t permittedCapabilities, effectiveCapabilities;
...
    pid = fork();
    if (pid == 0) {
        int err;
        /* The child process */
    
        err = setgroupsIntarray(gids);

        if (err < 0) {
            LOGE("cannot setgroups(): %s", strerror(errno));
            dvmAbort();
        }

        err = setrlimitsFromArray(rlimits);

        if (err < 0) {
            LOGE("cannot setrlimit(): %s", strerror(errno));
            dvmAbort();
        }


        err = setgid(gid);
        if (err < 0) {
            LOGE("cannot setgid(%d): %s", gid, strerror(errno));
            dvmAbort();
        }

        err = setuid(uid);
        if (err < 0) {
            LOGE("cannot setuid(%d): %s", uid, strerror(errno));
            dvmAbort();
        }        
        ...
}


我們看到在子進(jìn)程里調用setgroupsIntarray設置該進(jìn)程所屬的組,這樣它就擁有了該組的權限。也通過(guò)setgid及setuid決定了應用程序的uid及gid值。

舉個(gè)例子:

我們新建一Android工程,讀取其應用的uid/gid值,貼入如下代碼:

try{

        java.lang.Process process = Runtime.getRuntime().exec("id");

        InputStream input = process.getInputStream();

        byte[] bytes = new byte[1204];

        int len;

        while((len = (input.read(bytes))) > 0)

        {

        System.out.print(new String(bytes, 0, len)); 

        }

        input.close();

這里運行運行linuxid命令的代碼,id命令的功能是輸出當前用戶(hù)的uid,主要的group id和所在的group

在其AndroidManifest.xml添加如下權限:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

運行后看log里面有:


這里面就有groups=1015


再看下android_filesystem_config.h里面

代碼路徑:

system\core\include\private

有如下代碼

#define AID_ROOT             0  /* traditional unix root user */

#define AID_SYSTEM        1000  /* system server */

#define AID_RADIO         1001  /* telephony subsystem, RIL */
#define AID_BLUETOOTH     1002  /* bluetooth subsystem */
#define AID_GRAPHICS      1003  /* graphics devices */

...

#define AID_WIFI          1010  /* wifi subsystem */
#define AID_ADB           1011  /* android debug bridge (adbd) */
#define AID_INSTALL       1012  /* group for installing packages */
#define AID_MEDIA         1013  /* mediaserver process */
#define AID_DHCP          1014  /* dhcp client */
#define AID_SDCARD_RW     1015  /* external storage write access */


再看下platform.xml

路徑:frameworks\base\data\etc

有如下配置

<permission name="android.permission.WRITE_EXTERNAL_STORAGE" >

        <group gid="sdcard_rw" />

</permission>

這樣就把android.permission.WRITE_EXTERNAL_STORAGE 、"sdcard_rw"、以及 1015關(guān)聯(lián)起來(lái)了


我們再看下當sd卡掛載上去后目錄的權限:

ls -l

drwxr-xr-x root     system            1970-01-01 08:00 obb

drwxr-xr-x root     system            1970-01-01 08:00 asec

drwx------ root     root              1970-01-01 08:00 secure

d---rwxr-x system   sdcard_rw          2012-03-29 17:11 sdcard

可以看到對于sd卡,組用戶(hù)具有讀寫(xiě)權限,而我們的應用也加入了這個(gè)組,這樣它就可以操作sdcard了。


當一個(gè)應用需要操作sdcard而沒(méi)有在AndroidManifest.xml添加相應的權限時(shí),就不能成功完成。

以下是同一個(gè)程序,一個(gè)有在AndroidManifest.xml添加WRITE_EXTERNAL_STORAGE權限,一個(gè)沒(méi)有,它們的對比,可以看到由于沒(méi)有權限程序運行異常了。


對于管理權限的xml文件補充說(shuō)明一下:

源代碼中權限文件位于: frameworks\base\data\etc 下面,鏡像生成在 system\etc\permissions\platform.xml中

文件權限讀取點(diǎn):

readPermissions @ PackageManagerService.java

    void readPermissions() {
        // Read permissions from .../etc/permission directory.
        File libraryDir = new File(Environment.getRootDirectory(), "etc/permissions");

        if (!libraryDir.exists() || !libraryDir.isDirectory()) {
            Slog.w(TAG, "No directory " + libraryDir + ", skipping");
            return;
        }
        if (!libraryDir.canRead()) {
            Slog.w(TAG, "Directory " + libraryDir + " cannot be read");
            return;
        }

        // Iterate over the files in the directory and scan .xml files
        for (File f : libraryDir.listFiles()) {
            // We'll read platform.xml last
            if (f.getPath().endsWith("etc/permissions/platform.xml")) {
                continue;
            }



            if (!f.getPath().endsWith(".xml")) {
                Slog.i(TAG, "Non-xml file " + f + " in " + libraryDir + " directory, ignoring");
                continue;
            }
            if (!f.canRead()) {
                Slog.w(TAG, "Permissions library file " + f + " cannot be read");
                continue;
            }

            readPermissionsFromXml(f);
        }

        // Read permissions from .../etc/permissions/platform.xml last so it will take precedence
        final File permFile = new File(Environment.getRootDirectory(),
                "etc/permissions/platform.xml");
        readPermissionsFromXml(permFile);

    }


platform.xml 的重要性在于:

<!-- This file is used to define the mappings between lower-level system
     user and group IDs and the higher-level permission names managed
     by the platform.


     Be VERY careful when editing this file!  Mistakes made here can open
     big security holes.
-->

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
從NDK在非Root手機上的調試原理探討Android的安全機制
Android的安全設計與架構
Android沙箱機制
AndroidManifest.xml的作用
Android權限申請的學(xué)習實(shí)踐
保護你的隱私,五種控制Android應用的權限的方法
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久