首页 > 系统相关 >linux Capabiltiy 示例——以前只有root和普通用户两种权限,root的权限太大了,现在有了cap,可以细分让某持续有单个权限而非所有特权,见下示例

linux Capabiltiy 示例——以前只有root和普通用户两种权限,root的权限太大了,现在有了cap,可以细分让某持续有单个权限而非所有特权,见下示例

时间:2023-06-01 11:38:33浏览次数:42  
标签:cap 示例 data CAP proc caps set 权限 root

Capabiltiy 示例

Capability的设定和清除

下面的示例程序给当前的进程设定Capability,最后我们清除掉所设置的Capability,源代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/capability.h>

extern int errno;

void whoami(void) {
    printf("uid=%i euid=%d gid=%i\n", getuid(), geteuid(), getgid());
}

void list_caps() {
    // cap_get_proc() allocates a capability state in working stroage, sets
    // its state to taht of the calling process, and returns a pointer to thei newly
    // create capability state.
    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);

    // free the releaseable memory
    if (cap_free(caps) == -1) {
        perror("cap_free()");
    }
}

int main(int argc, char **argv) {
    int stat;
    whoami();

    stat = setuid(geteuid());
    pid_t   parent_pid = getpid();

    if (!parent_pid) {
        perror("parent_pid == 0");
        return 1;
    }

    // cap_init() creates a capability state in working storage and returns
    // a pointer to the capability state. the initial value of all flags
    // are cleared.
    cap_t caps = cap_init();

    // CAP_IS_SUPPORTED(cap_value_t cap) evaluates to true if the system supports the specified capability cap.
    // If the system does not supports the specified capability, the function returns 0.
    // this macro works by testing for an error condition with cap_get_bound()
    if (!CAP_IS_SUPPORTED(CAP_NET_RAW)) {
        perror("do not support CAP_NET_RAW");
        return 1;
    }

    cap_value_t    cap_list[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, cap_list, CAP_SET);
    cap_set_flag(caps, CAP_INHERITABLE, num_caps, cap_list, CAP_SET);
    cap_set_flag(caps, CAP_PERMITTED, num_caps, cap_list, CAP_SET);

    if (cap_set_proc(caps) == -1) {
        perror("cap_set_proc()");
        return EXIT_FAILURE;
    }
    list_caps();

    printf("dropping caps\n");
    cap_clear(caps);
    if (cap_set_proc(caps) == -1) {
        perror("cap_set_proc()");
        return EXIT_FAILURE;
    }
    list_caps();

    if (cap_free(caps) == -1) {
        perror("cap_free()");
        return EXIT_FAILURE;
    }

    return 0;

}

编译运行如下:

# gcc capsettest.c -o capsettest -lcap
# ./capsettest 
uid=0 euid=0 gid=0
The process 21428 was give capabilities = cap_setgid,cap_setuid,cap_setpcap,cap_net_bind_service,cap_net_raw+eip
dropping caps
The process 21428 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函数清理/释放cap变量。
  • 如果我们fork()了子进程,那么子进程继承父进程的所有能力。
  • 不能单独设定CAP_EFFECTIVE,CAP_INHERITABLE位图,必须要和CAP_PERMITTED联用,且CAP_PERMITTED一定要是其它两个位图的超集。
  • 如果两次调用cap_set_proc函数,第二次调用的值力值不能少于或多于第一次调用,如第一次我们授权chown,setuid能力,第二次只能是chown,setuid不能是其它的能力值。
  • 普通用户不能给进程设定能力。

通过capget和capset来获取和设定进程的Capability

下面的程序通过capget函数来获取当前进程的Capability。代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/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_3;

    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);
    return 0;
}

运行如下:

# gcc -o capget capget.c 
# root用户
# ./capget 
Cap data 0xffffffff, 0xffffffff, 0x0
# 非root用户
$ ./capget 
Cap data 0x0, 0x0, 0x0

这说明了默认情况下,root运行的程序什么权限都有,而普通用户则什么权限都没有。

