1.首先取消su只限定ROOT,SHELL用户使用的限制
code/system/extras/su/su.c
int main(int argc, char** argv) {
//uid_t current_uid = getuid();
//if (current_uid != AID_ROOT && current_uid != AID_SHELL) error(1, 0, “not allowed”);
// Handle -h and --help.
++argv;
2.APP通过socket 与su服务建立连接
suserver.c
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the “License”);
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an “AS IS” BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
char* result;
long lenght = 8192;
void executeCMD(const char *cmd) {
char buf_ps[8192];
char ps[8192] = { 0 };
int i = 1;
//char *result2 = NULL;
FILE *ptr = NULL;
strcpy(ps, cmd);
if ((ptr = popen(ps, “r”)) != NULL) {
result = (char ) malloc(lenght sizeof(char));
char result2 = (char ) malloc(lenght * sizeof(char));
while (fgets(buf_ps, 8192, ptr) != NULL) {
result = (char *) malloc(lenght * i * sizeof(char));
if (result2 != NULL)
strcpy(result, result2);
strcat(result, buf_ps);
i++;
result2 = (char *) malloc(lenght * (i - 1) * sizeof(char));
strcpy(result2, result);
}
pclose(ptr);
ptr = NULL;
} else {
printf("popen %s error\n", ps);
}
}
int main() {
//pid_t pc;
//int i, fd;
int i;
/*
pc = fork();
if (pc < 0) {
printf("error fork/n");
exit(1);
} else if (pc > 0)
exit(0); // 父进程退出 , 这个子进程变成孤儿进程 , 由 init 进程接管 ,
*/
setsid(); // 变为后台程序
chdir("/");
umask(0); // 对所有的权限开放
for (i = 0; i < MAXFILE; i++)
close(i); // 关闭所有的不需要的文件描述符
int server_sockfd; //服务器端套接字
int client_sockfd; //客户端套接字
int len;
struct sockaddr_in my_addr; //服务器网络地址结构体
struct sockaddr_in remote_addr; //客户端网络地址结构体
int sin_size;
char buf[8192]; //数据传送的缓冲区
memset(&my_addr, 0, sizeof(my_addr)); //数据初始化--清零
my_addr.sin_family = AF_INET; //设置为IP通信
my_addr.sin_addr.s_addr = INADDR_ANY; //服务器IP地址--允许连接到所有本地地址上
my_addr.sin_port = htons(40000); //服务器端口号
/*创建服务器端套接字--IPv4协议,面向连接通信,TCP协议*/
if ((server_sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
return 1;
}
/*将套接字绑定到服务器的网络地址上*/
if (bind(server_sockfd, (struct sockaddr *) &my_addr,
sizeof(struct sockaddr)) < 0) {
perror("bind");
return 1;
}
/*监听连接请求--监听队列长度为5*/
listen(server_sockfd, 5);
sin_size = sizeof(struct sockaddr_in);
while (1) // 守护进程实现的服务
{
//printf("等待连接...\n");
if ((client_sockfd = accept(server_sockfd,
(struct sockaddr *) &remote_addr, (socklen_t *)&sin_size)) < 0) {
perror("accept");
//return 1;
}
//printf("接受到一个连接:%s \r\n", inet_ntoa(remote_addr.sin_addr));
if ((len = recv(client_sockfd, buf, 8192, 0)) > 0) {
buf[len] = '\0';
//printf("%s\n", buf);
executeCMD(buf);
if (strlen(result) == 0) {
strcpy(result, "Returing is null!");
}
if (send(client_sockfd, result, strlen(result), 0) < 0) {
perror("write");
//return 1;
}
}
close(client_sockfd);
}
close(server_sockfd);
return 0;
}
3.suserver security 相关
code/device/qcom/sepolicy/common/file_contexts
/system/xbin/suserver u:object_r:suserver_exec:s0
code/device/qcom/sepolicy/common/suserver.te
type suserver, domain;
type suserver_exec, exec_type, file_type;
init_daemon_domain(suserver)
4.启动服务
code/device/qcom/xxx/init.target.rc
service suserver /system/xbin/suserver
class main
user root
group root wifi
oneshot
on boot
start suserver
5.APP调用方法例子
try{
Process suProcess = Runtime.getRuntime().exec(“suclient”);//root权限
DataOutputStream os = new DataOutputStream(suProcess.getOutputStream());
os.writeBytes(“ifconfig eth0 192.168.1.99 broadcast 192.168.1.255 netmask 255.255.255.0\n”);
os.writeBytes(“exit\n”);
os.flush();
}catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}