当前位置: 首页 > news >正文

Linux中capability权能管理的实现

一、内核中Capabilities的详细分析及汇总

1.文件与目录权限相关

#define CAP_CHOWN 0

  • 允许修改文件所有者(chown)和组所有权(chgrp),无视 _POSIX_CHOWN_RESTRICTED 限制
  • 通常仅 root 用户默认拥有此能力

#define CAP_DAC_OVERRIDE 1

  • 允许进程完全忽略文件的 DAC 访问限制

#define CAP_DAC_READ_SEARCH 2

  • 允许进程忽略文件读及目录搜索的 DAC 访问限制

#define CAP_FOWNER 3

  • 允许进程忽略文件属主 ID 必须和进程用户 ID 相匹配的限制

#define CAP_FSETID 4

  • 允许在文件所有者变更时保留 S_ISUID/S_ISGID 位(chown 后不清除)
  • 允许进程设置文件的所有者 ID 而无需拥有特权

#define CAP_LEASE 28

  • 允许进程修改文件锁的 FL_LEASE 标志
  • FL_LEASE 标志是文件锁的一种类型,它允许进程在文件上建立租借锁(lease lock)
  • 租借锁是一种特殊的文件锁,允许锁的持有者在一定时间内独占对文件的访问权限

#define CAP_LINUX_IMMUTABLE 9

  • 允许修改文件的 S_IMMUTABLE(不可变)和 S_APPEND(仅追加)属性。
  • 通常仅 root 用户可设置这些标志

2. 进程与信号相关

#define CAP_KILL 5

  • 允许向任意进程发送信号(kill),无视目标进程的用户 ID 匹配限制。
  • 默认仅允许进程向同用户或更低权限进程发信号

#define CAP_SETUID 7

  • 允许修改进程的 UID(包括 setuid()setfsuid())。
  • 允许在 socket 凭证中伪造 PID

