关于capability,可参考这里
第一个文件,cap.c

#include "cap.h"
void showCap(pid_t pid)
{                                                                                                                                                 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 = pid;                                                                                                                       cap_header->version = _LINUX_CAPABILITY_VERSION_1;                                                                                           if (capget(cap_header, cap_data) < 0) {                                                                                                      perror("Failed capget");                                                                                                                 exit(1);                                                                                                                                 }                                                                                                                                            printf("pid %d, Cap data 0x%x, 0x%x, 0x%x\n", pid,cap_data->effective, cap_data->permitted, cap_data->inheritable);
}                                                                                                                                                 void setCap(pid_t pid)
{                                                                                                                                                 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 = pid;                                                                                                                       cap_header->version = _LINUX_CAPABILITY_VERSION_1;                                                                                           if (capget(cap_header, cap_data) < 0) {                                                                                                      perror("Failed capget");                                                                                                                 exit(1);                                                                                                                                 }                                                                                                                                            cap_data->effective &= ~(1 << CAP_NET_ADMIN);                                                                                                 cap_data->permitted &= ~(1 << CAP_NET_ADMIN);                                                                                                 cap_data->inheritable &= ~(1 << CAP_NET_ADMIN);                                                                                               printf("setCap pid %d, Cap data 0x%x, 0x%x, 0x%x\n", pid,cap_data->effective, cap_data->permitted, cap_data->inheritable);                    if (capset(cap_header, cap_data) < 0) {                                                                                                      perror("Failed capset");                                                                                                                 exit(1);                                                                                                                                 }
}

第二个文件,main.c

 #include "cap.h"                                                                                               int main()                                                                                                     {                                                                                                              pid_t pid;                                                                                                                                                                                                             pid = fork();                                                                                                                                                                                                       if(pid == 0) {                                                                                                                 //setCap(getpid());  /*注释2*/                                                                                 execve("./test", NULL, NULL);                                                                          }                                                                                                          else {                                                                                                     printf("in father pid = %d, child pid = %d, uid = %d, gid = %d\n", getpid(), pid, getuid(), getgid()); //setCap(pid);   /*注释1*/                                                                                      }                                                                                                                                                                                                                  return 0;                                                                                                  }

第三个文件 test.c

#include "cap.h"                              int main (int argc, char** argv) {            printf("in test");                        //setCap(getpid());    /*注释3*/                     while (1) {                               sleep (10);                           showCap(getpid());                    }                                         return 0;
}

Make file:

all:    install
CC = gcc
INCLUDE = .
INSTDIR = $(PWD)/
main:   main.c cap.c cap.h                               $(CC) -o main main.c cap.c cap.h -lcap
test:   test.c cap.c cap.h                               $(CC) -o test test.c  cap.c cap.h -lcap
clean:                                                   @ -rm $(INSTDIR) -r
install:        main    test

前提:只有root权限才可以set capability
只打开注释1
sudo ./main
输出:

in father pid = 3605, child pid = 3606, uid = 0, gid = 0
setCap pid 3606, Cap data 0xffffefff, 0xffffefff, 0x0
Failed capset: Operation not permitted

即使拥有root权限,也们没有权限修改其他进程capability

只打开注释2
sudo ./main
输出:

in father pid = 3630, child pid = 3631, uid = 0, gid = 0
setCap pid 3631, Cap data 0xffffefff, 0xffffefff, 0x0
in test
pid 3631, Cap data 0xffffffff, 0xffffffff, 0x0

进程可以修改自身capability,但execve()执行后,替换了进程img,capability也被重置。

只打开注释2
sudo ./main
输出:

in father pid = 3667, child pid = 3668, uid = 0, gid = 0
in test
setCap pid 3668, Cap data 0xffffefff, 0xffffefff, 0x0
pid 3668, Cap data 0xffffefff, 0xffffefff, 0x0

进程修改自身capability,要在execve()之后,才可以成功。

修改test.c

#include "cap.h"                           int main (int argc, char** argv) {         printf("in test\n");                   setCap(getpid());   /*注释3*/            setuid(1000);           while (1) {                            sleep (10);                        showCap(getpid());                 }                                      return 0;
}

sudo ./main
输出:

in father pid = 3708, child pid = 3709, uid = 0, gid = 0
in test
setCap pid 3709, Cap data 0xffffefff, 0xffffefff, 0x0
pid 3709, Cap data 0x0, 0x0, 0x0

从root变为普通用户后,进程自身的capability被clear
那么如何才能使得capability在user变化后保持不变。通过pctrl()
修改main.c

int main (int argc, char** argv)
{                                                   int ret = 0;                                    printf("in test\n");                            //setCap(getpid()); /*注释3*/                     ret = prctl(PR_SET_KEEPCAPS, 1);                if (ret) {                                      perror("prctl");                            return -1;                                  }                                                                                          printf("before set uid 1000\n");                showCap(getpid());                              setuid(1000);                                   setCap(getpid());   /*注释3*/                     printf("after set uid 1000\n");                 while (1) {                                     sleep (10);                                 showCap(getpid());                          }                                               return 0;
}

sudo ./main
输出:

before set uid 1000
pid 97, Cap data 0xffffffff, 0xffffffff, 0x0
setCap pid 97, Cap data 0x0, 0xffffefff, 0x0
after set uid 1000
pid 97, Cap data 0x0, 0xffffefff, 0x0

可以看到在setuid之前调用prctl(PR_SET_KEEPCAPS, 1);,使得Permitted得以保留,但为什么Effective没有被保留?留个疑问吧
如果想改变Effective的值,修改cap.c的setCap函数:

     cap_data->permitted &= ~(1 << CAP_NET_ADMIN);     //cap_data->effective &= ~(1 << CAP_NET_ADMIN); cap_data->effective = cap_data->permitted;      cap_data->inheritable &= ~(1 << CAP_NET_ADMIN);

