Capabiltiy example

使用capget查看内核 capabilities的版本号

由于历史原因,capability有三个版本,我们可以通过capget检测内核中国年capabilities的版本号:

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

int main(int argc, char **argv) {
    int ret;
    struct __user_cap_header_struct    cap_header;

    ret = capget(&cap_header, NULL);
    if (ret < 0) {
        fprintf(stderr, "capget error: %s", strerror(errno));
    }

    switch(cap_header.version) {
    case  _LINUX_CAPABILITY_VERSION_1:
        printf("cap version 1: 0x%x\n", cap_header.version);
        break;
    case  _LINUX_CAPABILITY_VERSION_2:
        printf("cap version 2: 0x%x\n", cap_header.version);
        break;
    case  _LINUX_CAPABILITY_VERSION_3:
        printf("cap version 3: 0x%x\n", cap_header.version);
        break;
    default:
        printf("unknown version: 0x%x\n", cap_header.version);
        break;
    }

    exit(EXIT_SUCCESS);
}

编译运行如下:

# gcc 0001-get-kernel-cap-version.c -o 0001-get-kernel-cap-version

查看可以设置的最大的Capability的值

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <sys/prctl.h>

int caps_last_cap_1(void) {
    int fd;
    int result = -1;

    // try to get the maximum capability over the kernel interface
    fd = open("/proc/sys/kernel/cap_last_cap", O_RDONLY);
    if (fd >= 0) {
        char buf[32];
        int n, ret;

        if ((n=read(fd, buf, 31)) >= 0) {
            buf[n] = '\0';
            ret = sscanf(buf, "%d", &result);
            if (ret != 1)
                result = -1;
        }
        close(fd);
    }

    return result;
}

int caps_last_cap_2(void) {
    // try to get maximum capability by trying get the status of
    // each capability indeviually from the kernel.
    int cap = 0;
    while (prctl(PR_CAPBSET_READ, cap) >= 0)
        cap++;
    return cap - 1;
}

int main(int argc, char **argv) {
    int cap;

    cap = caps_last_cap_1();
    if (cap != -1)
        printf("[caps_last_cap_1] The maximum capability is : %d\n", cap);
    else
        printf("[caps_last_cap_1] can not get maximum capability over kernel interface\n");

    cap = caps_last_cap_2();
    printf("[caps_last_cap_2] The maximum capability is : %d\n", cap);

    exit(0);
}

编译运行如下:

# gcc 0003-cap-last-cap.c -o 0003-cap-last-cap

使用capget获取当前进程的permitted、effective、inheritable

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

int main(int argc, char **argv) {
    int ret;
    struct __user_cap_header_struct    cap_header;
    struct __user_cap_data_struct cap_data[2];

    ret = capget(&cap_header, NULL);
    if (ret < 0) {
        fprintf(stderr, "capget error: %s", strerror(errno));
    }

    cap_header.pid = getpid();
    ret = capget(&cap_header, &cap_data[0]);
    if (ret < 0) {
        fprintf(stderr, "capget error: %s", strerror(errno));
    }

    printf("Capabilities of process %d is:\n", cap_header.pid);
    printf("\tCapInh: 0x%08x%08x\n", cap_data[1].inheritable, cap_data[0].inheritable);
    printf("\tCapEff: 0x%08x%08x\n", cap_data[1].effective, cap_data[0].effective);
    printf("\tCapPrm: 0x%08x%08x\n", cap_data[1].permitted, cap_data[0].permitted);

    exit(EXIT_SUCCESS);
}

// gcc 0002-get-cap-of-current-process.c -o 0002-get-cap-of-current-process

使用prctl获取当前进程的bounding、ambient


#include <stdio.h>
#include <stdlib.h>
#include <sys/capability.h>
#include <sys/prctl.h>

int main(int argc, char **argv) {
    int ret;
    int cap = 0;
    int cap_data[2] = {0};

    // get bounding capability of the current process
    while ((ret = prctl(PR_CAPBSET_READ, cap)) >= 0) {
        if (ret == 1) {
            if (cap > 31)
                cap_data[1] |= (1<<(cap-32));
            else
                cap_data[0] |= (1<<cap);
        }
        cap++;
    }
    printf("CapBnd: 0x%08x%08x\n", cap_data[1], cap_data[0]);

    cap_data[0] = 0;
    cap_data[1] = 0;
    cap = 0;
    // get ambient capability of the current process
    while ((ret = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, cap)) >= 0) {
        if (ret == 1) {
            if (cap > 31)
                cap_data[1] |= (1<<(cap-32));
            else
                cap_data[0] |= (1<<cap);
        }
        cap++;
    }
    printf("CapAmb: 0x%08x%08x\n", cap_data[1], cap_data[0]);

    exit(EXIT_SUCCESS);
}

// gcc 0004-cap-get-bound-and-ambient.c -o 0004-cap-get-bound-and-ambient