#define CAP_SETGID 6

  • 允许修改进程的 GID(包括 setgid()setgroups()
  • 允许在 socket 凭证中伪造 GID

#define CAP_SYS_NICE 23

  • 允许提升进程优先级(nice 值)、设置实时调度策略(如 SCHED_FIFO
  • 允许修改其他进程(不同 UID)的 CPU 亲和性

3. 网络相关

#define CAP_NET_BIND_SERVICE 10

  • 允许绑定到特权端口(<1024)的 TCP/UDP 套接字

#define CAP_NET_BROADCAST 11

  • 允许网络广播和多播(如 SO_BROADCAST 套接字选项)

#define CAP_NET_ADMIN 12

  • 允许配置网络接口、防火墙、路由表等
  • 包括修改 TOS(服务类型)、混杂模式、多播等

#define CAP_NET_RAW 13

  • 允许使用 RAW 和 PACKET 套接字(如 socket(AF_PACKET, SOCK_RAW, ...)
  • 可绕过传输层协议(直接访问链路层)

4. IPC 与内存管理

#define CAP_IPC_LOCK 14

  • 允许锁定共享内存段(mlock()mlockall()),防止交换到磁盘

#define CAP_IPC_OWNER 15

  • 绕过 IPC 对象(消息队列、信号量、共享内存)的所有权检查

#define CAP_SYS_RESOURCE 24

  • 覆盖资源限制(如 ulimit)、配额限制
  • 允许修改 IPC 消息队列大小、实时时钟中断频率等

5. 系统管理与特权操作

#define CAP_SYS_MODULE 16

  • 允许加载/卸载内核模块

#define CAP_SYS_RAWIO 17

  • 允许直接硬件访问

#define CAP_SYS_CHROOT 18

  • 允许使用 chroot() 更改根目录

#define CAP_SYS_PTRACE 19

  • 允许 ptrace() 调试任意进程

#define CAP_SYS_PACCT 20

  • 允许进程执行进程的 BSD 式审计
  • BSD 式审计是一种记录进程活动信息的机制,包括进程的启动时间、执行时间、资源使用情况等

#define CAP_SYS_ADMIN 21

  • 广义系统管理权限,包括:
    • 挂载/卸载文件系统(mount()umount())。
    • 修改磁盘配额、交换空间
    • 配置磁盘加密
    • 其他底层系统操作

#define CAP_SYS_BOOT 22

  • 允许调用 reboot() 重启系统

#define CAP_SYS_TIME 25

  • 允许修改系统时钟
  • 允许配置实时时钟

#define CAP_SYS_TTY_CONFIG 26

  • 允许配置 TTY 设备

#define CAP_MKNOD 27

  • 允许 mknod() 创建设备文件

6. 特殊能力

#define CAP_SETPCAP 8

  • 允许将自身能力集授予其他进程,或移除其他进程的能力
  • 用于权限提升或降权

二、capable检查是否具备指定权能

#define CAP_TO_MASK(x) (1 << (x))
#define cap_raised(c, flag)  (cap_t(c) & CAP_TO_MASK(flag))
int cap_capable (struct task_struct *tsk, int cap)
{/* Derived from include/linux/sched.h:capable. */if (cap_raised(tsk->cap_effective, cap))return 0;return -EPERM;
}int capable(int cap)
{if (security_ops->capable(current, cap)) {/* capability denied */return 0;}/* capability granted */current->flags |= PF_SUPERPRIV;return 1;
}

1. 宏定义和辅助函数

#define CAP_TO_MASK(x) (1 << (x))
#define cap_raised(c, flag)  (cap_t(c) & CAP_TO_MASK(flag))
  • CAP_TO_MASK(x):将权能编号转换为位掩码
    • 例如:CAP_CHOWN(0)1 << 0 = 0x00000001
    • CAP_DAC_OVERRIDE(1)1 << 1 = 0x00000002
  • cap_raised(c, flag):检查权能集 c 中是否设置了指定的权能 flag
    • 返回非零值表示有权能,返回0表示没有权能

2. cap_capable() 函数

int cap_capable(struct task_struct *tsk, int cap)
{/* Derived from include/linux/sched.h:capable. */if (cap_raised(tsk->cap_effective, cap))return 0;return -EPERM;
}
  • tsk:要检查的目标进程
  • cap:要检查的权能编号

返回值:

  • 0:有权能(成功)
  • -EPERM:没有权能(权限不足)

3. capable() 函数

int capable(int cap)
{if (security_ops->capable(current, cap)) {/* capability denied */return 0;}/* capability granted */current->flags |= PF_SUPERPRIV;return 1;
}
  • cap:要检查的权能编号

返回值:

  • 1:有权能(成功)
  • 0:没有权能(权限不足)

第1步:通过安全模块检查

if (security_ops->capable(current, cap)) {return 0;  // 安全模块拒绝
}
  • security_ops->capable:调用安全模块的权能检查钩子
  • 在默认的 capability 安全模块中,这会调用 cap_capable(current, cap)
  • 如果安全模块返回非零(通常是 -EPERM),表示权能被拒绝

第2步:标记特权使用

current->flags |= PF_SUPERPRIV;
return 1;
  • PF_SUPERPRIV:在进程标志中标记该进程使用了特权操作
  • 用于审计和调试目的,记录特权操作的使用

三、sys_capget系统调用实现

int cap_capget (struct task_struct *target, kernel_cap_t *effective,kernel_cap_t *inheritable, kernel_cap_t *permitted)
{/* Derived from kernel/capability.c:sys_capget. */*effective = cap_t (target->cap_effective);*inheritable = cap_t (target->cap_inheritable);*permitted = cap_t (target->cap_permitted);return 0;
}
static inline int security_capget (struct task_struct *target,kernel_cap_t *effective,kernel_cap_t *inheritable,kernel_cap_t *permitted)
{return cap_capget (target, effective, inheritable, permitted);
}
typedef struct __user_cap_data_struct {__u32 effective;__u32 permitted;__u32 inheritable;
} __user *cap_user_data_t;
asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
{int ret = 0;pid_t pid;__u32 version;task_t *target;struct __user_cap_data_struct data;if (get_user(version, &header->version))return -EFAULT;if (version != _LINUX_CAPABILITY_VERSION) {if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))return -EFAULT;return -EINVAL;}if (get_user(pid, &header->pid))return -EFAULT;if (pid < 0)return -EINVAL;spin_lock(&task_capability_lock);read_lock(&tasklist_lock);if (pid && pid != current->pid) {target = find_task_by_pid(pid);if (!target) {ret = -ESRCH;goto out;}} elsetarget = current;ret = security_capget(target, &data.effective, &data.inheritable, &data.permitted);out:read_unlock(&tasklist_lock);spin_unlock(&task_capability_lock);if (!ret && copy_to_user(dataptr, &data, sizeof data))return -EFAULT;return ret;
}

1. 核心功能函数

cap_capget() - 实际的权能获取函数

int cap_capget(struct task_struct *target, kernel_cap_t *effective,kernel_cap_t *inheritable, kernel_cap_t *permitted)
{/* Derived from kernel/capability.c:sys_capget. */*effective = cap_t(target->cap_effective);    // 获取有效权能集*inheritable = cap_t(target->cap_inheritable); // 获取可继承权能集  *permitted = cap_t(target->cap_permitted);    // 获取允许权能集return 0;
}

作用:直接从目标进程的 task_struct 中读取三个权能集合。

2. 安全模块封装

security_capget() - 安全模块接口

static inline int security_capget(struct task_struct *target,kernel_cap_t *effective,kernel_cap_t *inheritable, kernel_cap_t *permitted)
{return cap_capget(target, effective, inheritable, permitted);
}

作用:作为安全模块的钩子函数,在支持LSM(Linux Security Module)时可以被其他安全模块覆盖

3. 用户空间数据结构

cap_user_data_struct - 用户空间权能数据结构

typedef struct __user_cap_data_struct {__u32 effective;    // 有效权能位图__u32 permitted;    // 允许权能位图  __u32 inheritable;  // 可继承权能位图
} __user *cap_user_data_t;

作用:定义用户空间与内核空间传递权能数据的结构。

4. 系统调用主函数

sys_capget() - 系统调用入口

4.1.第1段:变量声明和初始化

asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
{int ret = 0;pid_t pid;__u32 version;task_t *target;struct __user_cap_data_struct data;  // 内核临时存储

分析

  • asmlinkage 表示参数通过栈传递,这是系统调用的标准调用约定
  • header:用户空间传递的权能头结构,包含版本号和目标PID
  • dataptr:用户空间用于接收权能数据的缓冲区指针
  • 在栈上声明 data 结构作为内核临时存储,避免直接操作用户空间内存

4.2.第2段:版本号获取和验证

    /* 1. 从用户空间获取版本号 */if (get_user(version, &header->version))return -EFAULT;/* 2. 版本兼容性检查 */if (version != _LINUX_CAPABILITY_VERSION) {if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))return -EFAULT;return -EINVAL;  // 版本不匹配}

分析

  • get_user():安全地从用户空间读取数据,失败返回 -EFAULT
  • 版本检查确保用户空间和内核使用相同的权能定义,避免语义不一致
  • 如果版本不匹配,先更新头结构中的版本号,再返回错误,这样用户空间可以知道正确的版本

4.3.第3段:目标PID获取和验证

    /* 3. 获取目标进程PID */if (get_user(pid, &header->pid))return -EFAULT;if (pid < 0)return -EINVAL;  // PID不能为负

分析

  • 从用户空间头结构中获取目标进程PID
  • PID有效性检查:Linux中PID必须是非负整数

4.4.第4段:锁保护机制

    /* 4. 加锁保护 */spin_lock(&task_capability_lock);read_lock(&tasklist_lock);

分析

  • task_capability_lock:自旋锁,保护权能相关的临界区
  • tasklist_lock:读写锁,保护进程列表的遍历操作

4.5.第5段:目标进程查找

    /* 5. 查找目标进程 */if (pid && pid != current->pid) {// 获取其他进程的权能target = find_task_by_pid(pid);if (!target) {ret = -ESRCH;  // 进程不存在goto out;}} else {// 获取当前进程的权能target = current;}
  • 三种情况处理
    1. pid == 0:获取当前进程权能
    2. pid == current->pid:获取当前进程权能
    3. pid != current->pid:获取其他进程权能
  • find_task_by_pid():在内核进程列表中查找指定PID的进程
  • 如果目标进程不存在,返回 -ESRCH (No such process)

4.5.第6段:权能获取核心操作

    /* 6. 调用安全模块获取权能 */ret = security_capget(target, &data.effective, &data.inheritable, &data.permitted);

分析

  • 调用安全模块钩子函数 security_capget()
  • 在支持LSM(Linux Security Module)时钩子函数可以被其他函数覆盖

4.6.第7段:锁释放和清理

out:/* 7. 释放锁 */read_unlock(&tasklist_lock);spin_unlock(&task_capability_lock);

4.7.第8段:结果返回用户空间

    /* 8. 将结果拷贝回用户空间 */if (!ret && copy_to_user(dataptr, &data, sizeof data))return -EFAULT;return ret;
}

分析

  • 只有在前面操作成功(ret == 0)时才拷贝数据
  • copy_to_user():安全地将内核数据拷贝到用户空间,失败返回 -EFAULT
  • 最终返回码:
    • 0:成功
    • -EFAULT:用户空间内存访问错误
    • -EINVAL:参数无效
    • -ESRCH:目标进程不存在
    • 其他:安全模块返回的错误码

四、security_capset_set权能设置操作

void cap_capset_set (struct task_struct *target, kernel_cap_t *effective,kernel_cap_t *inheritable, kernel_cap_t *permitted)
{target->cap_effective = *effective;target->cap_inheritable = *inheritable;target->cap_permitted = *permitted;
}
static inline void security_capset_set (struct task_struct *target,kernel_cap_t *effective,kernel_cap_t *inheritable,kernel_cap_t *permitted)
{cap_capset_set (target, effective, inheritable, permitted);
}

设置目标进程的三个权能集

五、cap_set_pg设置进程组所有成员权能

static inline void cap_set_pg(int pgrp, kernel_cap_t *effective,kernel_cap_t *inheritable,kernel_cap_t *permitted)
{task_t *g, *target;do_each_task_pid(pgrp, PIDTYPE_PGID, g) {target = g;while_each_thread(g, target)security_capset_set(target, effective, inheritable, permitted);} while_each_task_pid(pgrp, PIDTYPE_PGID, g);
}

1.函数原型和参数

static inline void cap_set_pg(int pgrp, kernel_cap_t *effective,kernel_cap_t *inheritable, kernel_cap_t *permitted)

参数说明

  • pgrp:进程组ID
  • effective:要设置的有效权能集
  • inheritable:要设置的可继承权能集
  • permitted:要设置的允许权能集

2.函数实现分析

2.1. 变量声明

task_t *g, *target;
  • g:进程组组长进程指针
  • target:当前正在处理的进程指针

2.2. 外层循环:遍历进程组

do_each_task_pid(pgrp, PIDTYPE_PGID, g) {

作用

  • 根据进程组ID pgrp 查找该进程组的所有进程
  • PIDTYPE_PGID 表示按进程组ID查找
  • 这个循环会遍历进程组中的每个进程

2.3. 内层循环:遍历线程组

while_each_thread(g, target)security_capset_set(target, effective, inheritable, permitted);

作用

  • 对于进程组中的每个进程,遍历其所有线程
  • target 遍历该线程组的所有线程
  • 对每个线程调用 security_capset_set() 设置权能

六、cap_set_all设置所有线程权能

static inline void cap_set_all(kernel_cap_t *effective,kernel_cap_t *inheritable,kernel_cap_t *permitted)
{task_t *g, *target;do_each_thread(g, target) {if (target == current || target->pid == 1)continue;security_capset_set(target, effective, inheritable, permitted);} while_each_thread(g, target);
}

1.函数定义

static inline void cap_set_all(kernel_cap_t *effective,kernel_cap_t *inheritable,kernel_cap_t *permitted)

为系统中除当前线程(current)和 init 进程(pid == 1)外的所有线程设置能力集(Capabilities)

  • 参数
    • effective:指向 kernel_cap_t 的指针,表示要设置的 Effective 能力集(进程实际可用的能力)
    • inheritable:指向 kernel_cap_t 的指针,表示要设置的 Inheritable 能力集(可被子进程继承的能力)
    • permitted:指向 kernel_cap_t 的指针,表示要设置的 Permitted 能力集(进程可拥有的最大能力集合)

2.代码逻辑解析

2.1. 遍历所有线程

task_t *g, *target;
do_each_thread(g, target) { ... } while_each_thread(g, target);

2.2.跳过当前线程和 init 进程

if (target == current || target->pid == 1)continue;
  • current:当前正在执行的线程,直接修改其能力集可能导致权限提升或不稳定
  • pid == 1init 进程):是系统关键进程,通常需要保持最高权限(如 CAP_SYS_ADMIN),修改其能力集可能影响系统稳定性

七、security_capset_check权能设置安全检查

#define cap_t(x) (x).cap
#define cap_issubset(a,set)  (!(cap_t(a) & ~cap_t(set))
static inline kernel_cap_t cap_combine(kernel_cap_t a, kernel_cap_t b)
{kernel_cap_t dest;cap_t(dest) = cap_t(a) | cap_t(b);return dest;
}
int cap_capset_check (struct task_struct *target, kernel_cap_t *effective,kernel_cap_t *inheritable, kernel_cap_t *permitted)
{/* Derived from kernel/capability.c:sys_capset. *//* verify restrictions on target's new Inheritable set */if (!cap_issubset (*inheritable,cap_combine (target->cap_inheritable,current->cap_permitted))) {return -EPERM;}/* verify restrictions on target's new Permitted set */if (!cap_issubset (*permitted,cap_combine (target->cap_permitted,current->cap_permitted))) {return -EPERM;}/* verify the _new_Effective_ is a subset of the _new_Permitted_ */if (!cap_issubset (*effective, *permitted)) {return -EPERM;}return 0;
}
static inline int security_capset_check (struct task_struct *target,kernel_cap_t *effective,kernel_cap_t *inheritable,kernel_cap_t *permitted)
{return cap_capset_check (target, effective, inheritable, permitted);
}

1. 宏定义与辅助函数

1.1.cap_t(x)cap_issubset(a, set)

#define cap_t(x) (x).cap
#define cap_issubset(a, set) (!(cap_t(a) & ~cap_t(set)))
  • cap_t(x)

    提取kernel_cap_t结构体中的cap字段(实际存储能力位掩码的值)

  • cap_issubset(a, set)

    检查能力集a是否在set的子集

    !(a & ~set)
    
    • ~set:取 set 的补集(即 set 没有的能力)。
    • a & ~set:如果结果非零,说明 a 包含 set 没有的能力,即 a 不是 set 的子集
    • ! 取反,返回 1(是子集)或 0(不是子集)。

1.2.cap_combine(a, b)

static inline kernel_cap_t cap_combine(kernel_cap_t a, kernel_cap_t b) {kernel_cap_t dest;cap_t(dest) = cap_t(a) | cap_t(b);return dest;
}
  • 作用:合并两个能力集 ab(按位或操作)

2.cap_capset_check()

int cap_capset_check(struct task_struct *target, kernel_cap_t *effective,kernel_cap_t *inheritable, kernel_cap_t *permitted)
{/* 1. 检查 target 的新 Inheritable 集是否合法 */if (!cap_issubset(*inheritable,cap_combine(target->cap_inheritable,current->cap_permitted))) {return -EPERM;}/* 2. 检查 target 的新 Permitted 集是否合法 */if (!cap_issubset(*permitted,cap_combine(target->cap_permitted,current->cap_permitted))) {return -EPERM;}/* 3. 检查新的 Effective 集是否是新 Permitted 集的子集 */if (!cap_issubset(*effective, *permitted)) {return -EPERM;}return 0; // 所有检查通过
}

2.1.Inheritable 能力集检查

  • 规则*inheritable 必须是 target 原有 inheritablecurrent(调用者)的 permitted 的并集的子集
  • 目的:防止进程将自身没有的能力传递给其他进程的 inheritable
  • 示例
    • target->cap_inheritable = { CAP_KILL }
    • current->cap_permitted = { CAP_SYS_ADMIN }
    • *inheritable 最多只能是 { CAP_KILL | CAP_SYS_ADMIN } 的子集

2.2.Permitted 能力集检查

  • 规则*permitted 必须是 target 原有 permittedcurrentpermitted 的并集的子集。
  • 目的:防止进程提升其他进程的 permitted 集(即使调用者有权限,也不能随意扩大目标进程的能力)

2.3.Effective 能力集检查

  • 规则*effective 必须是 *permitted 的子集
  • 目的:确保进程不能启用自身没有的能力(即 effective 不能超出 permitted

3.security_capset_check()

static inline int security_capset_check(struct task_struct *target,kernel_cap_t *effective,kernel_cap_t *inheritable,kernel_cap_t *permitted)
{return cap_capset_check(target, effective, inheritable, permitted);
}
  • 作用
    security_capset_checkcap_capset_check 的简单封装,为了兼容 LSM(Linux Security Module)框架

4. 安全检查的核心原则

  1. 权限继承限制
    • 进程只能将自身拥有的能力传递给其他进程的 inheritable
  2. Permitted 集限制
    • 进程不能随意扩大其他进程的 permitted 集,只能缩小或保持不变(除非调用者有更高权限)
  3. Effective 集限制
    • 进程不能启用自身没有的能力(即 effective 必须 ≤ permitted

八、sys_capset系统调用实现

asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
{kernel_cap_t inheritable, permitted, effective;__u32 version;task_t *target;int ret;pid_t pid;if (get_user(version, &header->version))return -EFAULT;if (version != _LINUX_CAPABILITY_VERSION) {if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))return -EFAULT;return -EINVAL;}if (get_user(pid, &header->pid))return -EFAULT;if (pid && !capable(CAP_SETPCAP))return -EPERM;if (copy_from_user(&effective, &data->effective, sizeof(effective)) ||copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) ||copy_from_user(&permitted, &data->permitted, sizeof(permitted)))return -EFAULT;spin_lock(&task_capability_lock);read_lock(&tasklist_lock);if (pid > 0 && pid != current->pid) {target = find_task_by_pid(pid);if (!target) {ret = -ESRCH;goto out;}} elsetarget = current;ret = -EPERM;if (security_capset_check(target, &effective, &inheritable, &permitted))goto out;if (!cap_issubset(inheritable, cap_combine(target->cap_inheritable,current->cap_permitted)))goto out;/* verify restrictions on target's new Permitted set */if (!cap_issubset(permitted, cap_combine(target->cap_permitted,current->cap_permitted)))goto out;/* verify the _new_Effective_ is a subset of the _new_Permitted_ */if (!cap_issubset(effective, permitted))goto out;ret = 0;/* having verified that the proposed changes are legal,we now put them into effect. */if (pid < 0) {if (pid == -1)  /* all procs other than current and init */cap_set_all(&effective, &inheritable, &permitted);else            /* all procs in process group */cap_set_pg(-pid, &effective, &inheritable, &permitted);} else {security_capset_set(target, &effective, &inheritable, &permitted);}out:read_unlock(&tasklist_lock);spin_unlock(&task_capability_lock);return ret;
}

