setcap 赋予权限的应用

背景:
linux的机器,应用没有root权限,无法调用route和iptables

Linux支持Capability的主要目的则是细化root特权,避免confused deputy问题。比如ping这个命令,需要raw_sockets,所以需要root的权限才可以运行,如果有了Capablity机制,该程序只要一个CAP_NET_RAW的权能,便可以运行,根据最小权限原则,该程序可以去掉所有不必要的权能。

linux官方链接:
https://man7.org/linux/man-pages/man7/capabilities.7.html
强调内核要在4.3之上才支持:Ambient (since Linux 4.3)
在这里插入图片描述

cap的示例代码:
在子进程(app)中可以把需要的cap设置好,然后再调用setuid把权限切换到app0,关键是切换之前要调用prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0); 否则setuid之后原先设置好的cap都会被清空

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


#define nitems(x) (sizeof(x) / sizeof(x[0]))

static void cap_dump(void)
{
    pid_t pid;
    cap_t cap;
    cap_value_t cap_list[CAP_LAST_CAP+1];
    cap_flag_value_t cap_flags_value;
    /* temporary use for cap_get_flag calls */
    struct {
        const char *str;
        cap_flag_t flag;
    } const flags[3] = {
        {"EFFECTIVE", CAP_EFFECTIVE},
        {"PERMITTED", CAP_PERMITTED},
        {"INHERITABLE", CAP_INHERITABLE}
    };
    int i, j;

    const char *cap_name[CAP_LAST_CAP+1] = {
        "cap_chown",
        "cap_dac_override",
        "cap_dac_read_search",
        "cap_fowner",
        "cap_fsetid",
        "cap_kill",
        "cap_setgid",
        "cap_setuid",
        "cap_setpcap",
        "cap_linux_immutable",
        "cap_net_bind_service",
        "cap_net_broadcast",
        "cap_net_admin",
        "cap_net_raw",
        "cap_ipc_lock",
        "cap_ipc_owner",
        "cap_sys_module",
        "cap_sys_rawio",
        "cap_sys_chroot",
        "cap_sys_ptrace",
        "cap_sys_pacct",
        "cap_sys_admin",
        "cap_sys_boot",
        "cap_sys_nice",
        "cap_sys_resource",
        "cap_sys_time",
        "cap_sys_tty_config",
        "cap_mknod",
        "cap_lease",
        "cap_audit_write",
        "cap_audit_control",
        "cap_setfcap",
        "cap_mac_override",
        "cap_mac_admin",
        "cap_syslog",
        "cap_wake_alarm",
        "cap_block_suspend",
        "cap_audit_read",
    };

    pid = getpid();
    cap = cap_get_pid(pid);
    if (cap == NULL) {
        perror("cap_get_pid");
        exit(-1);
    }

    /* dump them */
    for (i=0; i < CAP_LAST_CAP; i++) {
        cap_from_name(cap_name[i], &cap_list[i]);
        printf("%-20s %d\t\t", cap_to_name(cap_list[i]), cap_list[i]);
        printf("flags: \t\t");
        for (j=0; j < nitems(flags); j++) {
            cap_get_flag(cap, cap_list[i], flags[j].flag, &cap_flags_value);
            printf(" %s %-4s ", flags[j].str, (cap_flags_value == CAP_SET) ? "OK" : "NOK");
        }
        printf("\n");
    }

    cap_free(cap);
}

static int cap_set(const cap_flag_t *cap_flag, int cap_flag_size, const cap_value_t *cap_list, int cap_list_size)
{
    cap_t cap;
    int i;

    for (i = 0; i < cap_flag_size; ++i)
    {
        if (cap_flag[i] != CAP_EFFECTIVE
                && cap_flag[i] != CAP_PERMITTED
                && cap_flag[i] != CAP_INHERITABLE)
        {
            perror("invalid argument");
            return -1;
        }
    }
    for (i = 0; i < cap_list_size; ++i)
    {
        if (cap_list[i] > CAP_LAST_CAP)
        {
            perror("invalid argument");
            return -1;
        }
    }

    //1. get cap
    cap = cap_get_proc();
    if (cap == NULL) {
        perror("cap_get_proc");
        return -1;
    }

    //2. set cap flag
    for (i = 0; i < cap_flag_size; ++i)
    {
        /* set effective cap */
        if (cap_set_flag(cap, cap_flag[i], cap_list_size, cap_list, CAP_SET) == -1) {
            perror("cap_set_flag CAP_KILL");
            cap_free(cap);
            return -1;
        }
    }

    //3. set cap to kernel
    if (cap_set_proc(cap) < 0) {
        perror("cap_set_proc fail");
        cap_free(cap);
        return -1;
    }

    //4. clean
    cap_free(cap);

    return 0;
}

