转自:https://blog.csdn.net/wangpengqi/article/details/9821227

一)概述:1)从2.1版开始,Linux内核有了能力(capability)的概念,即它打破了UNIX/LINUX操作系统中超级用户/普通用户的概念,由普通用户也可以做只有超级用户可以完成的工作.
2)capability可以作用在进程上(受限),也可以作用在程序文件上,它与sudo不同,sudo只针对用户/程序/文件的概述,即sudo可以配置某个用户可以执行某个命令,可以更改某个文件,而capability是让某个程序拥有某种能力,例如:
capability让/tmp/testkill程序可以kill掉其它进程,但它不能mount设备节点到目录,也不能重启系统,因为我们只指定了它kill的能力,即使程序有问题也不会超出能力范围.
3)每个进程有三个和能力有关的位图:inheritable(I),permitted(P)和effective(E),对应进程描述符task_struct(include/linux/sched.h)里面的cap_effective, cap_inheritable, cap_permitted,所以我们可以查看/proc/PID/status来查看进程的能力.
4)cap_effective:当一个进程要进行某个特权操作时,操作系统会检查cap_effective的对应位是否有效,而不再是检查进程的有效UID是否为0.
例如,如果一个进程要设置系统的时钟,Linux的内核就会检查cap_effective的CAP_SYS_TIME位(第25位)是否有效.
5)cap_permitted:表示进程能够使用的能力,在cap_permitted中可以包含cap_effective中没有的能力,这些能力是被进程自己临时放弃的,也可以说cap_effective是cap_permitted的一个子集.
6)cap_inheritable:表示能够被当前进程执行的程序继承的能力.二)capability的设定与清除我们在下面的程序中给当前的进程设定能力,最后我们清除掉所设定的能力,源程序如下:#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <unistd.h>#undef _POSIX_SOURCE#include <sys/capability.h>extern int errno;void whoami(void){printf("uid=%i  euid=%i  gid=%i\n", getuid(), geteuid(), getgid());}void listCaps(){cap_t caps = cap_get_proc();ssize_t y = 0;printf("The process %d was give capabilities %s\n",(int) getpid(), cap_to_text(caps, &y));fflush(0);cap_free(caps);}int main(int argc, char **argv){int stat;whoami();stat = setuid(geteuid());pid_t parentPid = getpid();if(!parentPid)return 1;cap_t caps = cap_init();cap_value_t capList[5] ={ CAP_NET_RAW, CAP_NET_BIND_SERVICE , CAP_SETUID, CAP_SETGID,CAP_SETPCAP } ;unsigned num_caps = 5;cap_set_flag(caps, CAP_EFFECTIVE, num_caps, capList, CAP_SET);cap_set_flag(caps, CAP_INHERITABLE, num_caps, capList, CAP_SET);cap_set_flag(caps, CAP_PERMITTED, num_caps, capList, CAP_SET);if (cap_set_proc(caps)) {perror("capset()");return EXIT_FAILURE;}listCaps();printf("dropping caps\n");cap_clear(caps);  // resetting caps storageif (cap_set_proc(caps)) {perror("capset()");return EXIT_FAILURE;}listCaps();cap_free(caps);return 0;}编译:
gcc capsettest.c -o capsettest -lcap运行:
./capsettest
uid=0  euid=0  gid=0
The process 2383 was give capabilities = cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw+eip
dropping caps
The process 2383 was give capabilities =注:
1)我们对该进程增加了5种能力,随后又清除了所有能力.
2)首先通过cap_init()初始化存放cap能力值的状态,随后通过cap_set_flag函数的调用,将三种位图的能力设置给了变量caps,再通过cap_set_proc(caps)设定当前进程的能力值,通过cap_get_proc()返回当前进程的能力值,最后通过cap_free(caps)释放能力值.
3)cap_set_flag函数的原型是:
int cap_set_flag(cap_t cap_p, cap_flag_t flag, int ncap,const cap_value_t *caps, cap_flag_value_t value);我们这里的调用语句是:cap_set_flag(caps, CAP_PERMITTED, num_caps, capList, CAP_SET);
第一个参数cap_p是存放能力值的变量,是被设定值.这里是caps.
第二个参数flag是是三种能力位图,这里是CAP_PERMITTED.
第三个参数ncap是要设定能力的个数,这里是num_caps,也就是5.
第四个参数*caps是要设定的能力值,这里是capList数组,也就是CAP_NET_RAW, CAP_NET_BIND_SERVICE , CAP_SETUID, CAP_SETGID,CAP_SETPCAP.
第五个参数value是决定要设定还是清除,这里是CAP_SET.4)cap_set_proc函数的原型是:int cap_set_proc(cap_t cap_p);
cap_set_proc函数通过cap_p中的能力值设定给当前的进程.5)cap_get_proc函数的原型是:cap_t cap_get_proc(void);
cap_get_proc函数返回当前进程的能力值给cap变量.6)cap_free函数的原型是:cap_free(caps);
cap_free函数清理/释放cap变量.7)如果我们fork()了子进程,那么子进程继承父进程的所有能力.8)不能单独设定CAP_EFFECTIVE,CAP_INHERITABLE位图,必须要和CAP_PERMITTED联用,且CAP_PERMITTED一定要是其它两个位图的超集.9)如果两次调用cap_set_proc函数,第二次调用的值力值不能少于或多于第一次调用.如第一次我们授权chown,setuid能力,第二次只能是chown,setuid不能是其它的能力值.10)普通用户不能给进程设定能力.三)进程的能力掩码:
我们可以通过下面的程序获取当前进程的掩码,它是通过capget函数来获取指定进程的能力掩码,当然我们也可以用capset来设定掩码,下面获取掩码的体现:#undef _POSIX_SOURCE#include <stdlib.h>#include <stdio.h>#include <sys/types.h>#include <unistd.h>#include <linux/capability.h>#include <errno.h>int main(){struct __user_cap_header_struct cap_header_data;cap_user_header_t cap_header = &cap_header_data;struct __user_cap_data_struct cap_data_data;cap_user_data_t cap_data = &cap_data_data;cap_header->pid = getpid();cap_header->version = _LINUX_CAPABILITY_VERSION_1;if (capget(cap_header, cap_data) < 0) {perror("Failed capget");exit(1);}printf("Cap data 0x%x, 0x%x, 0x%x\n", cap_data->effective,cap_data->permitted, cap_data->inheritable);}gcc capget0.c -o capget0 -lcap普通用户:
./capget0
Cap data 0x0, 0x0, 0x0超级用户:
/home/test/capget0
Cap data 0xffffffff, 0xffffffff, 0x0这也说明了默认情况下,root运行的进程是什么权限都有,而普通用户则什么权限都没有.我们可以将本程序与上面的程序进行整合,如下:#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <unistd.h>#undef _POSIX_SOURCE#include <sys/capability.h>extern int errno;void whoami(void){printf("uid=%i  euid=%i  gid=%i\n", getuid(), geteuid(), getgid());}void listCaps(){cap_t caps = cap_get_proc();ssize_t y = 0;printf("The process %d was give capabilities %s\n",(int) getpid(), cap_to_text(caps, &y));fflush(0);cap_free(caps);}int main(int argc, char **argv){int stat;whoami();stat = setuid(geteuid());pid_t parentPid = getpid();if(!parentPid)return 1;cap_t caps = cap_init();cap_value_t capList[5] ={ CAP_NET_RAW, CAP_NET_BIND_SERVICE , CAP_SETUID, CAP_SETGID,CAP_SETPCAP } ;unsigned num_caps = 5;cap_set_flag(caps, CAP_EFFECTIVE, num_caps, capList, CAP_SET);cap_set_flag(caps, CAP_INHERITABLE, num_caps, capList, CAP_SET);cap_set_flag(caps, CAP_PERMITTED, num_caps, capList, CAP_SET);if (cap_set_proc(caps)) {perror("capset()");return EXIT_FAILURE;}listCaps();cap_free(caps);struct __user_cap_header_struct cap_header_data;cap_user_header_t cap_header = &cap_header_data;struct __user_cap_data_struct cap_data_data;cap_user_data_t cap_data = &cap_data_data;cap_header->pid = getpid();cap_header->version = _LINUX_CAPABILITY_VERSION_1;if (capget(cap_header, cap_data) < 0) {perror("Failed capget");exit(1);}printf("Cap data 0x%x, 0x%x, 0x%x\n", cap_data->effective,cap_data->permitted, cap_data->inheritable);sleep(60);return 0;}编译并执行:
gcc capsettest.c -o capsettest -lcap./capsettest
uid=0  euid=0  gid=0
The process 3101 was give capabilities = cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw+eip
Cap data 0x25c0, 0x25c0, 0x25c0注:0x25c0=10 0101 1100 0000(二进制)
对映的能力如下:
cap_setgid=6(位)
cap_setuid=7(位)
cap_setpcap=8(位)
cap_net_bind_service=10(位)
cap_net_raw=13(位)在程序sleep的时候,我们查看一下进程的status,如下:
cat /proc/`pgrep capsettest`/status略
CapInh: 00000000000025c0
CapPrm: 00000000000025c0
CapEff: 00000000000025c0
CapBnd: ffffffffffffffff
略我们看到进程的status也反映了它的能力状态.
CapBnd是系统的边界能力,我们无法改变它.