1.第1段:变量声明和版本检查

asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
{kernel_cap_t inheritable, permitted, effective;__u32 version;task_t *target;int ret;pid_t pid;if (get_user(version, &header->version))return -EFAULT;if (version != _LINUX_CAPABILITY_VERSION) {if (put_user(_LINUX_CAPABILITY_VERSION, &header->version))return -EFAULT;return -EINVAL;}

分析

  • 声明内核空间的权能集变量用于临时存储
  • 版本检查确保用户空间和内核使用相同的权能定义
  • 如果版本不匹配,更新头结构版本号并返回错误

2.第2段:PID获取和权限检查

     if (get_user(pid, &header->pid))return -EFAULT;if (pid && !capable(CAP_SETPCAP))return -EPERM;

分析

  • 获取目标进程PID
  • 关键权限检查
    • 如果 pid != 0(设置其他进程的权能),需要 CAP_SETPCAP 权能
    • 如果 pid == 0(设置当前进程权能),不需要特殊权限

3.第3段:从用户空间拷贝权能数据

     if (copy_from_user(&effective, &data->effective, sizeof(effective)) ||copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) ||copy_from_user(&permitted, &data->permitted, sizeof(permitted)))return -EFAULT;

分析

  • 安全地将用户空间传递的权能数据拷贝到内核空间
  • 三个权能集:有效集、可继承集、允许集
  • 任何拷贝失败都返回 -EFAULT