获取任意进程的permitted、effective、inheritable

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>

#include <sys/capability.h>

void usage(void) {
    fprintf(stderr, "Usage: getpcaps <pid> [<pid> ...]\n");
    exit(1);
}

int main(int argc, char **argv) {
    if (argc < 2) {
        usage();
    }

    for (++argv; --argc > 0; ++argv) {
        int ret;
        struct __user_cap_header_struct    cap_header;
        struct __user_cap_data_struct cap_data[2];
        ret = capget(&cap_header, NULL);
        if (ret < 0) {
            fprintf(stderr, "capget error: %s", strerror(errno));
        }
        memset(cap_data, 0, sizeof(cap_data));
        // get capabilities of the calling thred if pid is 0
        cap_header.pid = atoi(argv[0]);
        ret = capget(&cap_header, &cap_data[0]);
        if (ret < 0) {
            fprintf(stderr, "capget error: %s", strerror(errno));
        } else {
            printf("\nCapabilities of process %d is:\n", cap_header.pid);
            printf("\tCapInh: 0x%08x%08x\n", cap_data[1].inheritable, cap_data[0].inheritable);
            printf("\tCapEff: 0x%08x%08x\n", cap_data[1].effective, cap_data[0].effective);
            printf("\tCapPrm: 0x%08x%08x\n", cap_data[1].permitted, cap_data[0].permitted);
        }
    }

    exit(EXIT_SUCCESS);
}

// gcc 0005-getpcaps.c -o getpcaps

使用capset设置进程的permitted、effective、inheritable


#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>

#include <sys/capability.h>

void list_caps() {
    int ret;
    struct __user_cap_header_struct    cap_header;
    struct __user_cap_data_struct cap_data[2];
    ret = capget(&cap_header, NULL);
    if (ret < 0) {
        fprintf(stderr, "capget error: %s", strerror(errno));
    }
    memset(cap_data, 0, sizeof(cap_data));
    cap_header.pid = getpid();
    ret = capget(&cap_header, &cap_data[0]);
    if (ret < 0) {
        fprintf(stderr, "capget error: %s", strerror(errno));
    } else {
        printf("Capabilities of process %8d is:", cap_header.pid);
        printf(" CapInh: 0x%08x%08x", cap_data[1].inheritable, cap_data[0].inheritable);
        printf(" CapEff: 0x%08x%08x", cap_data[1].effective, cap_data[0].effective);
        printf(" CapPrm: 0x%08x%08x", cap_data[1].permitted, cap_data[0].permitted);
        printf("\n");
    }
}

int set_caps(struct __user_cap_data_struct cap_data[2]) {
    int ret = 0;
    struct __user_cap_header_struct    cap_header;
    ret = capget(&cap_header, NULL);
    if (ret < 0) {
        fprintf(stderr, "capget error: %s", strerror(errno));
    }

    cap_header.pid = getpid();
    ret = capset(&cap_header, &cap_data[0]);
    if (ret < 0) {
        fprintf(stderr, "capget error: %s", strerror(errno));
    }
    return ret;
}

int main(int argc, char **argv) {
    struct __user_cap_data_struct cap_data[2];

    list_caps();

    // NOTE: set a capability in the effecitve or inheritable sets that is not
    // in the permitted set will cause EPERM error.
    cap_data[0].inheritable = 0x000000ff;
    cap_data[0].effective = 0x000000ff;
    cap_data[0].permitted = 0x00000fff;
    cap_data[1].inheritable = 0x00000001;
    cap_data[1].effective = 0x00000003;
    cap_data[1].permitted = 0x0000000f;
    set_caps(cap_data);
    list_caps();

    exit(EXIT_SUCCESS);
}

// gcc 0006-set-current-process-cap.c -o 0006-set-current-process-cap

获取file Capability的版本


#include <stdio.h>
#include <sys/capability.h>
#include <stdlib.h>

