SElinux init.rc 赋予 脚本执行权限

来源:互联网 发布:路由器访客网络是什么 编辑:程序博客网 时间:2024/05/20 16:11

我们前面看到了,可以编写自己的 .te 文件, 定义自己的类型。
目标案例可以参考, 高通或者 mtk 平台下自带的 system\core\init\readme.txt

一、 init.rc

1.1 如何写服务

在android源码根目录下有android/system/core/rootdir/init.rc文件, 有很多地方都有
.rc 文件, 类似 init.target.rc init.usb.rc init.environ.rc.in

注:每个设备下都会有自己对应的init.rc,init.设备名.rc脚本文件

init.rc 该脚本文件中有很多 服务权限的赋予,定义等等,

假设我现在写了一个脚本 my.sh 那么,我需要赋予它权限的,所以就可以在 init.rc 中去定义和赋予

service  usblp_test  /data/setip/my.shoneshotdisabled

oneshot disabled向我们说明了在系统启动的时候这个服务是不会自动启动的,并且该服务的目的是执行/data/setip/init.usblpmod.sh脚本。脚本的内容你可以随便写,只要符合shell语法就可以了

这里。我后面会好好 总结一下 一些 sh脚本的用法等等

书写完 sh 脚本后,需要编译进 android 系统中 比如 system/bin vender/

(1)有几种在模块中的 mk文件中, 要看这个sh是为哪个模块工作的
编译进 system

include $(CLEAR_VARS)LOCAL_MODULE := my.shLOCAL_MODULE_TAGS := optionalLOCAL_MODULE_CLASS := EXECUTABLESLOCAL_SRC_FILES := assets/my.shLOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_EXECUTABLES)include $(BUILD_PREBUILT)

(2)再就是编译的时候 copy file 了

前面是文件源路径,后面的是目的路径PRODUCT_COPY_FILES += \        device/xx/xx/etc/my.sh:system/etc/my.sh

1.2 添加 服务

添加启动动作,使Android在启动时候执行。

init.rc文件末尾处加入以下内容

service mount-usbfs /system/etc/usbfs.sh    class main    user root    group root    oneshotchown root shell /system/etc/usbfs.shchmod 0550 /system/etc/usbfs.sh

其实这里赋予了权限并没有什么用,这里也是转载网上的
为什么?接着查,在查看init.rc的过程中,发现了以下内容:

mount ext4 ext4@system /system ro 原来system分区是以只读的形式进行挂载的,忽略这点了。以只读形式挂载,再怎么赋权限,也是徒劳啊
那为什么相同目录下的 其他sh可以

6.0 /android/system/core/include/private/android_filesystem_config.h
这里定义的,谁对应的谁 比如: AID_SYSTEM - “system”

    #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 */  static const struct android_id_info android_ids[] = {    { "root",          AID_ROOT, },    { "system",        AID_SYSTEM, },    { "radio",         AID_RADIO, },    { "bluetooth",     AID_BLUETOOTH, },    { "graphics",      AID_GRAPHICS, },    { "input",         AID_INPUT, },    { "audio",         AID_AUDIO, },    { "camera",        AID_CAMERA, },    { "log",           AID_LOG, },    { "compass",       AID_COMPASS, },    { "mount",         AID_MOUNT, },    ......

/android/system/core/libcutils/fs_config.c 有对他的定义, 这里就定义了哪些sh 属于哪个权限组了

