包含javauidgid的词条

博主:adminadmin 2023-03-18 06:07:09 518

本篇文章给大家谈谈javauidgid,以及对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

Java web项目,怎么做负载均衡啊?

HAProxy是一款反向代理服务器工具,通过它,可以实现负载均衡。它支持双机热备支持虚拟主机,但其配置简单,拥有非常不错的服务器健康检查功能,当其代理的后端服务器出现故障, HAProxy会自动将该服务器摘除,故障恢复后再自动将该服务器加入。新的1.3引入了frontend,backend,frontend根据任意HTTP请求头内容做规则匹配,然后把请求定向到相关的backend.

利用HAPorxy实现负载均衡

1. 利用HAProxy实现负载均衡

192.168.169.137 (haproxy)———负载均衡———-(192.168.169.117;192.168.169.118)

安装配置HAproxy

cd /usr/local/

wget

tar zxvf haproxy-1.3.14.2.tar.gz

mv haproxy-1.3.14.2 haproxy

cd haproxy

make TARGET=linux26

2. 创建配置文件

# vi haproxy.cfg

global

maxconn 5120

chroot /usr/local/haproxy

uid 99

gid 99

daemon

quiet

nbproc 2 #通过nbproc多设置几个haproxy并发进程,这样每个进程的task_queue相对就会短很多,性能自然就能提高不少

#pidfile /var/run/haproxy-private.pid

defaults

log global

mode http

option httplog

option dontlognull

log 127.0.0.1 local3

retries 3

option redispatch

maxconn 2000

contimeout 5000

clitimeout 50000

srvtimeout 50000

listen webfarm 0.0.0.0:80

mode http

stats uri /haproxy-stats #监控haproxy状态

stats realm Haproxy\ statistics

stats auth netseek:52netseek #设置状态监控的用户名为netseek密码为52netseek

balance roundrobin #负载均衡算法

cookie SERVERID insert indirect

option httpclose #

option forwardfor #apache日志转发功能

option httpchk HEAD /check.txt HTTP/1.0 #健康检测

server app_bbs1 192.168.169.117:80 cookie app1inst1 check inter 2000 rise 2 fall 5

server app_bbs2 192.168.169.118:80 cookie app1inst2 check inter 2000 rise 2 fall 5

syslog.conf里加一行

local3.* /var/log/haproxy.log

# touch /var/log/haproxy.log

# chown haproxy:haproxy /var/log/haproxy.log

# chmod u+x /var/log/haproxy.log

# tail –f /var/log/harpoxy.log 监控日志

# ./haproxy -f haproxy.cfg 启动服务.

监控状态图示 ,输入用户名密码查看状态。

后端apache日志处理

配置httpd.conf

LogFormat “%{X-Forwarded-For}i %l %u %t \”%r\” %s %b ” combined

CustomLog /var/log/httpd/access_log combined

虚拟主机不记录检测日志:

SetEnvIf Request_URI “^/check\.txt$” dontlog

LogLevel warn

ErrorLog /var/log/httpd/vhost_error.log

CustomLog /var/log/httpd/vhost_access.log combined env=!dontlog

相关介绍

#./haproxy –help //haproxy相关命令参数介绍.

haproxy -f 配置文件 [-n 最大并发连接总数] [-N 每个侦听的最大并发数] [-d] [-D] [-q] [-V] [-c] [-p pid文件] [-s] [-l] [-dk]

[-ds] [-de] [-dp] [-db] [-m 内存限制M] [{-sf|-st} pidlist...]

-d 前台,debug模式

-D daemon模式启动

-q 安静模式,不输出信息

-V 详细模式

-c 对配置文件进行语法检查

-s 显示统计数据

-l 显示详细统计数据

-dk 不使用kqueue

-ds 不使用speculative epoll

-de 不使用epoll

-dp 不使用poll

-db 禁用后台模式,程序跑在前台

-sf pidlist

程序启动后向pidlist里的进程发送FINISH信号,这个参数放在命令行的最后

