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