转载于:https://www.cnblogs.com/sky-heaven/p/9481310.html

Linux的capability深入分析(1)【转】相关推荐

  1. Linux的capability深入分析(2)

    一)capability的工具介绍 在我们的试验环境是RHEL6,libcap-2.16软件包中包含了相关的capability设置及查看工作,如下: rpm -ql libcap-2.16-5.2. ...

  2. Linux的capability深入分析(1)

    一)概述: 1)从2.1版开始,Linux内核有了能力(capability)的概念,即它打破了UNIX/LINUX操作系统中超级用户/普通用户的概念,由普通用户也可以做只有超级用户可以完成的工作. ...

  3. Linux的奖励机制是啥意思,Linux能力(capability)机制的继承

    1.Linux能力机制概述 在以往的UNIX系统上,为了做进程的权限检查,把进程分为两类:特权进程(有效用户ID是0)和非特权进程(有效用户ID是非0).特权进程可以通过内核所有的权限检查,而非特权进 ...

  4. linux系统存储文件系统,Linux文件系统的深入分析

    [IT168 技术]本人很喜欢Linux,在工作中也很喜欢总结关于Linux文件系统的经验,下面就这个问题来详细说说吧.Linux支持多种文件系统,包括ext2.iso9660.jffs.ext3.v ...

  5. setuid与capability

    课程作业: 1.解释"passwd","sudo", "ping"等命令为什么需要setuid位,去掉s位试运行,添加权能试运行. 2.指出 ...

  6. Linux进程调度切换和虚拟空间管理深入分析

    Linux进程调度切换和虚拟空间管理深入分析 一.Linux进程切换深入分析 #define CLONE_KERNEL    (CLONE_FS | CLONE_FILES | CLONE_SIGHA ...

  7. linux内核数据结构之链表

    1.前言 最近写代码需用到链表结构,正好公共库有关于链表的.第一眼看时,觉得有点新鲜,和我之前见到的链表结构不一样,只有前驱和后继指针,而没有数据域.后来看代码注释发现该代码来自linux内核,在li ...

  8. Linux内核跟踪eBPF:bpftrace 参考指南

    bpftrace Reference Guide 推荐阅读:Linux内核跟踪eBPF:bpftrace一行教程 For a reference summary, see the README.md ...

  9. Linux沙箱技术 - Setuid Sandbox

    Setuid Sandbox主要基于Linux Kernel所提供的安全机制来实现.简单地说,就是利用 random uid/gid + chroot() + capability 来达到限制不可信进 ...

