android sdcard文件访问权限与apk应用 userid 访问权限的关系。

时间:2022-06-08 05:39:15


问题:应用在AndroidManifest.xml 文件 申请WRITE_EXTERNAL_STORAGE 权限即可对sdcard 下文件进行操作。

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

应用的用户id 和所属组是什么?

adb shell 查看 sdcard 文件读写执行权限:

dengpei@dengpei-pc:~$ adb shell
# cd /mnt/sdcard
# ls -al |grep "fileForTestRight.txt"
----rwxr-x    1 system   sdcard_rw         0 Jan 18 11:20 fileForTestRight.txt
# whoami
root
#

文件

fileForTestRight.txt

权限:

system     --x

sdcard_r rwx

other        r_x


sdcrad 文件 权限定义由VoId 设置

gingerbread/system/vold/Volume.cpp


int Volume::mountVol() {
dev_t deviceNodes[4];
int n, i, rc = 0;
char errmsg[255];

if (getState() == Volume::State_NoMedia) {
snprintf(errmsg, sizeof(errmsg),
"Volume %s %s mount failed - no media",
getLabel(), getMountpoint());
mVm->getBroadcaster()->sendBroadcast(
ResponseCode::VolumeMountFailedNoMedia,
errmsg, false);
errno = ENODEV;
return -1;
} else if (getState() != Volume::State_Idle) {
errno = EBUSY;
return -1;
}

if (isMountpointMounted(getMountpoint())) {
SLOGW("Volume is idle but appears to be mounted - fixing");
setState(Volume::State_Mounted);
// mCurrentlyMountedKdev = XXX
return 0;
}

n = getDeviceNodes((dev_t *) &deviceNodes, 4);
if (!n) {
SLOGE("Failed to get device nodes (%s)\n", strerror(errno));
return -1;
}

for (i = 0; i < n; i++) {
char devicePath[255];

sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(deviceNodes[i]),
MINOR(deviceNodes[i]));

SLOGI("%s being considered for volume %s\n", devicePath, getLabel());

errno = 0;
setState(Volume::State_Checking);

if (Fat::check(devicePath)) {
if (errno == ENODATA) {
SLOGW("%s does not contain a FAT filesystem\n", devicePath);
continue;
}
errno = EIO;
/* Badness - abort the mount */
SLOGE("%s failed FS checks (%s)", devicePath, strerror(errno));
setState(Volume::State_Idle);
return -1;
}

/*
* Mount the device on our internal staging mountpoint so we can
* muck with it before exposing it to non priviledged users.
*/
errno = 0;
if (Fat::doMount(devicePath, "/mnt/secure/staging", false, false, false,
1000, 1015, 0702, true)) {
SLOGE("%s failed to mount via VFAT (%s)\n", devicePath, strerror(errno));
continue;
}

SLOGI("Device %s, target %s mounted @ /mnt/secure/staging", devicePath, getMountpoint());

protectFromAutorunStupidity();

if (createBindMounts()) {
SLOGE("Failed to create bindmounts (%s)", strerror(errno));
umount("/mnt/secure/staging");
setState(Volume::State_Idle);
return -1;
}

/*
* Now that the bindmount trickery is done, atomically move the
* whole subtree to expose it to non priviledged users.
*/
if (doMoveMount("/mnt/secure/staging", getMountpoint(), false)) {
SLOGE("Failed to move mount (%s)", strerror(errno));
umount("/mnt/secure/staging");
setState(Volume::State_Idle);
return -1;
}
setState(Volume::State_Mounted);
mCurrentlyMountedKdev = deviceNodes[i];
return 0;
}

SLOGE("Volume %s found no suitable devices for mounting :(\n", getLabel());
setState(Volume::State_Idle);

return -1;
}

doMount(devicePath, "/mnt/secure/staging", false, false, false,
1000, 1015, 0702, true)

定义 uid 1000 gid 1015 文件读写执行权限 为 0702
即 075  ---rwxr-x

继续查看:

gingerbread/system/core/include/private/android_filesystem_config.h

/* This is the master Users and Groups config for the platform.
** DO NOT EVER RENUMBER.
*/

#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_INPUT 1004 /* input devices */
#define AID_AUDIO 1005 /* audio devices */
#define AID_CAMERA 1006 /* camera devices */
#define AID_LOG 1007 /* log devices */
#define AID_COMPASS 1008 /* compass device */
#define AID_MOUNT 1009 /* mountd socket */
#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 */
#define AID_VPN 1016 /* vpn system */
#define AID_KEYSTORE 1017 /* keystore subsystem */
#define AID_USB 1018 /* USB devices */
#define AID_GPS 1021 /* GPS daemon */
#define AID_UNUSED1 1022 /* deprecated, DO NOT USE */
#define AID_RFU1 1023 /* RFU */
#define AID_RFU2 1024 /* RFU */
#define AID_NFC 1025 /* nfc subsystem */

#define AID_SHELL 2000 /* adb and debug shell user */
#define AID_CACHE 2001 /* cache access */
#define AID_DIAG 2002 /* access to diagnostic resources */

/* The 3000 series are intended for use as supplemental group id's only.
* They indicate special Android capabilities that the kernel is aware of. */
#define AID_NET_BT_ADMIN 3001 /* bluetooth: create any socket */
#define AID_NET_BT 3002 /* bluetooth: create sco, rfcomm or l2cap sockets */
#define AID_INET 3003 /* can create AF_INET and AF_INET6 sockets */
#define AID_NET_RAW 3004 /* can create raw INET sockets */
#define AID_NET_ADMIN 3005 /* can configure interfaces and routing tables. */