4.第4段:加锁和目标进程查找

     spin_lock(&task_capability_lock);read_lock(&tasklist_lock);if (pid > 0 && pid != current->pid) {target = find_task_by_pid(pid);if (!target) {ret = -ESRCH;goto out;}} elsetarget = current;

分析

  • 双重锁保护:自旋锁保护权能操作,读写锁保护进程列表
  • 目标进程查找逻辑:
    • pid > 0 且 pid != current->pid:查找其他进程
    • 其他情况:目标为当前进程
  • 如果指定PID的进程不存在,返回 -ESRCH

5.第5段:权能设置合法性验证

     ret = -EPERM;if (security_capset_check(target, &effective, &inheritable, &permitted))goto out;if (!cap_issubset(inheritable, cap_combine(target->cap_inheritable,current->cap_permitted)))goto out;/* verify restrictions on target's new Permitted set */if (!cap_issubset(permitted, cap_combine(target->cap_permitted,current->cap_permitted)))goto out;/* verify the _new_Effective_ is a subset of the _new_Permitted_ */if (!cap_issubset(effective, permitted))goto out;ret = 0;

5.1. 安全模块检查

security_capset_check(target, &effective, &inheritable, &permitted)
  • 调用安全模块进行额外的安全检查

5.2. 可继承集限制检查