最新文章

  1. [14] 薪酬迅速翻倍的13条跳槽原则
  2. php 未定义偏移,未定义的偏移PHP错误,尝试从文件读取
  3. Android利用Looper在子线程中改变UI
  4. 【mybatis】IF判断的坑 (实现if test= status == 'zhangsan')
  5. javascript在第三个文本框中显示文字_一段中的个别文字,显示在目录中
  6. 陌屿授权系统v2.0源码
  7. 用python计算准确率_Python 学习 scikit-learn 预测准确率计算
  8. C# 调用Excel组件生成excel文件
  9. python学习之文件处理
  10. [Linux] 使用 SCP 指令,讓您傳送檔案至遠端、下載檔案
  11. 初次了解struts的action类
  12. 推荐一款安卓抓包工具(抓包精灵)
  13. 中国荧光探针市场应用前景与投资动态预测报告(2022-2027年)
  14. 学生端极域课堂万能密码
  15. 计算机软件服务费入哪个科目,软件服务费计入什么科目?
  16. 最短剩余时间调度算法_LRTF:最长剩余时间优先调度算法
  17. 砥砺前行,匠心致远|袋鼠云联合创始人、易知微CEO宁海元荣获“数字工匠 ”
  18. Java GridBagLayout(网格包布局管理器)
  19. 番外篇(1)模块次序表、代数环及其检测算法
  20. 择偶标准与黑名单了解一下

热门文章

  1. Android 常用的地球经纬度转换公里(km)计算工具类
  2. 剥开比原看代码17:比原是如何显示交易的详细信息的?
  3. PHP 页面编码声明方法详解(header或meta)
  4. 程序员提升编程效率的十五点建议!
  5. bootstrap-自适应导航
  6. Puppet 4 性能提升超2倍,升级前应该你知悉的变化
  7. intellij idea maven dependency自动补全
  8. vue 百度统计_百度暑期实习前端开发面经
  9. LTE voice centric和data centric
  10. MDK 工程宏定义的应用