android seliunx权限问题(访问设备节点)

sancaiodm Android应用 2021-11-07 1635 0

查看手机系统某一个设备节点的权限是什么的查看命令是:

ls -Zl xx  //xx为设备点文件 l 不是1,是字母l


什么是设备节点(设备文件)?

Linux中设备节点是通过“mknod”命令来创建的。一个设备节点其实就是一个文件,Linux中称为设备文件。有一点必要说明的是,在Linux中,所有的设备访问都是通过文件的方式,一般的数据文件程序普通文件,设备节点称为设备文件。所以读写设备节点即读取更改文件数据。

无论是在android应用内以java代码或是用c语言jni来读写设备节点值,或是执行sh脚本通过cat命令获取,或是JAVA IO流来操作读取文件内容,在此前都要确认当前应用是否有权限去读写设备节点,如果任意用户都有权去操作读写底层的设备节点值,就会造成你可以改,我也可以改,系统毫无不安全性可言,

我们可以使用shell命令写看读写设备节点所需要的相应权限:

ls -Zl xx 

sargo:/sys/class/qcom-battery # ls -Zl

total 0

-rw-r--r-- 1 root root u:object_r:sysfs:s0 4096 2021-11-27 10:28 parallel_pct

-rw-r--r-- 1 root root u:object_r:sysfs:s0 4096 2021-11-27 10:28 restricted_charging

-rw-r--r-- 1 root root u:object_r:sysfs:s0 4096 2021-11-27 10:28 restricted_current

-r--r--r-- 1 root root u:object_r:sysfs:s0 4096 2021-11-27 10:28 version

linux文件的权限还不太了解的可先阅读本站此文,

如果是临时性的调试开发,可通过adb更改一下节点用户组及执行所需的权限

chown system system /dev/xx
chmod 0777 /dev/xx      #文件赋予任何用户可读,可写,可执行权限

chmod a+x  build.log   #给build.log文件赋予所有者可执行权限

或是

setenforce 1   //打开seLinux

setenforce 0   //关闭seLinux

getenforce    //获取当前seLinux状态,

临时性的关闭selinux再去读写节点,或是执行节点


操作设备节点的日志log可以过滤:avc    adb logcat |grep avc


JAVA IO操作,读节点 方式1

//sys_path 为节点映射到的实际路径
public static String readFile(String sys_path) { 
     String prop = "waiting";// 默认值 
     BufferedReader reader = null; 
     try { 
           reader = new BufferedReader(new FileReader(sys_path)); 
           prop = reader.readLine(); 
     } catch (IOException e) { 
          e.printStackTrace(); 
          Log.w(MainActivity.TAG, " ***ERROR***  " + e.getMessage()); 
     } finally { 
          if(reader != null){ 
              try { 
                   reader.close(); 
              } catch (IOException e) { 
                   e.printStackTrace(); 
              } 
        } 
    } 
    Log.w(MainActivity.TAG, "readFile cmd from"+sys_path + "data"+" -> prop = "+prop); 
    return prop; }

JAVA IO操作,读节点方式2

//sys_path 为节点映射到的实际路径
public static String read(String sys_path){ 
    try { 
        Runtime runtime = Runtime.getRuntime(); 
        Process process = runtime.exec("cat " + sys_path); // 此处进行读操作 
        InputStream is = process.getInputStream(); 
        InputStreamReader isr = new InputStreamReader(is); 
        BufferedReader br = new BufferedReader(isr); 
        String line ; 
        while (null != (line = br.readLine())) { 
            Log.w(MainActivity.TAG, "read data ---> " + line); return line; 
        } 
    } catch (IOException e) { 
         e.printStackTrace(); 
         Log.w(MainActivity.TAG, "*** ERROR *** " + e.getMessage()); 
    }
    return null; }

JAVA IO操作,读节点方式3

private static String getString(String path) {
    String prop = "none";// 默认值
    try {
        BufferedReader reader = new BufferedReader(new FileReader(path));
        prop = reader.readLine();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return prop;
}


JAVA IO操作写节点

private static final String WAKE_PATH = "/sys/class/demo/wake";
       try {
           BufferedWriter bufWriter = null;
           bufWriter = new BufferedWriter(new FileWriter(WAKE_PATH));
           bufWriter.write("1");  // 写入字符串"1"操作
           bufWriter.close();
           Log.d(TAG,"功能已激活 angle " + getString(ANGLE_PATH));
       } catch (IOException e) {
           e.printStackTrace();
       }

JAVA IO操作 写节点2

public static void writeSysFile(String sys_path){ 
    Process p = null; 
    DataOutputStream os = null; 
    try { 
        p = Runtime.getRuntime().exec("sh"); 
        os = new DataOutputStream(p.getOutputStream()); 
        os.writeBytes("echo 1 > "+sys_path + "\n"); 
        os.writeBytes("exit\n"); 
        os.flush(); 
    } catch (IOException e) { 
        e.printStackTrace(); 
        Log.e(MainActivity.TAG, " can't write " + sys_path+e.getMessage()); 
    } finally { 
        if(p != null)  { p.destroy(); } 
        if(os != null){ 
            try { 
                os.close(); 
            } catch (IOException e) { 
                e.printStackTrace(); 
            } 
        } 
    } }



在jni中去操作某个设备节点

//方法在驱动中生成的节点

#define DEV_NAME “/dev/xx”

namespace android{
static jint com_android_server_SelfManagerService_tngpio_read (JNIEnv* env, jobject clazz)
{
    FILE *fp = NULL;
    fp = fopen(DEV_NAME, “w+”);
    char buff[255];
    fgets(buff, 255, fp);
    fclose(fp);
    return atoi(buff);
}
static void com_android_server_SelfManagerService_tngpio_write (JNIEnv* env, jobject clazz)
{ 
    FILE *fp = NULL;
    fp = fopen(DEV_NAME, "w+");
    char str[255];
    fputs(str,fp);
    fclose(fp);
}

//cpp中对节点写值:

extern int nodeWriteValue(const char* path,const char *value){
  int resultWrite;
  int filep = open(path,O_WRONLY);
  if(filep < 0){
     printf("open file %s failed",path);
  }
  resultWrite = write(filep,value,MAX_SIZE);
  if(resultWrite < 0){
     printf("wirte file %s failed",path);
  }
  close(filep);
  return resultWrite;
}

好文分享:

Android app如何正确读写系统sys设备节点

Android APP如何简单快速实现控制硬件设备并实现APP签名

android 自定义上层API控制硬件设备的一种完整过程实现

评论