-st pidlist

程序启动后向pidlist里的进程发送TERMINATE信号,这个参数放在命令行的最后

如何用JAVA实现Linux上的消息队列功能

下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处。有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信——使用命名管道

一、什么是消息队列

消息队列提供了一种从一个进程向另一个进程发送一个数据块的方法。 每个数据块都被认为含有一个类型,接收进程可以独立地接收含有不同类型的数据结构。我们可以通过发送消息来避免命名管道的同步和阻塞问题。但是消息队列与命名管道一样,每个数据块都有一个最大长度的限制。

Linux用宏MSGMAX和MSGMNB来限制一条消息的最大长度和一个队列的最大长度。

二、在Linux中使用消息队列

Linux提供了一系列消息队列的函数接口来让我们方便地使用它来实现进程间的通信。它的用法与其他两个System V PIC机制,即信号量和共享内存相似。

1、msgget函数

该函数用来创建和访问一个消息队列。它的原型为:

int msgget(key_t, key, int msgflg);

与其他的IPC机制一样,程序必须提供一个键来命名某个特定的消息队列。msgflg是一个权限标志,表示消息队列的访问权限,它与文件的访问权限一样。msgflg可以与IPC_CREAT做或操作,表示当key所命名的消息队列不存在时创建一个消息队列,如果key所命名的消息队列存在时,IPC_CREAT标志会被忽略,而只返回一个标识符。

它返回一个以key命名的消息队列的标识符(非零整数),失败时返回-1.

2、msgsnd函数

该函数用来把消息添加到消息队列中。它的原型为:

int msgsend(int msgid, const void *msg_ptr, size_t msg_sz, int msgflg);

msgid是由msgget函数返回的消息队列标识符。

msg_ptr是一个指向准备发送消息的指针,但是消息的数据结构却有一定的要求,指针msg_ptr所指向的消息结构一定要是以一个长整型成员变量开始的结构体,接收函数将用这个成员来确定消息的类型。所以消息结构要定义成这样:

struct my_message{

long int message_type;

/* The data you wish to transfer*/

};

msg_sz是msg_ptr指向的消息的长度,注意是消息的长度,而不是整个结构体的长度,也就是说msg_sz是不包括长整型消息类型成员变量的长度。

msgflg用于控制当前消息队列满或队列消息到达系统范围的限制时将要发生的事情。

如果调用成功,消息数据的一分副本将被放到消息队列中,并返回0,失败时返回-1.

3、msgrcv函数

该函数用来从一个消息队列获取消息,它的原型为

int msgrcv(int msgid, void *msg_ptr, size_t msg_st, long int msgtype, int msgflg);

msgid, msg_ptr, msg_st的作用也函数msgsnd函数的一样。

msgtype可以实现一种简单的接收优先级。如果msgtype为0,就获取队列中的第一个消息。如果它的值大于零,将获取具有相同消息类型的第一个信息。如果它小于零,就获取类型等于或小于msgtype的绝对值的第一个消息。

msgflg用于控制当队列中没有相应类型的消息可以接收时将发生的事情。

调用成功时,该函数返回放到接收缓存区中的字节数,消息被复制到由msg_ptr指向的用户分配的缓存区中,然后删除消息队列中的对应消息。失败时返回-1.

4、msgctl函数

该函数用来控制消息队列,它与共享内存的shmctl函数相似,它的原型为:

int msgctl(int msgid, int command, struct msgid_ds *buf);

command是将要采取的动作,它可以取3个值,

IPC_STAT:把msgid_ds结构中的数据设置为消息队列的当前关联值,即用消息队列的当前关联值覆盖msgid_ds的值。

IPC_SET:如果进程有足够的权限,就把消息列队的当前关联值设置为msgid_ds结构中给出的值

IPC_RMID:删除消息队列

buf是指向msgid_ds结构的指针,它指向消息队列模式和访问权限的结构。msgid_ds结构至少包括以下成员:

struct msgid_ds