!cap_issubset(inheritable, cap_combine(target->cap_inheritable, current->cap_permitted))

规则:新的可继承集 ⊆ (目标原有可继承集 ∪ 当前进程允许集)

  • 防止当前进程授予目标进程超出自己权限的可继承权能

5.3. 允许集限制检查

!cap_issubset(permitted, cap_combine(target->cap_permitted, current->cap_permitted))

规则:新的允许集 ⊆ (目标原有允许集 ∪ 当前进程允许集)

  • 防止当前进程授予目标进程超出自己权限的允许权能

5.4. 有效集与允许集一致性检查

!cap_issubset(effective, permitted)

规则:新的有效集 ⊆ 新的允许集

  • 确保有效权能不会超过允许的权能范围

6.第6段:实际应用权能设置

     /* having verified that the proposed changes are legal,we now put them into effect. */if (pid < 0) {if (pid == -1)  /* all procs other than current and init */cap_set_all(&effective, &inheritable, &permitted);else            /* all procs in process group */cap_set_pg(-pid, &effective, &inheritable, &permitted);} else {security_capset_set(target, &effective, &inheritable, &permitted);}

根据PID值的不同,有三种设置模式:

6.1. pid > 0:设置单个进程

security_capset_set(target, &effective, &inheritable, &permitted)