int main(void)
{
    cap_value_t cap_list[CAP_LAST_CAP+1];
    cap_flag_t cap_flag[3];
    pid_t parent_pid;
    pid_t child_pid;

    parent_pid = getpid();
    child_pid = fork();
    if (child_pid < 0)
    {
        TRACE("fork fail");
        exit(-1);
    }
    else if (child_pid > 0)
    {
        //parent
        TRACE("I am parent, pid=%d, child pid=%d", parent_pid, child_pid);

        InstallSignalINT();
        while (!g_exit)
        {
            sleep(1);
        }
        TRACE("get signal INT");
    }
    else
    {
        //child
        int ret;

        TRACE("I am child, pid=%d, parent pid=%d", child_pid, parent_pid);
        TRACE("get uid %d", getuid());

        /* enable CAP_KILL */
        cap_flag[0] = CAP_EFFECTIVE;
        cap_flag[1] = CAP_PERMITTED;
        cap_flag[2] = CAP_INHERITABLE;
        cap_list[0] = CAP_KILL;
        cap_set(cap_flag, 3, cap_list, 1);
        cap_dump();

        /*! keep caps after setuid */
        prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);

        ret = setuid(1000);
        if (ret)
            TRACE("setuid 1000 Fail, %m");
        else
            TRACE("child uid=%d", getuid());


        /*! setuid will clear EFFECTIVE CAP sets, but we can re-enable it */
        cap_flag[0] = CAP_EFFECTIVE;
        cap_list[0] = CAP_KILL;
        cap_set(cap_flag, 1, cap_list, 1);

        cap_dump();

        sleep(1);
        kill(parent_pid, SIGINT);
        TRACE("child exit");
    }

    return 0;
}

在实际运行的app里,再调用cap_dump把授权信息再打印一遍看看

execv看来对权限也有影响

During an execve(2), the kernel calculates the new capabilities of the process
using the following algorithm:

P'(permitted) = (P(inheritable) & F(inheritable)) | (F(permitted) & cap_bset)

P'(effective) = F(effective) ? P'(permitted) : 0 

P'(inheritable) = P(inheritable)    [i.e., unchanged]

where:

P        denotes the value of a thread capability set before the execve(2)
P'       denotes the value of a capability set after the execve(2)
F        denotes a file capability set
cap_bset is the value of the capability bounding set 

execv之后,kernel重新计算了程序的权限,打印应用有的cap_dump
execv之后权限又被清了
execv之后权限又被清了

还有一些权限要先设置,才能避免execv之后被清零:

/*
 * test libcap
 */
#if 1
#include "my_common.h"
#include "trace.h"

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


#define nitems(x) (sizeof(x) / sizeof(x[0]))

static void cap_dump(void)
{
    pid_t pid;
    cap_t cap;
    cap_value_t cap_list[CAP_LAST_CAP+1];
    cap_flag_value_t cap_flags_value;
    /* temporary use for cap_get_flag calls */
    struct {
        const char *str;
        cap_flag_t flag;
    } const flags[3] = {
        {"EFFECTIVE", CAP_EFFECTIVE},
        {"PERMITTED", CAP_PERMITTED},
        {"INHERITABLE", CAP_INHERITABLE}
    };
    int i, j;

    const char *cap_name[CAP_LAST_CAP+1] = {
        "cap_chown",
        "cap_dac_override",
        "cap_dac_read_search",
        "cap_fowner",
        "cap_fsetid",
        "cap_kill",
        "cap_setgid",
        "cap_setuid",
        "cap_setpcap",
        "cap_linux_immutable",
        "cap_net_bind_service",
        "cap_net_broadcast",
        "cap_net_admin",
        "cap_net_raw",
        "cap_ipc_lock",
        "cap_ipc_owner",
        "cap_sys_module",
        "cap_sys_rawio",
        "cap_sys_chroot",
        "cap_sys_ptrace",
        "cap_sys_pacct",
        "cap_sys_admin",
        "cap_sys_boot",
        "cap_sys_nice",
        "cap_sys_resource",
        "cap_sys_time",
        "cap_sys_tty_config",
        "cap_mknod",
        "cap_lease",
        "cap_audit_write",
        "cap_audit_control",
        "cap_setfcap",
        "cap_mac_override",
        "cap_mac_admin",
        "cap_syslog",
        "cap_wake_alarm",
        "cap_block_suspend",
        "cap_audit_read",
    };

    pid = getpid();
    cap = cap_get_pid(pid);
    if (cap == NULL) {
        perror("cap_get_pid");
        exit(-1);
    }

    /* dump them */
    for (i=0; i < CAP_LAST_CAP; i++) {
        cap_from_name(cap_name[i], &cap_list[i]);
        printf("%-20s %d\t\t", cap_to_name(cap_list[i]), cap_list[i]);
        printf("flags: \t\t");
        for (j=0; j < nitems(flags); j++) {
            cap_get_flag(cap, cap_list[i], flags[j].flag, &cap_flags_value);
            printf(" %s %-4s ", flags[j].str, (cap_flags_value == CAP_SET) ? "OK" : "NOK");
        }
        printf("\n");
    }

    cap_free(cap);
}