{

uid_t shm_perm.uid;

uid_t shm_perm.gid;

mode_t shm_perm.mode;

};

成功时返回0,失败时返回-1.

三、使用消息队列进行进程间通信

马不停蹄,介绍完消息队列的定义和可使用的接口之后,我们来看看它是怎么让进程进行通信的。由于可以让不相关的进程进行行通信,所以我们在这里将会编写两个程序,msgreceive和msgsned来表示接收和发送信息。根据正常的情况,我们允许两个程序都可以创建消息,但只有接收者在接收完最后一个消息之后,它才把它删除。

接收信息的程序源文件为msgreceive.c的源代码为:

#include unistd.h

#include stdlib.h

#include stdio.h

#include string.h

#include errno.h

#include sys/msg.h

struct msg_st

{

long int msg_type;

char text[BUFSIZ];

};

int main()

{

int running = 1;

int msgid = -1;

struct msg_st data;

long int msgtype = 0; //注意1

//建立消息队列

msgid = msgget((key_t)1234, 0666 | IPC_CREAT);

if(msgid == -1)

{

fprintf(stderr, "msgget failed with error: %d\n", errno);

exit(EXIT_FAILURE);

}

//从队列中获取消息,直到遇到end消息为止

while(running)

{

if(msgrcv(msgid, (void*)data, BUFSIZ, msgtype, 0) == -1)

{

fprintf(stderr, "msgrcv failed with errno: %d\n", errno);

exit(EXIT_FAILURE);

}

printf("You wrote: %s\n",data.text);

//遇到end结束

if(strncmp(data.text, "end", 3) == 0)

running = 0;

}

//删除消息队列

if(msgctl(msgid, IPC_RMID, 0) == -1)

{

fprintf(stderr, "msgctl(IPC_RMID) failed\n");

exit(EXIT_FAILURE);

}

exit(EXIT_SUCCESS);

}

发送信息的程序的源文件msgsend.c的源代码为:

#include unistd.h

#include stdlib.h

#include stdio.h

#include string.h

#include sys/msg.h

#include errno.h

#define MAX_TEXT 512

struct msg_st

{

long int msg_type;

char text[MAX_TEXT];

};

int main()

{

int running = 1;

struct msg_st data;

char buffer[BUFSIZ];

int msgid = -1;

//建立消息队列

msgid = msgget((key_t)1234, 0666 | IPC_CREAT);

if(msgid == -1)

{

fprintf(stderr, "msgget failed with error: %d\n", errno);

exit(EXIT_FAILURE);

}

//向消息队列中写消息,直到写入end

while(running)

{

//输入数据

printf("Enter some text: ");

fgets(buffer, BUFSIZ, stdin);

data.msg_type = 1; //注意2

strcpy(data.text, buffer);

//向队列发送数据

if(msgsnd(msgid, (void*)data, MAX_TEXT, 0) == -1)

{

fprintf(stderr, "msgsnd failed\n");

exit(EXIT_FAILURE);

}

//输入end结束输入

if(strncmp(buffer, "end", 3) == 0)

running = 0;

sleep(1);

}

exit(EXIT_SUCCESS);

}

转载仅供参考,版权属于原作者。祝你愉快,满意请采纳哦

无法打开安装界面 出现this application requires a java runtime environment 1.6.0

无法打开安装界面可以从其他主机直接复制Oracle软件至目标主机。这要求主机之间的操作系统版本一致,且安装用户的uid、gid属性一致,复制完成之后需要执行relink all命令,否则在数据库的运行过程可能会出现一些不可预知的错误。

碰到此类故障的解决方法:

1、在root用户下执行xclock命令,确定是否能在服务器的桌面上顺利启动小时钟。如果不能显示,则检查操作系统X Window服务是否正常。

2、检查DISPLAY环境变量的设置是否正确。如果在个人计算机的终端上开启了多个X Window连接窗口,每个终端的DISPLAY环境变量的设置往往也会不一样,如export DISPLAY=192.168.0.1:0.0、export DISPLAY=192.168.0.1:1.0等。