标签:cap,示例,data,CAP,proc,caps,set,权限,root
From: https://blog.51cto.com/u_11908275/6392970

相关文章

  • 如何定制buildroot文件系统-基于TQ3568开发板
    在日常开发中,经常需要添加应用软件以及自定义的文件来辅助我们开发。因为buildroot不支持apt-get命令,我们需要通过makemenuconfig配置bulidroot文件系统来安装应用。本文档以搭建开发板NFS环境为例,描述如何在buildroot文件系统中添加应用软件。Buildroot添加应用配置开发板NFS服务......
  • 2023.5.31-Linux系统基本权限
    02.Linux系统基本权限1.权限修改命令chmod2.属主属组修改命令chown3.基础权限设置案例Linux中的⽂件或⽬录的权限和⽤户及⽤户组关联很⼤,Linux中每个⽂件或⽬录都有⼀组共9个基础权限位,每三个字符被分为⼀组,他们分别是属主权限位(占三个字符)、属组权限位(占三个字符)、其他⽤户权......
  • Java 微服务中的聚合器设计模式示例
    微服务架构中的聚合器设计模式是一种设计模式,用于通过聚合多个独立的微服务的响应来组成一个复杂的服务。它也是与SAGA、CQRS和EventSourcing一起的基本微服务设计模式之一。当客户端请求需要跨多个微服务分布的数据或功能时,此模式是合适的。可以提高系统的性能和可扩展性通过允许......
  • Google Pixel 4 Android13 刷入Magisk + KernelSU 双root环境
    本文所有教程及源码、软件仅为技术研究。不涉及计算机信息系统功能的删除、修改、增加、干扰,更不会影响计算机信息系统的正常运行。不得将代码用于非法用途,如侵立删!GooglePixel4Android13刷入Magisk+KernelSU双root环境环境win10Pixel4Android13下载官方rom包......
  • java的包和权限
    注:同一个文件夹下不能有相同的类包的作用:1.区分形同名字的类2.当有很多类时,可以很好的额管理类(如javaAPI文档)3.控制访问范围包的本质:创建不同的文件夹来保存类文件。语法:packagecom.douyin;package是关键字,表示打包com.douyin表示包名。相......
  • bat脚本在C:\Program Files (x86)使用普通权限运行与使用管理员权限运行获取当前路径
    bat脚本在C:\ProgramFiles(x86)使用管理员权限运行获取当前路径不对。bat脚本如下:@echooffset"current_dir=%cd%"echoCurrentdirectory:%current_dir%set"filepath=%current_dir%\1.txt"setlocalenabledelayedexpansionifexist"%filepath%"(......
  • Vue+element搭建后台管理系统-六、实现权限管理
    在一些后台管理系统中,每个身份登录的权限不一样,以至于配置的菜单不一样。就我做过的小区物业管理系统而言,举个例子:业主登录网站只能看到社区服务中的投诉、维修以及查看公告。而管理员可以看到一些对本小区的基本操作,例如查看楼栋,查看业主,账单催缴等等…而超级管理员,可以看到所有......
  • SqlServer2014管理工具创建用户并设置对应访问权限
     需求:创建一个具有访问权限登录的用户,用以访问指定数据库, 对其放开指定数据库的指定表  一、用户名创建以及设置1、首先使用管理员账号登陆到数据库,【安全性】-【登录名】-右键【新建登录名】 【服务器角色】页签中:用于向用户授予服务器范围内的安全特权 【用户映......
  • aspnetcore最最简单的接口权限认证
    五月一眨眼就过去,就当凑个数吧。场景:一个小小的项目,需要一个后台,就展示几个列表,连用户表、角色表等都不需要设计。之前有写过identityserver4和jwt4的demo(exercisebook/IdentityServer4&Serilogatmain·liuzhixin405/exercisebook·GitHubexercisebook/授权/授权一/Jw......
  • java开发jwt示例
    pom文件引入<dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.15.1</version></dependency>......