static int cap_set(const cap_flag_t *cap_flag, int cap_flag_size, const cap_value_t *cap_list, int cap_list_size)
{
    cap_t cap;
    int i;

    for (i = 0; i < cap_flag_size; ++i)
    {
        if (cap_flag[i] != CAP_EFFECTIVE
                && cap_flag[i] != CAP_PERMITTED
                && cap_flag[i] != CAP_INHERITABLE)
        {
            perror("invalid argument");
            return -1;
        }
    }
    for (i = 0; i < cap_list_size; ++i)
    {
        if (cap_list[i] > CAP_LAST_CAP)
        {
            perror("invalid argument");
            return -1;
        }
    }

    //1. get cap
    cap = cap_get_proc();
    if (cap == NULL) {
        perror("cap_get_proc");
        return -1;
    }

    //2. set cap flag
    for (i = 0; i < cap_flag_size; ++i)
    {
        /* set CAP_EFFECTIVE/CAP_PERMITTED/CAP_INHERITABLE cap */
        if (cap_set_flag(cap, cap_flag[i], cap_list_size, cap_list, CAP_SET) == -1) {
            perror("cap_set_flag CAP_KILL");
            cap_free(cap);
            return -1;
        }
    }

    //3. set cap to kernel
    if (cap_set_proc(cap) < 0) {
        perror("cap_set_proc fail");
        cap_free(cap);
        return -1;
    }

    //4. clean
    cap_free(cap);

    return 0;
}

static int cap_ambient_set(const cap_value_t *cap_list, int cap_list_size)
{
    int i;

    for (i = 0; i < cap_list_size; ++i)
    {
        if (cap_list[i] > CAP_LAST_CAP)
        {
            perror("invalid argument");
            return -1;
        }
    }

    for (i = 0; i < cap_list_size; ++i)
    {
        if (cap_set_ambient(cap_list[i], CAP_SET) < 0) {
            perror("cap_set_ambient fail");
            return -1;
        }
    }

    return 0;
}

static void child(void)
{
    printf("I am child bin\r\n");
    cap_dump();
}

int main(int argc, char *argv[])
{
    cap_value_t cap_list[CAP_LAST_CAP+1];
    cap_flag_t cap_flag[3];
    pid_t parent_pid;
    pid_t child_pid;

    if (argc > 1 && !strcmp(argv[1], "--child"))
    {
        child();
        return 0;
    }

    parent_pid = getpid();
    child_pid = fork();
    if (child_pid < 0)
    {
        TRACE("fork fail");
        exit(-1);
    }
    else if (child_pid > 0)
    {
        //parent
        TRACE("I am parent, pid=%d, child pid=%d", parent_pid, child_pid);

        InstallSignalINT();
        while (!g_exit)
        {
            sleep(1);
        }
        TRACE("get signal INT");
    }
    else
    {
        //child
        int ret;

        TRACE("I am child, pid=%d, parent pid=%d", child_pid, parent_pid);
        TRACE("get uid %d", getuid());

        /* enable CAP_KILL */
        cap_flag[0] = CAP_EFFECTIVE;
        cap_flag[1] = CAP_PERMITTED;
        cap_flag[2] = CAP_INHERITABLE;
        memset(cap_list, 0, sizeof(cap_list));
        cap_list[0] = CAP_KILL;
        cap_set(cap_flag, 3, cap_list, 1);
        /* enable CAP_SETPCAP */
        cap_flag[0] = CAP_EFFECTIVE;
        cap_flag[1] = CAP_PERMITTED;
        cap_flag[2] = CAP_INHERITABLE;
        memset(cap_list, 0, sizeof(cap_list));
        cap_list[0] = CAP_SETPCAP;
        cap_set(cap_flag, 3, cap_list, 1);

        cap_dump();

        /*! keep caps after setuid */
        prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);

        ret = setuid(1000);
        if (ret)
            TRACE("setuid 1000 Fail, %m");
        else
            TRACE("child uid=%d", getuid());


        /*! setuid will clear EFFECTIVE CAP sets, but we can re-enable it */
        cap_flag[0] = CAP_EFFECTIVE;
        memset(cap_list, 0, sizeof(cap_list));
        cap_list[0] = CAP_KILL;
        cap_set(cap_flag, 1, cap_list, 1);

        cap_dump();

        sleep(1);
        kill(parent_pid, SIGINT);
        TRACE("child exit");


        memset(cap_list, 0, sizeof(cap_list));
        cap_list[0] = CAP_KILL;
        cap_ambient_set(cap_list, 1);

        {
            char path[128] = {'\0'};
            char *arg[8] = {NULL};

            readlink("/proc/self/exe", path, sizeof(path));
            arg[0] = path;
            arg[1] = "--child";
            execv(path, arg);
        }
    }

    return 0;
}