6.2. pid == -1:设置所有进程(除当前进程和init进程)

cap_set_all(&effective, &inheritable, &permitted)

6.3. pid < -1:设置整个进程组

cap_set_pg(-pid, &effective, &inheritable, &permitted)

7.第7段:清理和返回

out:read_unlock(&tasklist_lock);spin_unlock(&task_capability_lock);return ret;
}

分析

  • 对称释放锁资源
  • 返回操作结果:
    • 0:成功
    • -EPERM:权限不足或验证失败
    • -ESRCH:目标进程不存在
    • -EFAULT:用户空间内存访问错误
    • -EINVAL:版本不匹配或参数无效
http://www.dtcms.com/a/449540.html

相关文章:

  • Python 语法与注释详解
  • joomla 网站建设教程合肥网站推广公司
  • 介绍一个做美食的网站网店网站技术方案
  • 电源——BUCK电路设计实战
  • wordpress点击页面跳转通辽做网站通过seo来赚钱
  • Git 分支完整操作指南
  • 英伟达:人类反馈与可验证奖励相结合
  • claude code + GLM模型 入门
  • linux-1
  • Docker 三剑客:镜像、容器、仓库
  • 有哪些做二手的网站排名好的网站关键词优化企业
  • FPGA驱动LTC1856 ADC芯片
  • 应用层:Http、Https
  • ARMv8系统的安全性(一):安全目标是什么?
  • Flink 作业测试依赖、MiniCluster、DataStream 与 Table/SQL 上手
  • 如何分析对手网站关键词免费logo在线制作字体logo
  • 如何设计优秀的银行数字化转型培训方案
  • redis的主从模式的复制
  • 如何网站做淘客怎样建立
  • 购物网站的功能板块wordpress ajax 评论翻页
  • 齐博cms重庆百度搜索优化
  • 大模型原理与实践:第四章-大语言模型_第2部分-LLM预训练、监督微调、强化学习
  • Flutter SingleChildScrollView 使用详解
  • 中秋特别篇:使用QtOpenGL和着色器绘制星空与满月
  • Easysearch 索引别名(Index Alias)详解
  • 安徽省港航建设投资集团网站wordpress图片清晰度
  • 网站交互性企业营销型网站建设规划
  • 无锡设计网站公司微信小程序登录流程
  • GraphQL 工程化篇 I - REST vs GraphQL 的取舍与基础配置
  • springboot二手儿童绘本交易系统设计与实现(代码+数据库+LW)