3、如果Xmanager软件连接主机时无法显示服务器桌面,那么需检查服务器的/etc/hosts配置文件是否正确,Xmanager是否跨网段连接至服务器。

梳理uid、userid及UserHandle概念

在Android 4.2之前,Android不支持多用户,在4.2以后Android系统增加了自己的多用户功能。Android是基于Linux的OS,Linux下有一套自己的账户管理体系,而Android在Linux的基础上有一些封装和改动。

在加入了多用户之后,常在源码中看到UserHandle、userid、uid这些概念,一时间让我有些混乱,这里我就来梳理一下,算是做一次记录。

Linux uid

Linux是多用户系统,每个用户都拥有一个uid,这个uid由系统和用户名做映射绑定。同时,为了便于用户管理(譬如管理文档权限),Linux引入了群组的概念,可以将多个用户归于一个群组。每一个群组拥有一个群组id(gid)。

Android uid

Android的应用的UID是从10000开始,到19999结束,可以在Process.java中查看到(FIRST_APPLICATION_UID和LAST_APPLICATION_UID),使用adb shell的ps命令查看到的pid,例如 u0_a 后面的数字就是该应用的UID值减去FIRST_APPLICATION_UID所得的值。

android\os\Process.java

应用安装后,系统重启和应用重启都不会改变uid。

uid记录在 data/system/packages.xml 中。可以dumpsys出来看看。

通过源码可以看到,UserHandle包含三种概念:userid、uid、appid

userid :就是有多少个实际的用户,即手机里的主机、访客等多用户。

uid :上文讲过他跟应用进程相关,除了shareduid的应用,每个用户的每个应用的uid不一样的。

appid :跟app相关,包名相同的appid都一样,即使是不同用户。

SELinux权限

在了解SELinux之前,我们先来了解一下Linux的两种访问控制策略:DAC和MAC

DAC,自主访问控制(Discretionary Access control)。系统只提供基本的验证, 完整的访问控制由开发者自己控制。

 DAC将资源访问者分成三类:Owner、Group、Other 。

 将访问权限也分成三类:read、write、execute

资源针对资源访问者设置不同的访问权限。访问者通常是各个用户的进程,有自己的uid/gid,通过uid/gid 和文件权限匹配, 来确定是否可以访问。DAC机制下,每一个用户进程默认都拥有该用户的所有权限。

DAC 有两个严重问题:

 问题一:

 因为Root用户是拥有所有权限的,所以DAC对Root用户的限制是无效的。并且在Linux Kernel 2.1以后,Linux将Root权限根据不同的应用场景划分成许多的Root Capabilities, 普通用户也可以被设置某个Root Capability。普通用户如果被设置了CAP_DAC_OVERRIDE, 也可以绕过 DAC 限制。

 问题二:

 用户进程拥有该用户的所有权限,可以修改/删除该用户的所有文件资源, 难以防止恶意软件。

可见,DAC 有明显的缺陷,一旦被入侵,取得Root权限的用户进程就可以无法无天,胡作非为,早期android版本就深受其害。

MAC, 强制性访问控制(Mandatory Access control)。 系统针对每一项访问都进行严格的限制, 具体的限制策略由开发者给出。

Linux MAC 针对DAC 的不足, 要求系统对每一项访问, 每访问一个文件资源都需要根据已经定义好了的策略进行针对性的验证。系统可以针对特定的进程与特定的文件资源来进行权限的控制。即使是root用户,它所属的不同的进程,并不一定能取得root权限,而得要看事先为该进程定义的访问限制策略。如果不能通过MAC 验证,一样无法执行相关的操作。

与DAC相比,MAC访问控制的“主体”变成了“进程”而不是用户。这样可以限制了Root 权限的滥用,另外要求对每一项权限进行了更加完整的细化, 可以限制用户对资源的访问行为。

SELinux就是目前最好的MAC机制,也是目前的行业标准。

