Android system_server无法访问sdcard目录问题记录(Android 4.4 mtk平台)

一、原因

原因:Android具有system权限为什么不可以访问SDcard
官方文档解释

Processes that continue holding open fds on the sdcard a little after it is
requested to be unmounted will be killed so that it can unmount.
We don’t want the system process to be able to access the sdcard to avoid
these kinds of issues (and just general security cleanliness), so that it
does not have permission to access it.

中文翻译

sdcard属于易插拔的外部设备,如果说我们系统app可以访问sdcard,并且一直持有sdcard中相应文件的fds(文件句柄),如果我们sdcard这时候拔除,
这时系统app就有可能因为fds文件句柄没有被killed,但是系统app一般是不可以被killed,因为你想想如果我们的主页launcher被killed了或者其他重要系统app被killed
就有可能导致一系列安全问题,如主页crash或者手机重启等等,也就是我一拔sdcard结果手机死机了的悲剧结果

简单总结就是以前的sdcard卡是可插拔的,如果系统进程去访问sdcard目录,会持有sdcard文件句柄,如果sdcard被拔除,可能会导致系统崩溃,故官方做了这个限制。但是目前的sdcard一般是内置的,不可插拔,一般不会存在这种情况。

二、解决方法

1、方法一

参考链接:【framework】framework中为systemserver添加权限

问题解决思路:查看system_server是否属于sdcard读写相关用户组**
解决过程
  1. 查看sdcard目录信息
    sdcard目录详情

红框标注的地方为所属用户组信息,进程属于这个用户组才能访问sdcard目录

  1. 查看 sdcard_r对应的用户组id

头文件位置:system/core/include/private/android_filesystem_config.h

#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_DRM           1019  /* DRM server */
#define AID_MDNSR         1020  /* MulticastDNSResponder (service discovery) */
#define AID_GPS           1021  /* GPS daemon */
#define AID_UNUSED1       1022  /* deprecated, DO NOT USE */
#define AID_MEDIA_RW      1023  /* internal media storage write access */
#define AID_MTP           1024  /* MTP USB driver access */
#define AID_UNUSED2       1025  /* deprecated, DO NOT USE */
#define AID_DRMRPC        1026  /* group for drm rpc */
#define AID_NFC           1027  /* nfc subsystem */
#define AID_SDCARD_R      1028  /* external storage read access */
#define AID_CLAT          1029  /* clat part of nat464 */
#define AID_LOOP_RADIO    1030  /* loop radio devices */
#define AID_MEDIA_DRM     1031  /* MediaDrm plugins */
#define AID_PACKAGE_INFO  1032  /* access to installed package details */
#define AID_SDCARD_PICS   1033  /* external storage photos access */
#define AID_SDCARD_AV     1034  /* external storage audio/video access */
#define AID_SDCARD_ALL    1035  /* access all users external storage */

#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_NET_BW_STATS  3006  /* read bandwidth statistics */
#define AID_NET_BW_ACCT   3007  /* change bandwidth statistics accounting */
#define AID_NET_BT_STACK  3008  /* bluetooth: access config files */

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

#define AID_APP          10000  /* first app user */

#define AID_ISOLATED_START 99000 /* start of uids for fully isolated sandboxed processes */
#define AID_ISOLATED_END   99999 /* end of uids for fully isolated sandboxed processes */

#define AID_USER        100000  /* offset for uid ranges for each user */

#define AID_SHARED_GID_START 50000 /* start of gids for apps in each user to share */
#define AID_SHARED_GID_END   59999 /* start of gids for apps in each user to share */

由以上头文件可查看到一下这行定义
#define AID_SDCARD_R 1028 /* external storage read access */
所以sdcard_r对应的groud_id 为1028

  1. 查看system_server 进程信息
    ① 查看uid
    查看system_server uid
    ② 查看进程详细信息
    cd proc/1863
    cat status
    system_server进程信息

从上图可以看出system_server并不属于sdcard_r(1028)用户组,所以没有读写sdcard目录的权限,所以system_server在读写sdcard文件的时候会报(Permission denied)错误(不过也可能是别的原因)

  1. 修改system_server 用户组

system_server是由ZygoteInit类负责初始化和启动的,相关的代码在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中。其中关键的启动代码如下。从代码中可以看到,在启动sysetm_server时通过–setgroups为其设置了所属用户组。

