1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <errno.h>
#include <sys/stat.h>
#include <selinux/selinux.h>
#include <selinux/label.h>
static __attribute__ ((__noreturn__)) void usage(const char *progname)
{
fprintf(stderr,
"usage: %s [-v] [-r] -p path [-m mode] [-f file] [link...]\n\n"
"Where:\n\t"
"-v Validate file_contxts entries against loaded policy.\n\t"
"-r Use \"raw\" function.\n\t"
"-p Path to check for best match using the link(s) provided.\n\t"
"-m Optional mode (b, c, d, p, l, s or f) Defaults to 0.\n\t"
"-f Optional file containing the specs (defaults to\n\t"
" those used by loaded policy).\n\t"
"link Zero or more links to check against, the order of\n\t"
" precedence for best match is:\n\t\t"
" 1) An exact match for the real path (if no links), or\n\t\t"
" 2) An exact match for any of the links (aliases), or\n\t\t"
" 3) The longest fixed prefix match.\n\n"
"Example:\n\t"
"%s -p /dev/initctl /run/systemd/initctl/fifo\n\t"
" Find best matching context for the specified path using one link.\n\n",
progname, progname);
exit(1);
}
static mode_t string_to_mode(char *s)
{
switch (s[0]) {
case 'b':
return S_IFBLK;
case 'c':
return S_IFCHR;
case 'd':
return S_IFDIR;
case 'p':
return S_IFIFO;
case 'l':
return S_IFLNK;
case 's':
return S_IFSOCK;
case 'f':
return S_IFREG;
};
return 0;
}
int main(int argc, char **argv)
{
int raw = 0, mode = 0, rc, opt, i, num_links, string_len;
char *validate = NULL, *path = NULL, *context = NULL, *file = NULL;
char **links = NULL;
struct selabel_handle *hnd;
struct selinux_opt options[] = {
{ SELABEL_OPT_PATH, file },
{ SELABEL_OPT_VALIDATE, validate }
};
if (argc < 3)
usage(argv[0]);
while ((opt = getopt(argc, argv, "f:vrp:m:")) > 0) {
switch (opt) {
case 'f':
file = optarg;
break;
case 'v':
validate = (char *)1;
break;
case 'r':
raw = 1;
break;
case 'p':
path = optarg;
break;
case 'm':
mode = string_to_mode(optarg);
break;
default:
usage(argv[0]);
}
}
/* Count links */
for (i = optind, num_links = 0; i < argc; i++, num_links++)
;
if (num_links) {
links = calloc(num_links + 1, sizeof(char *));
if (!links) {
fprintf(stderr, "ERROR: calloc failed.\n");
exit(1);
}
for (i = optind, num_links = 0; i < argc; i++, num_links++) {
string_len = strlen(argv[i]) + 1;
links[num_links] = malloc(string_len);
if (!links[num_links]) {
fprintf(stderr, "ERROR: malloc failed.\n");
exit(1);
}
strcpy(links[num_links], argv[i]);
}
}
options[0].value = file;
options[1].value = validate;
hnd = selabel_open(SELABEL_CTX_FILE, options, 2);
if (!hnd) {
fprintf(stderr, "ERROR: selabel_open - Could not obtain "
"handle.\n");
rc = -1;
goto out;
}
if (raw)
rc = selabel_lookup_best_match_raw(hnd, &context, path,
(const char **)links, mode);
else
rc = selabel_lookup_best_match(hnd, &context, path,
(const char **)links, mode);
selabel_close(hnd);
if (rc) {
switch (errno) {
case ENOENT:
fprintf(stderr, "ERROR: selabel_lookup_best_match "
"failed to find a valid context.\n");
break;
case EINVAL:
fprintf(stderr, "ERROR: selabel_lookup_best_match "
"failed to validate context, or path / mode "
"are invalid.\n");
break;
default:
fprintf(stderr, "selabel_lookup_best_match ERROR: "
"%s\n", strerror(errno));
}
} else {
printf("Best match context: %s\n", context);
freecon(context);
}
out:
if (links) {
for (i = 0; links[i]; i++)
free(links[i]);
free(links);
}
return rc;
}
|