#define AID_MISC 9998 /* access to misc storage */
#define AID_NOBODY 9999

#define AID_APP 10000 /* first app user */

可知 

AID_SYSTEM        1000  /* system server */
AID_SDCARD_RW     1015 /* external storage write access */
AID_APP          10000 /* first app user */


每个 apk 安装时 PackageInstaller 都会分配一个 userid

并记录在

# ls
accounts.db packages.xml
appwidgets.xml password.key
batterystats.bin registered_services
called_pre_boots.dat shared_prefs
cameraCalFile.bin sync
confirmed_package_behavior.authz theme
confirmed_package_behavior.log throttle
customized_icons_1 trafficstats.bin
device_policies.xml uiderrors.txt
dropbox usagestats
entropy.dat wallpaper_info.xml
gesture.key wallpapers
packages.list
# pwd
/data/system
#

package.xml中,同时也包含 uses-permission 信息

<package name="com.pathfindeng.test" codePath="/data/app/com.pathfindeng.test-1.apk" nativeLibraryPath="/data/data/com.pathfindeng.test/lib" flags="268435456" ft="134eed493a0" it="134eeba07a2" ut="134eed49801" version="1" userId="10137">
<sigs count="1">
<cert index="34" />
</sigs>
<perms>
<item name="android.permission.WRITE_EXTERNAL_STORAGE" />
</perms>


查看 data/data/app目录

# pwd
/data/data
# cd com.pathfindeng.test
# ls -al
drwxr-x--x 4 app_137 app_137 4096 Jan 18 11:20 .
drwxrwx--x 175 system system 12288 Jan 18 10:51 ..
drwxr-xr-x 2 system system 4096 Jan 18 11:20 lib
drwxrwx--x 2 app_137 app_137 4096 Jan 18 10:51 shared_prefs
# cd shar*
# ls -al
drwxrwx--x 2 app_137 app_137 4096 Jan 18 10:51 .
drwxr-x--x 4 app_137 app_137 4096 Jan 18 11:20 ..
-rw-rw---- 1 app_137 app_137 112 Jan 18 10:51 MODE_APPEND.xml
-rw-rw---- 1 app_137 app_137 113 Jan 18 10:51 MODE_PRIVATE.xml
-rw-rw-r-- 1 app_137 app_137 120 Jan 18 10:51 MODE_WORLD_READABLE.xml
-rw-rw--w- 1 app_137 app_137 121 Jan 18 10:51 MODE_WORLD_WRITEABLE.xml

可以看出应用id 为137 其实为 10137. 及该用户权限,所属组权限。

该应用主要代码,及manifest文件

AppRightActivity.java

package com.pathfindeng.test;

import java.io.File;
import java.io.IOException;

import android.app.Activity;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;

public class AppRightActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setSharedPreferencesData();

}


public void setSdcardData(){
File sdcard = Environment.getExternalStorageDirectory();

String[] fileNames = sdcard.list();


Log.d("pathfindeng","fileNames.length is "+fileNames.length);


File testRight = new File(sdcard, "fileForTestRight.txt");

if(testRight.exists()){
testRight.delete();
Log.d("pathfindeng","delete file ok");
}else{
try {
testRight.createNewFile();
Log.d("pathfindeng","create file ok");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

Log.d("pathfindeng", testRight.canRead()+""+testRight.canWrite()+""+testRight.canExecute());

}


public void setSharedPreferencesData (){
SharedPreferences mSharedPreferences;
Editor mEditor;
//
mSharedPreferences = getSharedPreferences("MODE_PRIVATE",MODE_PRIVATE);

mEditor = mSharedPreferences.edit();

mEditor.putString("right", "MODE_PRIVATE");

mEditor.commit();

//
mSharedPreferences = getSharedPreferences("MODE_WORLD_READABLE",MODE_WORLD_READABLE);

mEditor = mSharedPreferences.edit();

mEditor.putString("right", "MODE_WORLD_READABLE");

mEditor.commit();

//
mSharedPreferences = getSharedPreferences("MODE_WORLD_WRITEABLE",MODE_WORLD_WRITEABLE);

mEditor = mSharedPreferences.edit();

mEditor.putString("right", "MODE_WORLD_WRITEABLE");

mEditor.commit();

//
mSharedPreferences = getSharedPreferences("MODE_APPEND",MODE_APPEND);

mEditor = mSharedPreferences.edit();

mEditor.putString("right", "MODE_APPEND");

mEditor.commit();

}

/* (non-Javadoc)
* @see android.app.Activity#onResume()
*/
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();

setSdcardData();
}

/* (non-Javadoc)
* @see android.app.Activity#onDestroy()
*/
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}



}

manifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.pathfindeng.test"
android:versionCode="1"
android:versionName="1.0">

<uses-sdk android:minSdkVersion="10" />

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

<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:label="@string/app_name"
android:name=".AppRightActivity" >
<intent-filter >
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

继续查看

/gingerbread/frameworks/base/data/etc/platform.xml

    <permission name="android.permission.WRITE_EXTERNAL_STORAGE" >
<group gid="sdcard_rw" />
</permission>

应用申请
WRITE_EXTERNAL_STORAGE
权限时

即拥有

sdcard_rw
组权限。

所以即可解答开篇提出的问题。