修改Android源码使property中ro属性可重复修改

property ro.xxx属性介绍
ro的英文缩写是Read Only,故在Android系统中,带有ro.的属性都是只读而不可被重复修改的。ro.xxx属性的property通常在系统启动的时候就通过property_set()函数被写在了系统中,而ro属性每次系统启动只能写一次,顾一但设定便不可修改。

setprop
在system/core/toobox下有许多常用的命令的源码,setprop由setprop.c生成


#include 
#include 

int setprop_main(int argc, char *argv[])
{
    if(argc != 3) {
        fprintf(stderr,"usage: setprop  \n");
        return 1;
    }

    if(property_set(argv[1], argv[2])){
        fprintf(stderr,"could not set property\n");
        return 1;
    }
    return 0;
}

setprop调用了property_set(const char key, const char value)函数,该函数位于system/core/libcutils下,在这里,最后跳转到了__system_property_set函数。


#ifdef HAVE_LIBC_SYSTEM_PROPERTIES

#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include 

int property_set(const char *key, const char *value)
{
    return __system_property_set(key, value);
}

int __system_property_set(const char *key, const char *value)
{
    if (key == 0) return -1;
    if (value == 0) value = "";
    if (strlen(key) >= PROP_NAME_MAX) return -1;
    if (strlen(value) >= PROP_VALUE_MAX) return -1;

    prop_msg msg;
    memset(&msg, 0, sizeof msg);
    msg.cmd = PROP_MSG_SETPROP;
    strlcpy(msg.name, key, sizeof msg.name);
    strlcpy(msg.value, value, sizeof msg.value);

    const int err = send_prop_msg(&msg);
    if (err < 0) {
        return err;
    }
    return 0;
}

由于property_set与prop系统服务进程的通信方式主要是通过socket来设置对应的property,而__system_property_set主要作用便是与prop系统服务进程进行通信的。如上代码中,该函数通过send_prop_msg函数发送PROP_MSG_SETPROP命令告知prop系统服务进程写入property。send_prop_msg()函数通过存放在/dev/socket/下的socket本地套接字与服务进程通信。

  1. static const char property_service_socket[] = “/dev/socket/” PROP_SERVICE_NAME;
    prop服务进程在system/core/init下的property_service.c内定义。它通过socket接收来自客户端的消息,通过解析客户端发来的消息内容进行相关操作。

switch(msg.cmd) {
   case PROP_MSG_SETPROP:
       msg.name[PROP_NAME_MAX-1] = 0;
       msg.value[PROP_VALUE_MAX-1] = 0;

       if (!is_legal_property_name(msg.name, strlen(msg.name))) {
           ERROR("sys_prop: illegal property name. Got: \"%s\"\n", msg.name);
           close(s);
           return;
       }

使ro属性可重复被修改
在服务进程接收到客户端发来的PROP_MSG_SETPROP命令时,服务进程会判断将要修改的property是否是ro属性,如果是ro属性且已经存在程序直接返回,对property不做任何修改。
通过修改system/core/init/property_service.c 下的void handle_property_set_fd()函数


 switch(msg.cmd) {
 case PROP_MSG_SETPROP:
     msg.name[PROP_NAME_MAX-1] = 0;
     msg.value[PROP_VALUE_MAX-1] = 0;

     if (!is_legal_property_name(msg.name, strlen(msg.name))) {
         ERROR("sys_prop: illegal property name. Got: \"%s\"\n", msg.name);
         close(s);
         return;
     }

     getpeercon(s, &source_ctx);

     if(memcmp(msg.name,"ctl.",4) == 0) {
         // Keep the old close-socket-early behavior when handling
         // ctl.* properties.
         close(s);
         if (check_control_mac_perms(msg.value, source_ctx)) {
             handle_control_message((char*) msg.name + 4, (char*) msg.value);
         } else {
             ERROR("sys_prop: Unable to %s service ctl [%s] uid:%d gid:%d pid:%d\n",
                     msg.name + 4, msg.value, cr.uid, cr.gid, cr.pid);
         }
     } else {
         if (check_perms(msg.name, source_ctx) 
	|| (0 == strcmp(msg.name, "ro.serialno")) 
	|| (0 == strcmp(msg.name, "ro.deviceid"))) //mod to let 'ro.xxx' can be modifiy
{
             property_set((char*) msg.name, (char*) msg.value);
         } else {
             ERROR("sys_prop: permission denied uid:%d  name:%s\n",
                   cr.uid, msg.name);
         }

         // Note: bionic's property client code assumes that the
         // property server will not close the socket until *AFTER*
         // the property is written to memory.
         close(s);

以及int property_set(const char name, const char value)函数

int property_set(const char *name, const char *value)
{
    prop_info *pi;
    int ret;

    size_t namelen = strlen(name);
    size_t valuelen = strlen(value);

    if (!is_legal_property_name(name, namelen)) return -1;
    if (valuelen >= PROP_VALUE_MAX) return -1;

    pi = (prop_info*) __system_property_find(name);

    if(pi != 0) {
        /* ro.* properties may NEVER be modified once set */
		if((0 == strcmp(name, "ro.serialno")) 
       	|| (0 == strcmp(name, "ro.deviceid")))//mod to let 'ro.xxx' can be modifiy
		{;;}
		else if (!strncmp(name, "ro.", 3) ) return -1;
        //if(!strncmp(name, "ro.", 3) ) return -1;

        __system_property_update(pi, value, valuelen);
    } else {
        ret = __system_property_add(name, namelen, value, valuelen);
        if (ret < 0) {
            ERROR("Failed to set '%s'='%s'\n", name, value);
            return ret;
        }
    }

这样就可以实现对特定ro属性的property进行多次修改!

修改Android源码使property中ro属性可重复修改

你可能感兴趣的:(android内核及源码)