SELinux,安全增强Linux(Security-Enhanced Linux),是由美国国家安全局(NSA)发起, 多个非营利组织和高校参与开发的强制性安全审查机制(Mandatory Access control,简称MAC)。SELinux最早于2000年12月采用GPL许可发布。目前,Linux Kernel 2.6 及以上的版本都已经集成了SELinux。

SELinux 分成三种模式:

Android 5.x及以上强制开启,因此,disabled(关闭)模式并没有什么用了。 通常在调试时,我们会启用Permissve(宽容模式), 以便尽可能的发现多的问题, 然后一次修正。 在量产时启用Enfocing mode(强制模式)来保护系统。

查看SELinux模式:adb shell getenforce

设置SELinux模式:adb shell setenforce 1 //0是Permissve,1是Enfocing

SELinux 的访问控制示意图:

通常我们开发的过程中,就是配置Subject、Object、Security Policy。

SELinux 给Linux 的所有对象都分配一个安全上下文(Security Context), 描述成一个标准的字符串。

安全上下文的标准格式: user:role:type[:range]

Security Label 用来绑定被访问资源和安全上下文,描述它们的对应关系。标准格式为:resource security_context。即:res user:role:type[:range]。这里也可以使用通配符,例如 net.就可以绑定所有以net.开头的属性,除此之外,还有类似正则表达式的*、?等等通配符。Security Label 都定义在type_contexts当中,例如file的定义在file_contexts中,service定义在service_contexts中,property定义在property_contexts中。

举例:

file_contexts:

service_contexts:

查看进程安全上下文: ps -AZ 。例如,查看Settings进程的安全上下文,ps -AZ | grep settings:

  u:r:system_app:s0 system 1381 585 4234504 201072 0 0 S com.android.settings

查看文件安全上下文: ls -Z 。例如,查看文件build.prop的安全上下文:

  u:object_r:system_file:s0 build.prop

Type Enforcement (TE) 是根据Security Context中的 type 进行权限审查, 审查 subject type 对 object type 的某个class 类型中某种permission 是否具有访问权限,是目前使用最为广泛的MAC 审查机制, 简单易用。

TE控制语句格式 : rule_name source_type target_type : class perm_set

Type Enforcement规则说明:

举个例子,logd.te、tombstoned.te中定义的TE规则:

  allow logd runtime_event_log_tags_file:file rw_file_perms;

  dontaudit domain runtime_event_log_tags_file:file { open read };

  auditallow tombstoned anr_data_file:file { append write };

  neverallow logd { app_data_file system_data_file }:dir_file_class_set write;

SELinux 中每一个进程或者文件都对应一个type, 而每一个type 都对应有一个或几个attribute。所有常见的attribute定义在以下文件中:

  system/sepolicy/public/attributes

  system/sepolicy/prebuilts/api/[build version]/public/attributes

  system/sepolicy/prebuilts/api/[build version]/private/attributes

其中的[build version]即为android版本号,例如android O为28.0。常见的attribute定义:

Type对应一个或者几个attribute,Type的定义格式:

  type type_name, attribute1, attribute2;

Type的定义通常分散在各个te文件中。例如,常用普通文件的type定义在file.te中:

SEAndroid对于不同的资源类型,定义了不同的Class。比如普通的file、socket等等,比如SELinux 使用的security, 比如针对每个process 参数的process 等定义相关的class。这些class,每一个class 都有相对应的permissions。 比如file 就有 read, write, create, getattr, setattr, lock, ioctl 等等. 比如process 就有fork, sigchld, sigkill, ptrace, getpgid, setpgid 等等。这些相关的class, 以及他们具有那些Permissions都定义在以下文件中:

  system/sepolicy/private/access_vectors

  system/sepolicy/reqd_mask/access_vectors

  system/sepolicy/prebuilts/api/版本号/private/access_vectors

例如:

定义完之后,在以下对应的security_classes 文件中声明定义的classes。

  system/sepolicy/private/security_classes

  system/sepolicy/reqd_mask/security_classes

  system/sepolicy/prebuilts/api/版本号/private/security_classes

例如:

注意,Classes 和Permissions的定义与Kernel 中相关API是强相关的,普通用户严禁修改。

在SELinux 中, 我们通常称一个进程是一个domain, 一个进程fork 另外一个进程并执行(exec) 一个执行档时, 我们往往会涉及到domain 的切换. 比如init 进程, SELinux 给予了它很大的权限, 而它拉起的服务, 我们要限制这个服务的权限,于是就涉及到从一个domain 切换到另外一个domain, 不然默认就使用init 进程的domain.

在SELinux 里面有专门的一条语法: type_transition statement.

在准备切换前我们先要确保有相关的权限操作:

如下面的demo, init 拉起apache 并且切换到 apache 的domain.

(1). 首先,你得让init_t域中的进程能够执行type为apache_exec_t的文件

  allow init_t apache_exec_t : file {read getattr execute};

(2). 然后,你还得告诉SELinux,允许init_t做DT切换以进入apache_t域

  allow init_t apache_t : process transition;

(3). 然后,你还得告诉SELinux,切换入口(对应为entrypoint权限)为执行apache_exec_t类型 的文件

  allow apache_t apache_exec_t : file entrypoint;

(4).最后,Domain Transition

  type_transition init_t apache_exec_t : process apache_t;

可以看到,整个domain切换过程写起来非常麻烦。因此,Google 为了使用方便, 在system/sepolicy/public/te_macros 文件中定义了宏:

我们可以使用这些宏来完成domain切换。

举例:

kernel启动init进程切换domain:

  domain_auto_trans(kernel, init_exec, init)

init启动netd、vold、zygote、installd切换domain:

  init_daemon_domain(netd)

  init_daemon_domain(vold)

  init_daemon_domain(zygote)

  init_daemon_domain(installd)

一个进程创建在一个目录下创建文件时, 默认是沿用父目录的Security Context, 如果要设置成特定的Label, 就必须进行Object Transitions.

同样是使用:type_transition statement.

对应的必须有两个前提条件:

下面是一个demo, ext_gateway_t 这个domain 在类型为in_queue_t 的目录下,创建类型为 in_file_t 的文件.

(1). 首先,你得让ext_gateway_t 对in_queue_t 目录具备访问权限

  allow ext_gateway_t in_queue_t : dir { write search add_name };

(2). 然后,你还得告诉SELinux,允许ext_gateway_t 访问in_file_t的文件

  allow ext_gateway_t in_file_t : file { write create getattr };

(3).最后,Object Transition

  type_transition ext_gateway_t in_queue_t : file in_file_t;

同样的,为了方便使用,Google 也在system/sepolicy/public/te_macros 文件中定义了宏:

使用举例:

  file_type_auto_trans(factory, system_data_file, factory_data_file)

android O 以前sepolicy 集中放在boot image 。前面提到SELinux在Android的主要变更历史时,有提到android O 开始,Google将system image 和 vendor image 分离。因此,sepolicy 也相应的被分离存放到system image 以及 vendor image。与system 相关的sepolicy 就存放system image, 与SoC vendor 相关的sepolicy 就存放在vendor image。

对于原生AOSP,Google 设定了不同的存放目录, 以便进行分离, 以Google 默认的sepolicy 为例,sepolicy主目录为 /system/sepolicy,我们主要关注三个子目录:

对于不同的平台,不同平台厂商也设定了不同的存放目录,以MTK平台为例:

首先,根据不同的platform共用sepolicy、platform独有、project独有,分为:

对应的,不同版本会导入不同目录下的sepolicy配置

以mt6763平台为例,导入时:

[common] 路径为:/device/mediatek/sepolicy

[platfrom] 路径为:/device/mediatek/mt6763/sepolicy/

具体的定义在BoardConfig.mk文件中:

然后,basic、bsp、full又可以主要细分为:

Google 在system/sepolicy 中定义了相关的neverallow 规则, 对SELinux Policy 的更新进行了限制, 以防止开发者过度开放权限,从而引发安全问题。并且还会通过CTS测试检测开发者是否有违法相关的规则。

因此,我们需要注意以下几点:

出现SELinux Policy Exception时常见的两种解决方案:

(1). 修改对应节点的SELinux Security Label, 为特定的Subject,如system_app、platform_app、priv_app,例如Settings,SystemUI等内置APP开启权限, 但严禁为untrsted app 开启权限。

(2). 通过system server service 或者 init 启动的service 读写操作, 然后app 通过binder/socket 等方式连接访问. 此类安全可靠, 并且可以在service 中做相关的安全审查, 推荐这种方法.

情景: 定义由 init 进程启动的service, factory, 其对应的执行档是 /vendor/bin/factory。

(1). 在device/mediatek/mt6763/sepolicy/basic/non_plat 目录下创建一个factory.te , 然后将te文件加入编译,如放到这种指定目录下不需要额外配置,sytem/sepolicy/Android.mk中定义的build_policy函数会遍历指定目录导入te文件。

(2). 在factory.te 中定义factory类型,init 启动service 时类型转换,

  type factory, domain;

  type factory_exec, exec_type, file_type, vendor_file_type;

  init_daemon_domain(factory)

(3). 在file_contexts中绑定执行档

  /(system/vendor|vendor)/bin/factory u:object_r:factory_exec:s0

(4). 根据factory需要访问的文件以及设备, 定义其它的权限在factory.te 中.

  #Purpose: For key and touch event

  allow factory input_device:chr_file r_file_perms;

  allow factory input_device:dir rw_dir_perms;

情景: 添加一个自定义的system property: persist.demo,并为platform_app设置读写权限

(1). 在property.te中定义system property类型

  type demo_prop, property_type

(2). 在property_contexts中绑定system property的安全上下文。

  persist.demo u:object_r:demo_prop:s0

(3). 在platform_app.te 中新增写权限,可以使用set_prop宏。

  set_prop(platform_app, demo_prop)

(4). 在platform_app.te 中新增读权限,可以get_prop 宏。

  get_prop(platform_app, demo_prop)

情景: 有一个设备节点/dev/demo,有一个platform_app进程需要读写这个设备节点。

(1). 在device.te中定义device 类型

  type demo_device dev_type;

(2). 在 file_contexts中绑定demo_device

  /dev/demo u:object_r:demo_device:s0

(3). 在platform_app.te中,允许platform_app使用demo device 的权限

  allow platform_app demo_device:chr_file rw_file_perms;

情景: 有一个扩展的系统服务demo_service供APP调用。

(1). 在service.te 中定义service 类型

  type demo_service, app_api_service, system_server_service, service_manager_type;

(2). 在service_contexts 中绑定service

  demo u:object_r:demo_service:s0

(3). 在frameworks/base/core/java/android/content/Context.java中定义服务常量

  public static final String DEMO_SERVICE = "demo";

(4). 在frameworks/base/core/java/android/app/SystemServiceRegistry.java中,参照其它系统服务注册demo_service

(5). 在frameworks/base/services/java/com/android/server/SystemServer.java中,启动DemoService,添加到service_manager进行管理。

(6). 最后一步,参考其它系统服务,实现DemoManager、DemoService,并定义如IDemoService等等的AIDL接口。

情景: 一个native service 通过init 创建一个socket 并绑定在 /dev/socket/demo, 并且允许某些process 访问.

(1). 在file.te中定义socket 的类型

  type demo_socket, file_type;

(2). 在file_contexts中绑定socket 的类型

  /dev/socket/demo_socket u:object_r:demo_socket:s0

(3). 允许所有的process 访问,使用宏unix_socket_connect(clientdomain, socket, serverdomain)

  unix_socket_connect(appdomain, demo, demo)

(1). 在device/mediatek/mt6763/sepolicy/basic/non_plat目录下创建一个demo.te。

