16cd6a6acSopenharmony_ci#include <errno.h> 26cd6a6acSopenharmony_ci#include <getopt.h> 36cd6a6acSopenharmony_ci#include <limits.h> 46cd6a6acSopenharmony_ci#include <selinux/label.h> 56cd6a6acSopenharmony_ci#include <selinux/selinux.h> 66cd6a6acSopenharmony_ci#include <stdio.h> 76cd6a6acSopenharmony_ci#include <stdlib.h> 86cd6a6acSopenharmony_ci#include <string.h> 96cd6a6acSopenharmony_ci#include <sys/stat.h> 106cd6a6acSopenharmony_ci#include <sys/types.h> 116cd6a6acSopenharmony_ci#include <unistd.h> 126cd6a6acSopenharmony_ci 136cd6a6acSopenharmony_cistatic __attribute__ ((__noreturn__)) void usage(const char *progname) 146cd6a6acSopenharmony_ci{ 156cd6a6acSopenharmony_ci fprintf(stderr, 166cd6a6acSopenharmony_ci "usage: %s [-V] [-N] [-n] [-m type] [-f file_contexts_file] [-p prefix] [-P policy_root_path] filepath...\n", 176cd6a6acSopenharmony_ci progname); 186cd6a6acSopenharmony_ci exit(1); 196cd6a6acSopenharmony_ci} 206cd6a6acSopenharmony_ci 216cd6a6acSopenharmony_cistatic int printmatchpathcon(struct selabel_handle *hnd, const char *path, int header, int mode, int notrans) 226cd6a6acSopenharmony_ci{ 236cd6a6acSopenharmony_ci char *buf = NULL; 246cd6a6acSopenharmony_ci int rc; 256cd6a6acSopenharmony_ci 266cd6a6acSopenharmony_ci if (notrans) { 276cd6a6acSopenharmony_ci rc = selabel_lookup_raw(hnd, &buf, path, mode); 286cd6a6acSopenharmony_ci } else { 296cd6a6acSopenharmony_ci rc = selabel_lookup(hnd, &buf, path, mode); 306cd6a6acSopenharmony_ci } 316cd6a6acSopenharmony_ci if (rc < 0) { 326cd6a6acSopenharmony_ci if (errno == ENOENT) { 336cd6a6acSopenharmony_ci buf = strdup("<<none>>"); 346cd6a6acSopenharmony_ci } else { 356cd6a6acSopenharmony_ci fprintf(stderr, "selabel_lookup(%s) failed: %s\n", path, 366cd6a6acSopenharmony_ci strerror(errno)); 376cd6a6acSopenharmony_ci return 1; 386cd6a6acSopenharmony_ci } 396cd6a6acSopenharmony_ci } 406cd6a6acSopenharmony_ci if (header) 416cd6a6acSopenharmony_ci printf("%s\t%s\n", path, buf); 426cd6a6acSopenharmony_ci else 436cd6a6acSopenharmony_ci printf("%s\n", buf); 446cd6a6acSopenharmony_ci 456cd6a6acSopenharmony_ci freecon(buf); 466cd6a6acSopenharmony_ci return 0; 476cd6a6acSopenharmony_ci} 486cd6a6acSopenharmony_ci 496cd6a6acSopenharmony_cistatic mode_t string_to_mode(char *s) 506cd6a6acSopenharmony_ci{ 516cd6a6acSopenharmony_ci switch (s[0]) { 526cd6a6acSopenharmony_ci case 'b': 536cd6a6acSopenharmony_ci return S_IFBLK; 546cd6a6acSopenharmony_ci case 'c': 556cd6a6acSopenharmony_ci return S_IFCHR; 566cd6a6acSopenharmony_ci case 'd': 576cd6a6acSopenharmony_ci return S_IFDIR; 586cd6a6acSopenharmony_ci case 'p': 596cd6a6acSopenharmony_ci return S_IFIFO; 606cd6a6acSopenharmony_ci case 'l': 616cd6a6acSopenharmony_ci return S_IFLNK; 626cd6a6acSopenharmony_ci case 's': 636cd6a6acSopenharmony_ci return S_IFSOCK; 646cd6a6acSopenharmony_ci case 'f': 656cd6a6acSopenharmony_ci return S_IFREG; 666cd6a6acSopenharmony_ci default: 676cd6a6acSopenharmony_ci return -1; 686cd6a6acSopenharmony_ci } 696cd6a6acSopenharmony_ci return -1; 706cd6a6acSopenharmony_ci} 716cd6a6acSopenharmony_ci 726cd6a6acSopenharmony_ciint main(int argc, char **argv) 736cd6a6acSopenharmony_ci{ 746cd6a6acSopenharmony_ci int i, force_mode = 0; 756cd6a6acSopenharmony_ci int header = 1, opt; 766cd6a6acSopenharmony_ci int verify = 0; 776cd6a6acSopenharmony_ci int notrans = 0; 786cd6a6acSopenharmony_ci int error = 0; 796cd6a6acSopenharmony_ci int quiet = 0; 806cd6a6acSopenharmony_ci struct selabel_handle *hnd; 816cd6a6acSopenharmony_ci struct selinux_opt options[SELABEL_NOPT] = {}; 826cd6a6acSopenharmony_ci 836cd6a6acSopenharmony_ci if (argc < 2) 846cd6a6acSopenharmony_ci usage(argv[0]); 856cd6a6acSopenharmony_ci 866cd6a6acSopenharmony_ci while ((opt = getopt(argc, argv, "m:Nnf:P:p:Vq")) > 0) { 876cd6a6acSopenharmony_ci switch (opt) { 886cd6a6acSopenharmony_ci case 'n': 896cd6a6acSopenharmony_ci header = 0; 906cd6a6acSopenharmony_ci break; 916cd6a6acSopenharmony_ci case 'm': 926cd6a6acSopenharmony_ci force_mode = string_to_mode(optarg); 936cd6a6acSopenharmony_ci if (force_mode < 0) { 946cd6a6acSopenharmony_ci fprintf(stderr, "%s: mode %s is invalid\n", argv[0], optarg); 956cd6a6acSopenharmony_ci exit(1); 966cd6a6acSopenharmony_ci } 976cd6a6acSopenharmony_ci break; 986cd6a6acSopenharmony_ci case 'V': 996cd6a6acSopenharmony_ci verify = 1; 1006cd6a6acSopenharmony_ci break; 1016cd6a6acSopenharmony_ci case 'N': 1026cd6a6acSopenharmony_ci notrans = 1; 1036cd6a6acSopenharmony_ci break; 1046cd6a6acSopenharmony_ci case 'f': 1056cd6a6acSopenharmony_ci options[SELABEL_OPT_PATH].type = SELABEL_OPT_PATH; 1066cd6a6acSopenharmony_ci options[SELABEL_OPT_PATH].value = optarg; 1076cd6a6acSopenharmony_ci break; 1086cd6a6acSopenharmony_ci case 'P': 1096cd6a6acSopenharmony_ci if (selinux_set_policy_root(optarg) < 0 ) { 1106cd6a6acSopenharmony_ci fprintf(stderr, 1116cd6a6acSopenharmony_ci "Error setting policy root %s: %s\n", 1126cd6a6acSopenharmony_ci optarg, 1136cd6a6acSopenharmony_ci errno ? strerror(errno) : "invalid"); 1146cd6a6acSopenharmony_ci exit(1); 1156cd6a6acSopenharmony_ci } 1166cd6a6acSopenharmony_ci break; 1176cd6a6acSopenharmony_ci case 'p': 1186cd6a6acSopenharmony_ci // This option has been deprecated since libselinux 2.5 (2016): 1196cd6a6acSopenharmony_ci // https://github.com/SELinuxProject/selinux/commit/26e05da0fc2d0a4bd274320968a88f8acbb3b6a6 1206cd6a6acSopenharmony_ci fprintf(stderr, "Warning: using %s -p is deprecated\n", argv[0]); 1216cd6a6acSopenharmony_ci options[SELABEL_OPT_SUBSET].type = SELABEL_OPT_SUBSET; 1226cd6a6acSopenharmony_ci options[SELABEL_OPT_SUBSET].value = optarg; 1236cd6a6acSopenharmony_ci break; 1246cd6a6acSopenharmony_ci case 'q': 1256cd6a6acSopenharmony_ci quiet = 1; 1266cd6a6acSopenharmony_ci break; 1276cd6a6acSopenharmony_ci default: 1286cd6a6acSopenharmony_ci usage(argv[0]); 1296cd6a6acSopenharmony_ci } 1306cd6a6acSopenharmony_ci } 1316cd6a6acSopenharmony_ci hnd = selabel_open(SELABEL_CTX_FILE, options, SELABEL_NOPT); 1326cd6a6acSopenharmony_ci if (!hnd) { 1336cd6a6acSopenharmony_ci fprintf(stderr, 1346cd6a6acSopenharmony_ci "Error while opening file contexts database: %s\n", 1356cd6a6acSopenharmony_ci strerror(errno)); 1366cd6a6acSopenharmony_ci return -1; 1376cd6a6acSopenharmony_ci } 1386cd6a6acSopenharmony_ci for (i = optind; i < argc; i++) { 1396cd6a6acSopenharmony_ci int rc, mode = 0; 1406cd6a6acSopenharmony_ci struct stat buf; 1416cd6a6acSopenharmony_ci char *path = argv[i]; 1426cd6a6acSopenharmony_ci int len = strlen(path); 1436cd6a6acSopenharmony_ci if (len > 1 && path[len - 1 ] == '/') 1446cd6a6acSopenharmony_ci path[len - 1 ] = '\0'; 1456cd6a6acSopenharmony_ci 1466cd6a6acSopenharmony_ci if (lstat(path, &buf) == 0) 1476cd6a6acSopenharmony_ci mode = buf.st_mode; 1486cd6a6acSopenharmony_ci if (force_mode) 1496cd6a6acSopenharmony_ci mode = force_mode; 1506cd6a6acSopenharmony_ci 1516cd6a6acSopenharmony_ci if (verify) { 1526cd6a6acSopenharmony_ci rc = selinux_file_context_verify(path, mode); 1536cd6a6acSopenharmony_ci 1546cd6a6acSopenharmony_ci if (quiet) { 1556cd6a6acSopenharmony_ci if (rc == 1) 1566cd6a6acSopenharmony_ci continue; 1576cd6a6acSopenharmony_ci else 1586cd6a6acSopenharmony_ci exit(1); 1596cd6a6acSopenharmony_ci } 1606cd6a6acSopenharmony_ci 1616cd6a6acSopenharmony_ci if (rc == -1) { 1626cd6a6acSopenharmony_ci printf("%s error: %s\n", path, strerror(errno)); 1636cd6a6acSopenharmony_ci exit(1); 1646cd6a6acSopenharmony_ci } else if (rc == 1) { 1656cd6a6acSopenharmony_ci printf("%s verified.\n", path); 1666cd6a6acSopenharmony_ci } else { 1676cd6a6acSopenharmony_ci char * con; 1686cd6a6acSopenharmony_ci error = 1; 1696cd6a6acSopenharmony_ci if (notrans) 1706cd6a6acSopenharmony_ci rc = lgetfilecon_raw(path, &con); 1716cd6a6acSopenharmony_ci else 1726cd6a6acSopenharmony_ci rc = lgetfilecon(path, &con); 1736cd6a6acSopenharmony_ci 1746cd6a6acSopenharmony_ci if (rc >= 0) { 1756cd6a6acSopenharmony_ci printf("%s has context %s, should be ", 1766cd6a6acSopenharmony_ci path, con); 1776cd6a6acSopenharmony_ci printmatchpathcon(hnd, path, 0, mode, notrans); 1786cd6a6acSopenharmony_ci freecon(con); 1796cd6a6acSopenharmony_ci } else { 1806cd6a6acSopenharmony_ci printf 1816cd6a6acSopenharmony_ci ("actual context unknown: %s, should be ", 1826cd6a6acSopenharmony_ci strerror(errno)); 1836cd6a6acSopenharmony_ci printmatchpathcon(hnd, path, 0, mode, notrans); 1846cd6a6acSopenharmony_ci } 1856cd6a6acSopenharmony_ci } 1866cd6a6acSopenharmony_ci } else { 1876cd6a6acSopenharmony_ci error |= printmatchpathcon(hnd, path, header, mode, notrans); 1886cd6a6acSopenharmony_ci } 1896cd6a6acSopenharmony_ci } 1906cd6a6acSopenharmony_ci selabel_close(hnd); 1916cd6a6acSopenharmony_ci return error; 1926cd6a6acSopenharmony_ci} 193