Linux下的文件权限分类:
-
Discretionary Access Control (DAC) 自主访问控制权限
DAC又分为两类权限:
- 经典的UNIX样式权限检查: 将当前进程UID和GID与正在访问的文件的UID和GID进行比较,以确定已设置的模式(读/写/执行)
- POSIX Access Control Lists (ACL)
-
Mandatory Access Control (MAC) 基于策略的访问控制
- selinux
本文聚焦于 经典的UNIX样式权限检查
核心知识图:
此文重点介绍,不同App进程,在/sdcard/Android/data 目录下的文件,group 为什么都是 ext_data_rw ,而不是自己进程的gid
sdcard 几种目录权限 全览:
xxxxxx:/ # cd sdcard/
kaiser:/sdcard # ll
total 81
drwx------ 2 u0_a229 u0_a229 3452 2021-04-26 05:26 Alarms
drwxrws--x 6 media_rw media_rw 3452 2021-05-19 16:44 Android
drwx------ 2 u0_a229 u0_a229 3452 2021-04-26 05:26 Audiobooks
drwx------ 4 u0_a229 u0_a229 3452 2021-05-13 15:59 DCIM
drwx------ 2 u0_a229 u0_a229 3452 2021-04-26 05:26 Documents
drwx------ 3 u0_a229 u0_a229 3452 2021-05-18 17:26 Download
drwx------ 5 u0_a229 u0_a229 3452 2021-05-06 21:12 MIUI
drwx------ 3 u0_a229 u0_a229 3452 2021-04-26 05:26 Movies
drwx------ 4 u0_a229 u0_a229 3452 2021-05-06 20:40 Music
drwx------ 2 u0_a229 u0_a229 3452 2021-04-26 05:26 Notifications
drwx------ 3 u0_a229 u0_a229 3452 2021-04-26 05:26 Pictures
drwx------ 5 u0_a229 u0_a229 3452 2021-05-20 10:35 Tencent
xxxxxx:/sdcard # cd Android/
xxxxxx:/sdcard/Android # ll
total 20
-rw------- 1 u0_a229 media_rw 33 2021-05-19 16:44 24ea15
-rw------- 1 u0_a229 media_rw 34 2021-05-19 16:44 aa3dcb
drwxrws--x 40 media_rw ext_data_rw 3452 2021-05-19 16:44 data
drwxrws--x 3 media_rw media_rw 3452 2021-04-26 05:28 media
drwxrws--x 2 media_rw ext_obb_rw 3452 2021-05-12 11:11 obb
drwx--S--- 3 u0_a229 media_rw 3452 2021-05-18 18:17 obj
xxxxxx:/sdcard/Android # cd data/
xxxxxx:/sdcard/Android/data # ll
total 114
drwxrws--- 3 u0_a116 ext_data_rw 3452 2021-04-26 05:28 com.android.calendar
drwxrws--- 4 u0_a106 ext_data_rw 3452 2021-04-26 05:28 com.android.camera
drwxrws--- 3 u0_a168 ext_data_rw 3452 2021-05-07 17:00 com.android.fileexplorer
drwxrws--- 3 u0_a110 ext_data_rw 3452 2021-05-06 14:26 com.android.mms
drwx--S--- 3 u0_a71 ext_data_rw 3452 2021-04-26 05:26 com.android.providers.downloads
drwxrws--- 4 u0_a171 ext_data_rw 3452 2021-04-27 09:49 com.blackshark.bsaccount
libc中有这样一个函数:
// 头文件
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *file_name, struct stat *buf);
调用此函数会对 stat 结构体赋值:
struct stat
{
dev_t st_dev; /* ID of device containing file -文件所在设备的ID*/
ino_t st_ino; /* inode number -inode节点号*/
mode_t st_mode; /* 文件的类型和存取的权限*/
nlink_t st_nlink; /* number of hard links -链向此文件的连接数(硬连接)*/
uid_t st_uid; /* user ID of owner -user id*/
gid_t st_gid; /* group ID of owner - group id*/
dev_t st_rdev; /* device ID (if special file) -设备号,针对设备文件*/
off_t st_size; /* total size, in bytes -文件大小,字节为单位*/
blksize_t st_blksize; /* blocksize for filesystem I/O -系统块的大小*/
blkcnt_t st_blocks; /* number of blocks allocated -文件所占块数*/
time_t st_atime; /* time of last access -最近存取时间*/
time_t st_mtime; /* time of last modification -最近修改时间*/
time_t st_ctime; /* time of last status change - */
};
此结构体中有个 mode_t 类型的数据 st_mode,st_mode是个32位的整型变量:
其低16位的含义如图:
8进制下不同数值的含义
// 0170000 第一个0表示八进制。17转为十进制是15,是15位权限控制的最高4位。这四位的最大值0b1111,十进制为15,八进制表示法是017。
S_IFMT 0170000 文件类型的位遮罩
S_IFSOCK 0140000 socket
S_IFLNK 0120000 符号链接(symbolic link)
S_IFREG 0100000 一般文件
S_IFBLK 0060000 区块装置(block device)
S_IFDIR 0040000 目录
S_IFCHR 0020000 字符装置(character device)
S_IFIFO 0010000 先进先出(fifo)
S_ISUID 0004000 文件的(set user-id on execution)位
S_ISGID 0002000 文件的(set group-id on execution)位
S_ISVTX 0001000 文件的sticky位
S_IRWXU 00700 文件所有者的遮罩值(即所有权限值)
S_IRUSR 00400 文件所有者具可读取权限
S_IWUSR 00200 文件所有者具可写入权限
S_IXUSR 00100 文件所有者具可执行权限
S_IRWXG 00070 用户组的遮罩值(即所有权限值)
S_IRGRP 00040 用户组具可读取权限
S_IWGRP 00020 用户组具可写入权限
S_IXGRP 00010 用户组具可执行权限
S_IRWXO 00007 其他用户的遮罩值(即所有权限值)
S_IROTH 00004 其他用户具可读取权限
S_IWOTH 00002 其他用户具可写入权限
S_IXOTH 00001 其他用户具可执行权限
摘自《Linux C 函数库参考手册》
权限示例:0100724
// 看下 0 10 0 724 这个每个数值的含义:
/*
第一个0 表示8进制
10 表示文件类型为 一般文件,8进制下文件类型占据两个8位
第二个0 特殊权限UGT权限位
724 表示文件所有者具有全部权限,用户组具有写权限,其他用户具有读权限
*/
文件权限与进程的关系:
进程所属的user、group、groups 需要有与文件有相应的权限才能访问文件:
xxxxxx: # ps -elZ | grep media.module
u:r:mediaprovider_app:s0:c229,c256,c512,c768 5 S 10229 4011 839 0 29 -10 64 1395645 do_epoll_wait ? 00:01:52 rs.media.module
xxxxxx: # ps -p 4011
USER PID PPID VSZ RSS WCHAN ADDR S NAME
u0_a229 4011 839 5582580 144136 do_epoll_+ 0 S com.android.providers.media.module
xxxxxx: # cat /proc/4011/status
Name: rs.media.module
Umask: 0077
State: S (sleeping)
Tgid: 4011
Ngid: 0
Pid: 4011
PPid: 839
TracerPid: 0
Uid: 10229 10229 10229 10229 # 进程所属的 user
Gid: 10229 10229 10229 10229 # 进程当前工作的 group
FDSize: 256
Groups: 1015 1023 1065 1077 1078 1079 3007 9997 20229 50229 99909997 # 进程所属其他 group
xxxxxx:/ # id media_rw
uid=1023(media_rw) gid=1023(media_rw) groups=1023(media_rw) context=u:r:su:s0
# /sdcard/Android/media 的权限
drwxrws--x 3 media_rw media_rw 3452 2021-04-26 05:28 media
media_rw 用户进程,或者属于 media_rw 用户组的进程具有 /sdcard/Android/media 目录的读写权限
mediaprovider 进程不属于 media_rw 用户,当前工作的group为10229,也不属于media_rw,但是其Groups中有1023(media_rw)用户组,
因此 mediaprovider 进程具有 media 文件的读写访问权限
特殊权限位:
示例:
xxxxxx:~/work$ ls -l
total 157600
drwsrwSrwt 33 xxxxxx xxxxxx 4096 Feb 19 20:57 testfile
SUID
用SUID肯定满足一下几点: 1.SUID只对二进制文件有效 2.调用者对该文件有执行权 3.在执行过程中,调用者会暂时获得该文件的所有者权限 4.该权限只在程序执行的过程中有效
xxxxxx:~/work$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 47032 Jan 27 2016 /usr/bin/passwd
# 通过 passwd 进程修改密码,会修改 /etc/shadow 文件,但是普通用户没有权限
# 有了 SUID 位,调用者具有了 passwd所有者root的权限,因此可以写 /etc/shadow 文件
xxxxxx:~/work$ ls -l /etc/shadow
-rw-r----- 1 root shadow 1770 May 12 15:30 /etc/shadow
SGID
- 它作用于普通文件时,和SUID类似,在执行该文件时,用户将获得该文件所属组的权限。
- 当SGID作用于目录时:
- 前提,当用户对某一目录有写和执行权限时,该用户就可以在该目录下建立文件
- 如果该目录用SGID修饰,则该用户在这个目录下建立的文件都是属于这个目录所属的组。
SBIT
- 只能用来修饰一个目录。
- 当某一个目录拥有SBIT权限时,则任何一个能够在这个目录下建立文件的用户,该用户在这个目录下所建立的文件,
- 只有该用户自己和root可以删除,其他用户均不可以。
解释/sdcard/Android/data 目录:
- 手机在开机的时候会在 /sdcard/Android 默认创建 data 和 obb 目录
- 这两个目录的权限都是 drwxrws--x media_rw ext_data_rw
- 因为group位带有s权限,所以任何进程在这俩目录下创建的文件group都是 ext_data_rw
附:Android文件权限检查图:
其他 ACL 权限
/sdcard/Android/data /sdcard/Android/obb 这两个目录在Android上有 ACL权限 相关的代码,但是代码有没有运行,还不确定。