(2). 在demo.te 中定义demo 类型,init 启动service 时类型转换。并可以根据demo 需要访问的文件以及设备, 定义其它的权限在demo.te 中。

  type demo, domain;

  type demo_exec, exec_type, file_type;

  init_daemon_domain(demo)

(3). 绑定执行档 file_context 类型

  /vendor/bin/demo u:object_r:demo_exec:s0

(4). 创建demo的入口执行档demo_exec、并配置相应的权限。

(1). 将SELinux 调整到Permissive 模式复测

使用eng/userdebug 版本,adb shell setenforce 0 将SELinux 模式调整到Permissive 模式,然后复测。如果还能复现问题,则与SELinux 无关; 如果原本很容易复现, 而Permissive mode 不能再复现, 那么就可能与SELinux相关。

(2). 查看LOG 中是否有标准的SELinux Policy Exception.

在Kernel LOG / Main Log 中查询关键字 "avc: denied" 看看是否有与目标进程相关的SELinux Policy Exception, 并进一步确认这个异常是否与当时的逻辑相关。

一般情况我们在符合Google sepolicy策略及neverallow策略的前提下,根据LOG中的内容,需要什么权限就加什么权限。例如LOG:

2020-03-27 14:11:02.596 1228-1228/com.android.systemui W/FaceIdThread: type=1400 audit(0.0:481): avc: denied { read } for name="als_ps" dev="tmpfs" ino=10279 scontext=u:r:platform_app:s0:c512,c768 tcontext=u:object_r:als_ps_device:s0 tclass=chr_file permissive=0

LOG说明如下:

一般我们需要重点关注的是四个:permission、source type、target type、target class

根据这四个就可以配置出的所需要的selinux权限:

   allow [source type] [target type]: [target class] [permission]

例1:

03-27 03:45:22.632 2958 2958 W Camera: type=1400 audit(0.0:314): avc: denied { read } for name="u:object_r:graphics_debug_prop:s0" dev="tmpfs" ino=2649 scontext=u:r:platform_app:s0:c512,c768 tcontext=u:object_r:graphics_debug_prop:s0 tclass=file permissive=0

解决方案:

按正常的套公式,应该是这样修改platform_app.te,增加:

  allow platform_app graphics_debug_prop:file r_file_perms;

这里我们利用system/sepolicy/te_macros中定义的宏get_prop:

更多相关的宏定义请参考:system/sepolicy/public/te_macros。

所以最终简化后,修改platform_app.te,增加:

  get_prop(platform_app, graphics_debug_prop)

例2:

03-27 14:11:02.596 1228-1228/com.android.systemui W/BackThread: type=1400 audit(0.0:481): avc: denied { read } for name="als_ps" dev="tmpfs" ino=10279 scontext=u:r:platform_app:s0:c512,c768 tcontext=u:object_r:als_ps_device:s0 tclass=chr_file permissive=0

解决方案:

修改platform_app.te增加:

  allow platform_app als_ps_device:chr_file r_file_perms;

(1). 不符合neverallow规则或者修改了neverallow规则

编译报错:

  neverallow check failed at xxx

CTS测试项failed:

  android.cts.security.SELinuxNeverallowRulesTest#testNeverallowRulesXXX

这类问题在android O vendor和system分离之后,尤其容易出现。基本上这类问题都是因为修改或者增加的te配置不符合neverallow规则,导致编译报错。而为了解决编译报错,又修改了neverallow规则,最终在跑CTS时,没法通过相关的测试项。

解决思路:

(2). init进程fork新进程没有做domain切换

CTS测试项failed:

  android.security.cts.SELinuxDomainTest # testInitDomain

解决思路:

fork进程时,参考3.4节中做domain切换。

本文主要参考了MTK-Online的Quick-start中《SELinux 问题快速分析》的内容,感谢原作者们的辛勤付出。另外,结合源码和自身开发实践,增加了一些自身理解和实践内容。

关于javauidgid和的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。