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

一)概述:

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

Linux的capability深入分析(1)【转】的更多相关文章

  1. Linux的capability深入分析

    Linux的capability深入分析详见:http://blog.csdn.net/u014338577/article/details/48791953 lxd中对容器能力的限制: 普通用户不能 ...

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

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

  3. Linux的capability深入分析(2)【转】

    转自:https://blog.csdn.net/wangpengqi/article/details/9821231 rpm -ql libcap-2.16-5.2.el6.i686  /lib/l ...

  4. (转) Linux的capability深入分析(2)

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

  5. Linux select 机制深入分析

    Linux select 机制深入分析            作为IO复用的实现方式.select是提高了抽象和batch处理的级别,不是传统方式那样堵塞在真正IO读写的系统调用上.而是堵塞在sele ...

  6. 转载:linux capability深入分析

    转至http://www.cnblogs.com/iamfy/archive/2012/09/20/2694977.html 一)概述:  1)从2.1版开始,Linux内核有了能力(capabili ...

  7. Linux能力(capability)机制的继承

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

  8. 给linux安全模块LSM添加可链式调用模块(一)

    前些日子接了个外包的活,了解了一下Linux安全模块,发现了安全模块中的一些问题. 关于linux安全模块LSM在此就不多说了,大家google下就明白了. 这里主要介绍的是如何修改这个模块,使它可链 ...

  9. Linux VFS机制简析(一)

    Linux VFS机制简析(一) 本文主要基于Linux内核文档,简单分析Linux VFS机制,以期对编写新的内核文件系统(通常是给分布式文件系统编写内核客户端)的场景有所帮助. 个人渊源 切入正文 ...

随机推荐

  1. 自学Linux Shell7.3-linux共享文件

    点击返回 自学Linux命令行与Shell脚本之路 7.3-linux共享文件 在linux系统中共享文件的方法是通过创建组. 1. linux为每个文件和目录存储了3个额外的信息位: SUID设置用 ...

  2. 自学Linux Shell12.5-while、until命令

    点击返回 自学Linux命令行与Shell脚本之路 12.5-while.until命令 until 循环与 while 循环在处理方式上刚好相反. while循环用于不断执行一系列命令,也用于从输入 ...

  3. 【BZOJ1821】[JSOI2010]部落划分(二分,并查集)

    [BZOJ1821][JSOI2010]部落划分(二分,并查集) 题面 BZOJ 洛谷 题解 二分答案,把距离小于二分值的点全部并起来,\(\mbox{check}\)一下是否有超过\(K\)个集合就 ...

  4. BZOJ 4552 [Tjoi2016&Heoi2016]排序 | 二分答案 线段树

    题目链接 题面 题目描述 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这 ...

  5. 洛谷 P4174 [NOI2006]最大获利 解题报告

    P4174 [NOI2006]最大获利 题目描述 新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战.THU 集团旗下的 CS&T 通讯公司在新一代通讯技术血战的前夜,需要 ...

  6. 【bzoj1565】 NOI2009—植物大战僵尸

    http://www.lydsy.com/JudgeOnline/problem.php?id=1565 (题目链接) 题意 给出$n*m$的棋盘,僵尸攻击每个格子可以获得$v$的分数,每个格子又会保 ...

  7. Java -- JDBC 学习--批量处理

    批量处理JDBC语句提高处理速度 当需要成批插入或者更新记录时.可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理.通常情况下比单独提交处理更有效率JDBC的批量处理语句包 ...

  8. codeforces 793B - Igor and his way to work(dfs、bfs)

    题目链接:http://codeforces.com/problemset/problem/793/B 题目大意:告诉你起点和终点,要求你在只能转弯两次的情况下能不能到达终点.能就输出“YES”,不能 ...

  9. [poj1275][Cashier Employment]

    poj1275 题目大意: 每天有24小时,每个小时需要一定的人.有m个人每个人会有一个开始工作的时间,每个人会工作8小时,问至少需要多少人才能完成任务.如果这m个人也不能完成任务就输出"N ...

  10. IDEA集成有道翻译插件/maven帮助插件/mybatis插件

    (一)IDEA集成有道翻译插件:https://www.cnblogs.com/a8457013/p/7814335.html 插件下载地址:http://plugins.jetbrains.com/ ...