cap/cap_text.c

This is cap/cap_text.c, an example to accompany the book, The Linux Programming Interface.

This file is not printed in the book; it is a supplementary file for Chapter 39.

The source code file is copyright 2024, Michael Kerrisk, and is licensed under the GNU General Public License, version 3.

In the listing below, the names of Linux system calls and C library functions are hyperlinked to manual pages from the Linux man-pages project, and the names of functions implemented in the book are hyperlinked to the implementations of those functions.

 

Download cap/cap_text.c

  Cover of The Linux Programming Interface

Function list (Bold in this list means a function is not static)

/* cap_text.c

   Usage: cap_text "textual-cap-set"

   The goal of this program is to help the user to understand the text-form
   capabilities notation that is used by commands such as setcap(1) and
   getcap(1)). The program allows the user to supply a text-form capability
   string which it then converts and displays as "bit-wise" capability sets.

   This program uses cap_from_text(3) to convert the "textual-cap-set"
   supplied as a command-line argument to the internal capabilities
   representation (cap_t). It then uses cap_to_text(3) to convert that
   representation back to text, and displays the result. This enables the
   user to see the minimal text-form string that corresponds to the string
   that they supplied. In addition, the program steps through each of the
   capabilities in the internal representation, displaying a line indicating
   in which of the capability sets the capability was set according to the
   supplied text-form capability string. This enables the user to easily
   understand how the text-form capability string is interpreted.
*/
#include <sys/capability.h>
#include "tlpi_hdr.h"

#define PRCAP_SHOW_ALL          0x01    /* Also display capabilities that
                                           are not enabled in any set */
#define PRCAP_SHOW_UNRECOGNIZED 0x02    /* Display capabilities that are
                                           unrecognized by libcap */