private static boolean startSystemServer()
            throws MethodAndArgsCaller, RuntimeException {
        long capabilities = posixCapabilitiesAsBits(
            OsConstants.CAP_KILL,
            OsConstants.CAP_NET_ADMIN,
            OsConstants.CAP_NET_BIND_SERVICE,
            OsConstants.CAP_NET_BROADCAST,
            OsConstants.CAP_NET_RAW,
            OsConstants.CAP_SYS_MODULE,
            OsConstants.CAP_SYS_NICE,
            OsConstants.CAP_SYS_RESOURCE,
            OsConstants.CAP_SYS_TIME,
            OsConstants.CAP_SYS_TTY_CONFIG
        );
        /* Hardcoded command line to start the system server */
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1032,3001,3002,3003,3006,3007",
            "--capabilities=" + capabilities + "," + capabilities,
            "--runtime-init",
            "--nice-name=system_server",
            "com.android.server.SystemServer",
        };
        ZygoteConnection.Arguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteConnection.Arguments(args);
            ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);
            ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);

            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.uid, parsedArgs.gid,
                    parsedArgs.gids,
                    parsedArgs.debugFlags,
                    null,
                    parsedArgs.permittedCapabilities,
                    parsedArgs.effectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) {
            handleSystemServerProcess(parsedArgs);
        }

        return true;
    }

我们可以在--setgroups添加1028(不是固定的,根据实际情况)

添加1028用户组
重新编译framework并烧录验证,可以查看进程信息验证用户组是否添加成功。

1、方法二

解决思路:提高system_server权限
代码路径:dalvik/vm/native/dalvik_system_Zygote.cpp

/*
 * Utility routine to fork zygote and specialize the child process.
 */
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];
    u4 mountMode = MOUNT_EXTERNAL_NONE;
    int64_t permittedCapabilities, effectiveCapabilities;
    char *seInfo = NULL;
    char *niceName = NULL;

    if (isSystemServer) {
        /*
         * Don't use GET_ARG_LONG here for now.  gcc is generating code
         * that uses register d8 as a temporary, and that's coming out
         * scrambled in the child process.  b/3138621
         */
        //permittedCapabilities = GET_ARG_LONG(args, 5);
        //effectiveCapabilities = GET_ARG_LONG(args, 7);
        permittedCapabilities = args[5] | (int64_t) args[6] << 32;
        effectiveCapabilities = args[7] | (int64_t) args[8] << 32;
    } else {
        mountMode = args[5];
        permittedCapabilities = effectiveCapabilities = 0;
        StringObject* seInfoObj = (StringObject*)args[6];
        if (seInfoObj) {
            seInfo = dvmCreateCstrFromString(seInfoObj);
            if (!seInfo) {
                ALOGE("seInfo dvmCreateCstrFromString failed");
                dvmAbort();
            }
        }
        StringObject* niceNameObj = (StringObject*)args[7];
        if (niceNameObj) {
            niceName = dvmCreateCstrFromString(niceNameObj);
            if (!niceName) {
                ALOGE("niceName dvmCreateCstrFromString failed");
                dvmAbort();
            }
        }
    }
    ......

从以上代码分析中可以看到,如果是system_server(isSystemServer)
u4 mountMode = MOUNT_EXTERNAL_NONE;
从代码分析,如果是系统进程的情况下,通过mountMode控制,让系统进程不能访问sdcard目录
(但是海思方案也是这样定义,但是system_sever也能正常访问sdcard目录,可能是底层文件系统不一样导致,还有待研究)

我们再查看mountMode参数枚举,可以看到

//代码位置:dalvik/vm/native/dalvik_system_Zygote.cpp
enum {
    MOUNT_EXTERNAL_NONE = 0,
    MOUNT_EXTERNAL_SINGLEUSER = 1,
    MOUNT_EXTERNAL_MULTIUSER = 2,
    MOUNT_EXTERNAL_MULTIUSER_ALL = 3,
};

我们修改默认的mountMode参数
修改mountMode默认参数

如上图,修改mountMode参数为MOUNT_EXTERNAL_MULTIUSER_ALL,允许所有的用户访问(可能会造成别的问题,谨慎修改),修改完成后单编/整编进行验证。

三、总结

因为在项目中,有个需求是需要在system_server中去读取sdcard文件,发现了system_server竟然不能访问sdcard目录文件,起先感觉到很奇怪,在我们印象中系统进程的权限一般都高于普通应用进程,普通应用都能正常读写,system_server竟然不能?通过查询资料,发现其中端倪,故写此文章记录一下问题,方便以后翻阅。

以上分析属于笔者自己理解如果有错误请大神指出,欢迎转载

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值