cap_ambient_set

   Ambient (since Linux 4.3):
          This is a set of capabilities that are preserved across an execve(2) of a program that is not privileged.  The ambient capability set obeys the invariant that no capability can ever
          be ambient if it is not both permitted and inheritable.

          The ambient capability set can be directly modified using
          prctl(2).  Ambient capabilities are automatically lowered if
          either of the corresponding permitted or inheritable
          capabilities is lowered.

          Executing a program that changes UID or GID due to the set-
          user-ID or set-group-ID bits or executing a program that has
          any file capabilities set will clear the ambient set.  Ambient
          capabilities are added to the permitted set and assigned to
          the effective set when execve(2) is called.

   A child created via fork(2) inherits copies of its parent's
   capability sets.  See below for a discussion of the treatment of
   capabilities during execve(2).

Transformation of capabilities during execve()
   During an execve(2), the kernel calculates the new capabilities of
   the process using the following algorithm:

       P'(ambient) = (file is privileged) ? 0 : P(ambient)

       P'(permitted) = (P(inheritable) & F(inheritable)) |
                       (F(permitted) & cap_bset) | P'(ambient)

       P'(effective) = F(effective) ? P'(permitted) : P'(ambient)

       P'(inheritable) = P(inheritable)    [i.e., unchanged]

   where:

       P         denotes the value of a thread capability set before the
                 execve(2)

       P'        denotes the value of a thread capability set after the
                 execve(2)

       F         denotes a file capability set

       cap_bset  is the value of the capability bounding set (described
                 below).

   A privileged file is one that has capabilities or has the set-user-ID
   or set-group-ID bit set.

route需要做过权限设置,不能直接调用系统的,iptable这个命令也要在PC linux上先设置好权限
sudo setcap cap_net_admin,cap_net_raw=eip /path/to/iptables
route跟iptables两个程序,就跟着应用走,底层不集成

#include "my_common.h"
#include "trace.h"

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

#define TEST_CAP_KILL
#undef TEST_CAP_KILL
#define TEST_CAP_NET_ADMIN
//#undef TEST_CAP_NET_ADMIN


#define nitems(x) (sizeof(x) / sizeof(x[0]))