....#include <errno.h>#include <fcntl.h>#include <stdbool.h>#include <private/android_filesystem_config.h>....static const struct fs_path_config android_dirs[] = {    { 00770, AID_SYSTEM, AID_CACHE,  0, "cache" },    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app" },    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/app-private" },    { 00771, AID_ROOT,   AID_ROOT,   0, "data/dalvik-cache" },    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data/data" },    { 00771, AID_SHELL,  AID_SHELL,  0, "data/local/tmp" },    { 00771, AID_SHELL,  AID_SHELL,  0, "data/local" },    { 01771, AID_SYSTEM, AID_MISC,   0, "data/misc" },    { 00770, AID_DHCP,   AID_DHCP,   0, "data/misc/dhcp" },    { 00771, AID_SHARED_RELRO, AID_SHARED_RELRO, 0, "data/misc/shared_relro" },    { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media" },    { 00775, AID_MEDIA_RW, AID_MEDIA_RW, 0, "data/media/Music" },    { 00771, AID_SYSTEM, AID_SYSTEM, 0, "data" },    { 00750, AID_ROOT,   AID_SHELL,  0, "sbin" },    { 00755, AID_ROOT,   AID_SHELL,  0, "system/bin" },    { 00755, AID_ROOT,   AID_SHELL,  0, "system/vendor" },    { 00755, AID_ROOT,   AID_SHELL,  0, "system/xbin" },    { 00755, AID_ROOT,   AID_ROOT,   0, "system/etc/ppp" },    { 00755, AID_ROOT,   AID_SHELL,  0, "vendor" },    { 00777, AID_ROOT,   AID_ROOT,   0, "sdcard" },    { 00755, AID_ROOT,   AID_ROOT,   0, 0 },static const struct fs_path_config android_files[] = {    { 00440, AID_ROOT,      AID_SHELL,     0, "system/etc/init.goldfish.rc" },    { 00550, AID_ROOT,      AID_SHELL,     0, "system/etc/init.goldfish.sh" },    { 00771, AID_ROOT,      AID_SHELL,    0,   "system/bin/atmel_ts.sh" },    { 00550, AID_ROOT,      AID_SHELL,     0, "system/etc/init.ril" },    { 00550, AID_DHCP,      AID_SHELL,     0, "system/etc/dhcpcd/dhcpcd-run-hooks" },    { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/ppp/*" },    { 00555, AID_ROOT,      AID_ROOT,      0, "system/etc/rc.*" },    { 00444, AID_ROOT,      AID_ROOT,      0, conf_dir + 1 },    { 00444, AID_ROOT,      AID_ROOT,      0, conf_file + 1 },    { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app/*" },    { 00644, AID_MEDIA_RW,  AID_MEDIA_RW,  0, "data/media/*" },    { 00644, AID_SYSTEM,    AID_SYSTEM,    0, "data/app-private/*" },    { 00644, AID_APP,       AID_APP,       0, "data/data/*" },

1)首先了解下在服务启动的流程

  1. 在你的应用中让init.rc中添加的服务启动起来。
    首先了解下在服务启动的流程:
    在设备目录下的init.c(切记并不是system/core/init/init.rc)

Main函数的for(;;)循环中有一个handle_property_set_fd(),函数:

  for (i = 0; i < fd_count; i++) {        if (ufds[i].revents == POLLIN) {            if (ufds[i].fd == get_property_set_fd())                handle_property_set_fd();            else if (ufds[i].fd == get_keychord_fd())                handle_keychord();            else if (ufds[i].fd == get_signal_fd())                handle_signal();        }    }

这个函数的实现也在system/core/init目录下,该函数中的check_control_perms(msg.value, cr.uid, cr.gid)函数就是检查该uid是否有权限启动服务(msg.value就是你服务的名字),如果应用为root或system用户则直接返回1.之后就是调用handle_control_message((char*) msg.name + 4, (char*) msg.value),该函数的参数就是去掉1.ctl.后的start和2.你服务的名字。这个函数的详细内容:

void handle_control_message(const char *msg, const char *arg)
{
if (!strcmp(msg,”start”)) {
msg_start(arg);
} else if (!strcmp(msg,”stop”)) {
msg_stop(arg);
} else if (!strcmp(msg,”restart”)) {
msg_stop(arg);
msg_start(arg);
} else {
ERROR(“unknown control msg ‘%s’\n”, msg);
}
}

匹配start后调用msg_start.服务就这样起来了,我们的解决方案就是在检查权限的地方“下点功夫”,因为我们不确定uid,所以就让check_control_perms这个函数不要检查我们的uid,直接检查我们服务的名字,看看这个函数:

static int check_control_perms(const char *name, unsigned int uid, unsigned int gid) {
int i;
if (uid == AID_SYSTEM || uid == AID_ROOT)
return 1;
/* Search the ACL */
for (i = 0; control_perms[i].service; i++) {
if (strcmp(control_perms[i].service, name) == 0) {
if ((uid && control_perms[i].uid == uid) ||
(gid && control_perms[i].gid == gid)) {
return 1;
}
}
}
return 0;
}

这个函数里面是必须要检查uid的,我们只要在for循环上写上。
if(strcmp(“usblp_test”,name)==0) //usblp_test就是我们服务的名字。
return 1;

这样做不会破坏android原本的结构,不会有什么副作用。

init.c和init.rc都改好了,现在就可以编译源码了,编译好了装到机子开发板上就可以了。

0 0
原创粉丝点击