int main(int argc, char **argv) {
    int ret;
    struct vfs_cap_data file_cap_data;
    int file_cap_version;

    if (argc != 2) {
        fprintf(stderr ,"Usage: %s pathname\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    ret = getxattr(argv[1], "security.capability", &file_cap_data, sizeof(struct vfs_cap_data));
    if (ret < 0) {
        perror("getxattr");
        exit(EXIT_FAILURE);
    }

    file_cap_version = file_cap_data.magic_etc & VFS_CAP_REVISION_MASK;
    switch (file_cap_version) {
    case VFS_CAP_REVISION_1:
        printf("file cap version 1: 0x%08x\n", file_cap_version);
        break;
    case VFS_CAP_REVISION_2:
        printf("file cap version 2: 0x%08x\n", file_cap_version);
        break;
    default:
        printf("unknown file cap version: 0x%08x\n", file_cap_version);
        break;
    }

    exit(EXIT_SUCCESS);
}

/*
# gcc -o 0007-get-file-cap-version 0007-get-file-cap-version.c 
# ./0007-get-file-cap-version /usr/bin/traceroute6.iputils 
file cap version 2: 0x02000000
*/

使用getxattr获取文件的capabilities


#include <stdio.h>
#include <sys/capability.h>
#include <stdlib.h>

int main(int argc, char **argv) {
    int ret;
    struct vfs_cap_data file_cap_data;
    int file_cap_version;

    if (argc != 2) {
        fprintf(stderr ,"Usage: %s pathname\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    ret = getxattr(argv[1], "security.capability", &file_cap_data, sizeof(struct vfs_cap_data));
    if (ret < 0) {
        perror("getxattr");
        exit(EXIT_FAILURE);
    }
    // Print the version
    file_cap_version = file_cap_data.magic_etc & VFS_CAP_REVISION_MASK;
    switch (file_cap_version) {
    case VFS_CAP_REVISION_1:
        printf("file cap version 1: 0x%08x\n", file_cap_version);
        break;
    case VFS_CAP_REVISION_2:
        printf("file cap version 2: 0x%08x\n", file_cap_version);
        break;
    default:
        printf("unknown file cap version: 0x%08x\n", file_cap_version);
        break;
    }
    // Printf the effective flag
    printf("file effective cap flag: %d\n", file_cap_data.magic_etc & VFS_CAP_FLAGS_EFFECTIVE);

    // Print permitted and inheritable
    printf("file cap permitted:   0x%08x %08x\n",
            file_cap_data.data[1].permitted,
            file_cap_data.data[0].permitted);
    printf("file cap inheritable: 0x%08x %08x\n",
            file_cap_data.data[1].inheritable,
            file_cap_data.data[0].inheritable);
    exit(EXIT_SUCCESS);
}
/*
# gcc -o 0008-get-file-cap 0008-get-file-cap.c 
# ./0008-get-file-cap /usr/bin/traceroute6.iputils 
file cap version 2: 0x02000000
file effective cap flag: 1
file cap permitted:   0x00000000 00002000
file cap inheritable: 0x00000000 00000000
# getcap /usr/bin/traceroute6.iputils
/usr/bin/traceroute6.iputils = cap_net_raw+ep
*/

使用getxattr设置文件的capabilities


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

int main(int argc, char **argv) {
    int ret;
    struct vfs_cap_data file_cap_data;
    int file_cap_version;

    if (argc != 2) {
        fprintf(stderr ,"Usage: %s pathname\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    ret = getxattr(argv[1], "security.capability", &file_cap_data, sizeof(struct vfs_cap_data));
    if (ret < 0) {
        perror("getxattr");
        exit(EXIT_FAILURE);
    }
    // Print the version
    file_cap_version = file_cap_data.magic_etc & VFS_CAP_REVISION_MASK;
    switch (file_cap_version) {
    case VFS_CAP_REVISION_1:
        printf("file cap version 1: 0x%08x\n", file_cap_version);
        break;
    case VFS_CAP_REVISION_2:
        printf("file cap version 2: 0x%08x\n", file_cap_version);
        break;
    default:
        printf("unknown file cap version: 0x%08x\n", file_cap_version);
        break;
    }
    // Printf the effective flag
    printf("file effective cap flag: %d\n", file_cap_data.magic_etc & VFS_CAP_FLAGS_EFFECTIVE);

    // Print permitted and inheritable
    printf("file cap permitted:   0x%08x %08x\n",
            file_cap_data.data[1].permitted,
            file_cap_data.data[0].permitted);
    printf("file cap inheritable: 0x%08x %08x\n",
            file_cap_data.data[1].inheritable,
            file_cap_data.data[0].inheritable);

    // Set the file cap: CAP_CHOWN CAP_FSETID
    printf("set file permitted cap: CAP_CHOWN and CAP_FSETID\n");
    file_cap_data.data[0].permitted |= 0x11;

    ret = setxattr(argv[1], "security.capability", &file_cap_data, sizeof(struct vfs_cap_data), 0);
    if (ret < 0) {
        perror("setxattr");
        exit(EXIT_FAILURE);
    }

    exit(EXIT_SUCCESS);
}
/*
# gcc -o 0009-set-file-cap 0009-set-file-cap.c
# getcap /usr/bin/traceroute6.iputils
/usr/bin/traceroute6.iputils = cap_net_raw+ep
# ./0009-set-file-cap /usr/bin/traceroute6.iputils
file cap version 2: 0x02000000
file effective cap flag: 1
file cap permitted:   0x00000000 00002000
file cap inheritable: 0x00000000 00000000
set file permitted cap: CAP_CHOWN and CAP_FSETID
# getcap /usr/bin/traceroute6.iputils
/usr/bin/traceroute6.iputils = cap_chown,cap_fsetid,cap_net_raw+ep
*/

results matching ""

    No results matching ""