static void _cap_dump(cap_t cap)
{
    cap_value_t cap_list[CAP_LAST_CAP+1];
    cap_flag_value_t cap_flags_value;
    /* temporary use for cap_get_flag calls */
    struct {
        const char *str;
        cap_flag_t flag;
    } const flags[3] = {
        {"EFFECTIVE", CAP_EFFECTIVE},
        {"PERMITTED", CAP_PERMITTED},
        {"INHERITABLE", CAP_INHERITABLE}
    };
    int i, j;

    const char *cap_name[] = {
        "cap_chown",
        "cap_dac_override",
        "cap_dac_read_search",
        "cap_fowner",
        "cap_fsetid",
        "cap_kill",
        "cap_setgid",
        "cap_setuid",
        "cap_setpcap",
        "cap_linux_immutable",
        "cap_net_bind_service",
        "cap_net_broadcast",
        "cap_net_admin",
        "cap_net_raw",
        "cap_ipc_lock",
        "cap_ipc_owner",
        "cap_sys_module",
        "cap_sys_rawio",
        "cap_sys_chroot",
        "cap_sys_ptrace",
        "cap_sys_pacct",
        "cap_sys_admin",
        "cap_sys_boot",
        "cap_sys_nice",
        "cap_sys_resource",
        "cap_sys_time",
        "cap_sys_tty_config",
        "cap_mknod",
        "cap_lease",
        "cap_audit_write",
        "cap_audit_control",
        "cap_setfcap",
        "cap_mac_override",
        "cap_mac_admin",
        "cap_syslog",
        "cap_wake_alarm",
        "cap_block_suspend",
        "cap_audit_read",
        NULL
    };
    const int cap_size = ARRAY_SIZE(cap_name) - 1;

    /* dump them */
    for (i=0; i < cap_size; i++) {
        cap_from_name(cap_name[i], &cap_list[i]);
        printf("%-20s %d\t\t", cap_to_name(cap_list[i]), cap_list[i]);
        printf("flags: \t\t");
        for (j=0; j < nitems(flags); j++) {
            cap_get_flag(cap, cap_list[i], flags[j].flag, &cap_flags_value);
            printf(" %s %-4s ", flags[j].str, (cap_flags_value == CAP_SET) ? "OK" : "NOK");
        }
        printf("\n");
    }
}

static void cap_dump(void)
{
    pid_t pid;
    cap_t cap;

    pid = getpid();
    cap = cap_get_pid(pid);
    if (cap == NULL) {
        perror("cap_get_pid");
        exit(-1);
    }

    /* dump them */
    printf("dump proc:\n");
    _cap_dump(cap);

    cap_free(cap);
}

#if 0
static void cap_dump_file(char *path)
{
    cap_t cap;

    cap = cap_get_file(path);
    if (cap == NULL) {
        perror("cap_get_file");
        exit(-1);
    }

    /* dump them */
    printf("dump file:%s\n", path);
    _cap_dump(cap);

    cap_free(cap);
}
#endif

static int cap_set(const cap_flag_t *cap_flag, int cap_flag_size, const cap_value_t *cap_list, int cap_list_size)
{
    cap_t cap;
    int i;

    for (i = 0; i < cap_flag_size; ++i)
    {
        if (cap_flag[i] != CAP_EFFECTIVE
                && cap_flag[i] != CAP_PERMITTED
                && cap_flag[i] != CAP_INHERITABLE)
        {
            perror("invalid argument");
            return -1;
        }
    }
    for (i = 0; i < cap_list_size; ++i)
    {
        if (cap_list[i] > CAP_LAST_CAP)
        {
            perror("invalid argument");
            return -1;
        }
    }

    //1. get cap
    cap = cap_get_proc();
    if (cap == NULL) {
        perror("cap_get_proc");
        return -1;
    }

    //2. set cap flag
    for (i = 0; i < cap_flag_size; ++i)
    {
        /* set CAP_EFFECTIVE/CAP_PERMITTED/CAP_INHERITABLE cap */
        if (cap_set_flag(cap, cap_flag[i], cap_list_size, cap_list, CAP_SET) == -1) {
            perror("cap_set_flag CAP_KILL");
            cap_free(cap);
            return -1;
        }
    }

    //3. set cap to kernel
    if (cap_set_proc(cap) < 0) {
        perror("cap_set_proc fail");
        cap_free(cap);
        return -1;
    }

    //4. clean
    cap_free(cap);

    return 0;
}

static int cap_ambient_set(const cap_value_t *cap_list, int cap_list_size)
{
    int i;

    for (i = 0; i < cap_list_size; ++i)
    {
        if (cap_list[i] > CAP_LAST_CAP)
        {
            perror("invalid argument");
            return -1;
        }
    }

    for (i = 0; i < cap_list_size; ++i)
    {
        if (cap_set_ambient(cap_list[i], CAP_SET) < 0) {
            perror("cap_set_ambient fail");
            return -1;
        }
    }

    return 0;
}


#if defined(TEST_CAP_KILL)

static int test_cap[] = {CAP_KILL};
static void child_runner(void *userp)
{
    char path[128] = {'\0'};
    char *arg[8] = {NULL};
    int ret;

    ret = readlink("/proc/self/exe", path, sizeof(path));
    if (ret) {

    }

    arg[0] = path;
    arg[1] = "--test";
    arg[2] = userp;
    execv(path, arg);
}
static void child_handler(void *userp)
{
    char *parent_pid = userp;
    printf("I am child bin\r\n");
    cap_dump();

    sleep(1);
    kill(atoi(parent_pid), SIGINT);
    TRACE("child bin exit");
}