static int
capIsSet(cap_t capSets, cap_value_t cap, cap_flag_t set)
{
    cap_flag_value_t value;

    if (cap_get_flag(capSets, cap, set, &value) == -1)
        errExit("cap_get_flag");

    return value == CAP_SET;
}
static int
capIsPermitted(cap_t capSets, cap_value_t cap)
{
    return capIsSet(capSets, cap, CAP_PERMITTED);
}
static int
capIsEffective(cap_t capSets, cap_value_t cap)
{
    return capIsSet(capSets, cap, CAP_EFFECTIVE);
}
static int
capIsInheritable(cap_t capSets, cap_value_t cap)
{
    return capIsSet(capSets, cap, CAP_INHERITABLE);
}
/* Print a line indicating whether the capability 'cap' is in the
   permitted, effective, and inheritable sets of the capabilities state
   provided in 'capSets'.
*/
static void
printCap(cap_t capSets, cap_value_t cap, char *capStrName, int flags)
{
    cap_flag_value_t dummy;

    if (cap_get_flag(capSets, cap, CAP_PERMITTED, &dummy) != -1) {
        if ((flags & PRCAP_SHOW_ALL) ||
                capIsPermitted(capSets, cap) ||
                capIsEffective(capSets, cap) ||
                capIsInheritable(capSets, cap))
            printf("%-22s %s%s%s\n", capStrName,
                   capIsPermitted(capSets, cap) ? "p" : " ",
                   capIsEffective(capSets, cap) ? "e" : " ",
                   capIsInheritable(capSets, cap) ? "i" : " ");
    } else {
        if (flags & PRCAP_SHOW_UNRECOGNIZED)
            printf("%-22s unrecognized by libcap\n", capStrName);
    }
}
static void
printAllCaps(cap_t capSets, int flags)
{
    printCap(capSets, CAP_AUDIT_CONTROL, "CAP_AUDIT_CONTROL", flags);
#ifdef CAP_AUDIT_READ           /* Since Linux 3.16 */
    printCap(capSets, CAP_AUDIT_READ, "CAP_AUDIT_READ", flags);
#endif
    printCap(capSets, CAP_AUDIT_WRITE, "CAP_AUDIT_WRITE", flags);
#ifdef CAP_BPF          /* Since Linux 5.8 */
    printCap(capSets, CAP_BPF, "CAP_BPF", flags);
#endif
#ifdef CAP_BLOCK_SUSPEND        /* Since Linux 3.5 */
    printCap(capSets, CAP_BLOCK_SUSPEND, "CAP_BLOCK_SUSPEND", flags);
#endif
#ifdef CAP_CHECKPOINT_RESTORE   /* Since Linux 5.9 */
    printCap(capSets, CAP_CHECKPOINT_RESTORE, "CAP_CHECKPOINT_RESTORE", flags);
#endif
    printCap(capSets, CAP_CHOWN, "CAP_CHOWN", flags);
    printCap(capSets, CAP_DAC_OVERRIDE, "CAP_DAC_OVERRIDE", flags);
    printCap(capSets, CAP_DAC_READ_SEARCH, "CAP_DAC_READ_SEARCH", flags);
    printCap(capSets, CAP_FOWNER, "CAP_FOWNER", flags);
    printCap(capSets, CAP_FSETID, "CAP_FSETID", flags);
    printCap(capSets, CAP_IPC_LOCK, "CAP_IPC_LOCK", flags);
    printCap(capSets, CAP_IPC_OWNER, "CAP_IPC_OWNER", flags);
    printCap(capSets, CAP_KILL, "CAP_KILL", flags);
    printCap(capSets, CAP_LEASE, "CAP_LEASE", flags);
    printCap(capSets, CAP_LINUX_IMMUTABLE, "CAP_LINUX_IMMUTABLE", flags);
#ifdef CAP_MAC_ADMIN            /* Since Linux 2.6.25 */
    printCap(capSets, CAP_MAC_ADMIN, "CAP_MAC_ADMIN", flags);
#endif
#ifdef CAP_MAC_OVERRIDE         /* Since Linux 2.6.25 */
    printCap(capSets, CAP_MAC_OVERRIDE, "CAP_MAC_OVERRIDE", flags);
#endif
    printCap(capSets, CAP_MKNOD, "CAP_MKNOD", flags);
    printCap(capSets, CAP_NET_ADMIN, "CAP_NET_ADMIN", flags);
    printCap(capSets, CAP_NET_BIND_SERVICE, "CAP_NET_BIND_SERVICE", flags);
    printCap(capSets, CAP_NET_BROADCAST, "CAP_NET_BROADCAST", flags);
    printCap(capSets, CAP_NET_RAW, "CAP_NET_RAW", flags);
#ifdef CAP_PERFMON              /* Since Linux 5.8 */
    printCap(capSets, CAP_PERFMON, "CAP_PERFMON", flags);
#endif
    printCap(capSets, CAP_SETGID, "CAP_SETGID", flags);
    printCap(capSets, CAP_SETFCAP, "CAP_SETFCAP", flags);
    printCap(capSets, CAP_SETPCAP, "CAP_SETPCAP", flags);
    printCap(capSets, CAP_SETUID, "CAP_SETUID", flags);
    printCap(capSets, CAP_SYS_ADMIN, "CAP_SYS_ADMIN", flags);
    printCap(capSets, CAP_SYS_BOOT, "CAP_SYS_BOOT", flags);
    printCap(capSets, CAP_SYS_CHROOT, "CAP_SYS_CHROOT", flags);
    printCap(capSets, CAP_SYS_MODULE, "CAP_SYS_MODULE", flags);
    printCap(capSets, CAP_SYS_NICE, "CAP_SYS_NICE", flags);
    printCap(capSets, CAP_SYS_PACCT, "CAP_SYS_PACCT", flags);
    printCap(capSets, CAP_SYS_PTRACE, "CAP_SYS_PTRACE", flags);
    printCap(capSets, CAP_SYS_RAWIO, "CAP_SYS_RAWIO", flags);
    printCap(capSets, CAP_SYS_RESOURCE, "CAP_SYS_RESOURCE", flags);
    printCap(capSets, CAP_SYS_TIME, "CAP_SYS_TIME", flags);
    printCap(capSets, CAP_SYS_TTY_CONFIG, "CAP_SYS_TTY_CONFIG", flags);
#ifdef CAP_SYSLOG               /* Since Linux 2.6.37 */
    printCap(capSets, CAP_SYSLOG, "CAP_SYSLOG", flags);
#endif
#ifdef CAP_WAKE_ALARM           /* Since Linux 3.0 */
    printCap(capSets, CAP_WAKE_ALARM, "CAP_WAKE_ALARM", flags);
#endif
}
int
main(int argc, char *argv[])
{
    if (argc != 2) {
        fprintf(stderr, "%s <textual-cap-set>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    cap_t capSets = cap_from_text(argv[1]);
    if (capSets == NULL)
        errExit("cap_from_text");

    char *textCaps = cap_to_text(capSets, NULL);
    if (textCaps == NULL)
        errExit("cap_to_text");

    printf("caps_to_text() returned \"%s\"\n\n", textCaps);

    printAllCaps(capSets, PRCAP_SHOW_ALL);

    if (cap_free(textCaps) != 0 || cap_free(capSets) != 0)
        errExit("cap_free");

    exit(EXIT_SUCCESS);
}

 

Download cap/cap_text.c

Note that, in most cases, the programs rendered in these web pages are not free standing: you'll typically also need a few other source files (mostly in the lib/ subdirectory) as well. Generally, it's easier to just download the entire source tarball and build the programs with make(1). By hovering your mouse over the various hyperlinked include files and function calls above, you can see which other source files this file depends on.

Valid XHTML 1.1