得到输出:

before set uid 1000
pid 120, Cap data 0xffffffff, 0xffffffff, 0x0
setCap pid 120, Cap data 0xffffefff, 0xffffefff, 0x0
after set uid 1000
pid 120, Cap data 0xffffefff, 0xffffefff, 0x0

可以看到,虽然程序已经不是root权限,但依旧可以set Effective的值。

Linux capability初探相关推荐

  1. Linux 文件系统初探

    文章目录 文件系统 Linux文件系统标准结构 所有分区的含义 Linux分区 文件系统 Windows Linux 分盘,每个驱动器有自己的根目录,形成的是多个树并列的结构. 只有一个根目录 / , ...

  2. Linux内核初探3

    1.内核的任务 内核:充当底层的驱动程序,应用程序只与内核有联系,内核是应用程序的所知道的层次结构中最底层的,也是资源管理程序,也是一种库,提供了一组面向系统的命令. 2.实现策略 微内核(中央内核) ...

  3. linux内核开文件系统,内核必须懂(二): Linux文件系统初探

    目录 前言 文件系统结构 新建文件和inode 文件创建过程 inode解析 打开文件 参考 最后 前言 这次来说文件系统. 文件系统是非常重要的, 提高磁盘使用率, 减小磁盘磨损等等都是文件系统要解 ...

  4. linux驱动初探之字符驱动

    关键字:字符驱动.动态生成设备节点.helloworld linux驱动编程,个人觉得第一件事就是配置好平台文件,这里以字符设备,也就是传说中的helloworld为例~ 此驱动程序基于linux3. ...

  5. linux 基础初探

    linux 看了又看,学了又学,脑袋不灵光,太容易忘记,所以尝试可不可以将厚书学薄点,复习一遍也来梳理一遍! 第一部分 linux 规划与安装就略过了 第二部分 Linux 文件.目录与磁盘格式,共四 ...

  6. Linux文件管理初探---学习文件管理,我想你必须要知道的目录

    前言:在Linux系统中,文件管理的功能是必不可少的,包括创建目录与文件.复制与移动文件.删除文件与目录等.所以我们必须知道在Linux系统中,哪些目录是正规系统会存在的,以及该目录应该存放在哪些信息 ...

  7. LINUX CMA 初探

    一.什么是CMA CMA,Contiguous Memory Allocator,是内存管理子系统中的一个模块,负责物理地址连续的内存分配.一般系统会在启动过程中,从整个memory中配置一段连续内存 ...

  8. linux内核的论文,Linux kernel 初探

    在了解内核之前,先要会编译.调试内核. 编译内核 安装依赖: sudo apt-get update sudo apt-get install git fakeroot build-essential ...

  9. 熟悉linux指令游戏,Linux指令初探之闯关游戏Bandit(上)

    开学季,Evan会带领小萌新们一点点接触安全领域,今天要给大家讲的是和Linux有关的一款游戏Bandit,通过Bandit你会学到Linux的一些基础指令,这对今后的学习有很大的帮助,准备好了吗让我 ...

  10. Linux内核编程(二)-----------Linux内核初探

    写在前面:本篇主要介绍Linux内核的开发模式.linux代码的组成.vmlinux  zImage  uImage的区别,以及编译下内核. 正文: 一.Linux内核的开发模式 1.git:是一个分 ...

最新文章

  1. [HDOJ6165] FFF at Valentine(强联通分量,缩点,拓扑排序)
  2. oracle供需平衡,OracleR12_MRP_功能介绍_V2.ppt
  3. 第4件事 产品经理必须“入戏”, 与用户交朋友
  4. GCC全过程详解+剖析生成的.o文件[转]
  5. 简单详细的OD破解教程(转)
  6. c语言软件下载与配置
  7. 计算机桌面图标被挡怎么办,win7电脑桌面图标被挡住怎么恢复 - 卡饭网
  8. 开源硬件USB抓包及协议分析工具分享
  9. app android切图工具,小白自学APP切图:APP切图工具Cutterman的参数设置
  10. 电子通讯录(数据库版存储)
  11. mysql数据库data没有新创建_如何从pandas datafram在MySQL数据库中创建新表
  12. 郭霖博客出大事了,而鸿阳大神的博客现在情况暂时还好。
  13. 2020年等级计算机考试 二级MS Office
  14. 【博学谷学习记录】超强总结,用心分享丨一种创新的表格
  15. 当滑雪这项世界最古老的运动遇上AI
  16. 平面漩涡Shader
  17. 在PHP中怎么解决大量数据处理的问题
  18. python经典程序练习题6:健康食谱的输出。列出5种不同的食材,输出两两之间可能的组合形式
  19. java http 用户名密码_Web后端语言模拟http请求(带用户名和密码)实例代码大全
  20. 使用Visual Studio Code进行ABAP开发

热门文章

  1. python 转盘 圆形,用python实现一个转盘
  2. 浓缩书应用 Blinkist - 令人惊艳的商业策略
  3. Vue禁止浏览器自动填充
  4. MongoDB学习笔记(五) MongoDB文件存取操作
  5. LeetCode 罗马数字
  6. 方框加对勾怎么输入_如何打出带方框的对号
  7. 破解庞加莱猜想--中国人干的!
  8. 计算机组成原理2017答案,计算机组成原理答案2017(西南大学).docx
  9. CountDownTimer 倒计时器
  10. 影视之我看——写自己的剧本