#elif defined(TEST_CAP_NET_ADMIN)

static int test_cap[] = {CAP_NET_ADMIN};
static void child_runner(void *userp)
{
    char *path = "/tmp/route";
    char *arg[8] = {NULL};

    arg[0] = path;
    arg[1] = "add";
    arg[2] = "-host";
    arg[3] = "10.18.8.40";
    arg[4] = "dev";
    arg[5] = "eth0";
    execv(path, arg);
}
static void child_handler(void *userp)
{
    printf("I am child bin\r\n");
}

#endif

int main(int argc, char *argv[])
{
    cap_value_t cap_list[CAP_LAST_CAP+1];
    cap_flag_t cap_flag[3];
    pid_t parent_pid;
    pid_t child_pid;

    TRACE("CAP_LAST_CAP=%d", CAP_LAST_CAP);
    if (argc > 2 && !strcmp(argv[1], "--test"))
    {
        child_handler(argv[2]);
        return 0;
    }

    parent_pid = getpid();
    child_pid = fork();
    if (child_pid < 0)
    {
        TRACE("fork fail");
        exit(-1);
    }
    else if (child_pid > 0)
    {
        //parent
        TRACE("I am parent, pid=%d, child pid=%d", parent_pid, child_pid);

        InstallSignalINT();
        while (!g_exit)
        {
            sleep(1);
        }
        TRACE("get signal INT");
    }
    else
    {
        //child
        int i;
        int ret;

        TRACE("I am child, pid=%d, parent pid=%d", child_pid, parent_pid);
        TRACE("get uid %d", getuid());

        /* enable CAP_SETPCAP */
        cap_flag[0] = CAP_EFFECTIVE;
        cap_flag[1] = CAP_PERMITTED;
        cap_flag[2] = CAP_INHERITABLE;
        memset(cap_list, 0, sizeof(cap_list));
        cap_list[0] = CAP_SETPCAP;
        cap_set(cap_flag, 3, cap_list, 1);

        /* enable testing cap */
        cap_flag[0] = CAP_EFFECTIVE;
        cap_flag[1] = CAP_PERMITTED;
        cap_flag[2] = CAP_INHERITABLE;
        memset(cap_list, 0, sizeof(cap_list));
        for (i = 0; i < ARRAY_SIZE(test_cap); ++i) {
            cap_list[i] = test_cap[i];
        }
        cap_set(cap_flag, 3, cap_list, ARRAY_SIZE(test_cap));

        cap_dump();

        /*! keep caps after setuid */
        prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);

        ret = setuid(1000);
        if (ret)
            TRACE("setuid 1000 Fail, %m");
        else
            TRACE("child uid=%d", getuid());

        TRACE("after setuid");
        cap_dump();

        cap_flag[0] = CAP_EFFECTIVE;
        memset(cap_list, 0, sizeof(cap_list));
        for (i = 0; i < ARRAY_SIZE(test_cap); ++i) {
            cap_list[i] = test_cap[i];
        }
        cap_set(cap_flag, 1, cap_list, ARRAY_SIZE(test_cap));

        memset(cap_list, 0, sizeof(cap_list));
        for (i = 0; i < ARRAY_SIZE(test_cap); ++i) {
            cap_list[i] = test_cap[i];
        }
        cap_ambient_set(cap_list, ARRAY_SIZE(test_cap));

        TRACE("set cap again");
        cap_dump();

#if defined(TEST_CAP_KILL)
        {
            char arg[16];
            snprintf(arg, sizeof(arg), "%d", parent_pid);
            child_runner(arg);
        }
#elif defined(TEST_CAP_NET_ADMIN)
        {
            child_runner(NULL);
        }
#endif
    }

    return 0;
}

sdk & app 下的库 & 可执行程序的编译 都需要指定 运行时搜索库。 库要依赖第三方库的也需要指定,除了系统库(/lib,/usr/lib)。
LDFLAGS += -Wl,-rpath,/~/lib
LDFLAGS += -Wl,-rpath,/~/dll

app 提权 增加了新权限 后想 运行才需要, 不提权的 app 不加也不影响跑。

要彻底解决,可以 由root来生成 动态库数据字典,这个也是受信的。 生成的 数据字典放在 /etc/ld.so.cache

x86 上 更新 动态库后 由 ldconfig 命令来生成, 嵌入式下, 在工具链没找到。 需要的话要移植一个。 到时 管理这个生成 的就需要 daemon 每次下载完程序后 生成。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值