一文带你实现android获取检测Selinux

2,004 阅读2分钟

1.Selinux简介

SELinux(Security-Enhanced Linux) 是美国国家安全局(NSA)对于强制访问控制的实现,是 Linux历史上最杰出的新安全子系统。 SELinux的软件设计架构是参照Flask,Flask是一种灵活的操作系统安全架构,并且在Fluke research operating system中得到了实现。Flask的主要特点是把安全策略执行代码和安全策略决策代码,划分成了两个组件。安全策略决策代码在Flask架构中称作Security Server。除了这两个组件以外,另外一个组件Vector Cache(AVC), 主要提供策略决策结果的缓存,以此提高Security Server的性能。

SELinux 运行有三个运行状态,分别是disabled, permissive 和 enforcing

  • Disable: 禁用SELinux,不会给任何新资源打Label,如果重新启用的话,将会给资源重新打上Lable,过程会比较缓慢。

  • Permissive:如果违反安全策略,并不会真正的执行拒绝操作,替代的方式是记录一条log信息。\

  • Enforcing: 默认模式,SELinux的正常状态,会实际禁用违反策略的操作

2.设置和获取selinux的标志


static char *g_pszSelinuxFileSystemString=NULL;
static char **g_pSelinuxFileSystemStringPointer = &g_pszSelinuxFileSystemString;
//用户设置selinux的标志
int setSelinuxFlag(int value) {
	int fd=0, length=0;
	char fileContentBuffer[20]={0};
	char filePath[1024]={0};
	

	if (*g_pSelinuxFileSystemStringPointer == NULL) {
		errno = 2;
		return -1;
	}

	snprintf(filePath, 1024, "%s/enforce", *g_pSelinuxFileSystemStringPointer);
	fd = open(filePath, 2);
	if (fd < 0)
		return -1;

	snprintf(fileContentBuffer, 20, "%d", value);
	length = strlen(fileContentBuffer);
	
	length = write(fd, fileContentBuffer, len);

	close(fd);

	return length >> 31;
}
//用于获取selinux的标志
int getSelinuxFlag() {
	int fd=0, readLength=0, value=0;
	char fileContentBuffer[20]={0};
	char filePath[1024]={0};
	
	if (*g_pSelinuxFileSystemStringPointer == NULL) {
		errno = 2;
		return -1;
	}

	snprintf(filePath, 1024, "%s/enforce", *g_pSelinuxFileSystemStringPointer);
	fd = open(filePath, 0);
	if (fd < 0)
		return -1;

	memset(fileContentBuffer, 0, 20);
	readLength = read(fd, fileContentBuffer, 19);
	close(fd);

	if (readLength < 0)
		return -1;

	readLength = sscanf(fileContentBuffer, "%d", &value);
	if (readLength != 1)
		return -1;

	return value;
}

3.检测selinux实现

//检测selinux
 void checkSelinux() {
	if (*g_pSelinuxFileSystemStringPointer == NULL) {
		int ret=0;
		FILE *pFilesystems=NULL;
		char fileLineBuffer[1024]={0};
		struct statfs statfsBuffer={0};


		while ((ret = statfs("/sys/fs/selinux", &statfsBuffer)) < 0) {
			if (errno == EINTR)
				continue;
			
			LOGE("statfs error:%s\n", strerror(errno));
			
			return ;
		}

		if (ret == 0 && statfsBuffer.f_type == 0xF97CFF8C ) {
			*g_pSelinuxFileSystemStringPointer = strdup("/sys/fs/selinux");

			return;
		}

		pFilesystems = fopen("/proc/filesystems", "r");
		if (pFilesystems == NULL)
			return ;

		do {
			if (fgets(fileLineBuffer, 1024, pFilesystems) == NULL) {
				fclose(pFilesystems);
				return ;
			}

			if (strstr(fileLineBuffer, "selinuxfs")) {
				break;
			}
		} while (1);

		fclose(pFilesystems);

		pFilesystems = fopen("/proc/mounts", "r");
		if (pFilesystems == NULL)
			return ;

		do {
			char *spacePosition;
			char *fileSystemName;
			
			if (fgets(fileLineBuffer, 1024, pFilesystems) == NULL) {
				fclose(pFilesystems);
				return ;
			}

			spacePosition = strchr(fileLineBuffer, ' ');
			if (spacePosition == NULL) {
				fclose(pFilesystems);
				return ;
			}

			spacePosition++;
			fileSystemName = spacePosition;
			spacePosition = strchr(fileSystemName, ' ');
			if (spacePosition == NULL) {
				fclose(pFilesystems);
				return ;
			}

			spacePosition++;

			if (strncmp(spacePosition, "selinuxfs ", 10) != 0)
				continue;

			*(spacePosition -1) = 0;
			*g_pSelinuxFileSystemStringPointer = strdup(fileSystemName);
			break;
		} while (1);

		fclose(pFilesystems);
	}
}