1*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
2*2d543d20SAndroid Build Coastguard Worker #include <getopt.h>
3*2d543d20SAndroid Build Coastguard Worker #include <limits.h>
4*2d543d20SAndroid Build Coastguard Worker #include <selinux/label.h>
5*2d543d20SAndroid Build Coastguard Worker #include <selinux/selinux.h>
6*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
7*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
8*2d543d20SAndroid Build Coastguard Worker #include <string.h>
9*2d543d20SAndroid Build Coastguard Worker #include <sys/stat.h>
10*2d543d20SAndroid Build Coastguard Worker #include <sys/types.h>
11*2d543d20SAndroid Build Coastguard Worker #include <unistd.h>
12*2d543d20SAndroid Build Coastguard Worker
usage(const char * progname)13*2d543d20SAndroid Build Coastguard Worker static __attribute__ ((__noreturn__)) void usage(const char *progname)
14*2d543d20SAndroid Build Coastguard Worker {
15*2d543d20SAndroid Build Coastguard Worker fprintf(stderr,
16*2d543d20SAndroid Build Coastguard Worker "usage: %s [-V] [-N] [-n] [-m type] [-f file_contexts_file] [-p prefix] [-P policy_root_path] filepath...\n",
17*2d543d20SAndroid Build Coastguard Worker progname);
18*2d543d20SAndroid Build Coastguard Worker exit(1);
19*2d543d20SAndroid Build Coastguard Worker }
20*2d543d20SAndroid Build Coastguard Worker
printmatchpathcon(struct selabel_handle * hnd,const char * path,int header,int mode,int notrans)21*2d543d20SAndroid Build Coastguard Worker static int printmatchpathcon(struct selabel_handle *hnd, const char *path, int header, int mode, int notrans)
22*2d543d20SAndroid Build Coastguard Worker {
23*2d543d20SAndroid Build Coastguard Worker char *buf = NULL;
24*2d543d20SAndroid Build Coastguard Worker int rc;
25*2d543d20SAndroid Build Coastguard Worker
26*2d543d20SAndroid Build Coastguard Worker if (notrans) {
27*2d543d20SAndroid Build Coastguard Worker rc = selabel_lookup_raw(hnd, &buf, path, mode);
28*2d543d20SAndroid Build Coastguard Worker } else {
29*2d543d20SAndroid Build Coastguard Worker rc = selabel_lookup(hnd, &buf, path, mode);
30*2d543d20SAndroid Build Coastguard Worker }
31*2d543d20SAndroid Build Coastguard Worker if (rc < 0) {
32*2d543d20SAndroid Build Coastguard Worker if (errno == ENOENT) {
33*2d543d20SAndroid Build Coastguard Worker buf = strdup("<<none>>");
34*2d543d20SAndroid Build Coastguard Worker } else {
35*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "selabel_lookup(%s) failed: %s\n", path,
36*2d543d20SAndroid Build Coastguard Worker strerror(errno));
37*2d543d20SAndroid Build Coastguard Worker return 1;
38*2d543d20SAndroid Build Coastguard Worker }
39*2d543d20SAndroid Build Coastguard Worker }
40*2d543d20SAndroid Build Coastguard Worker if (header)
41*2d543d20SAndroid Build Coastguard Worker printf("%s\t%s\n", path, buf);
42*2d543d20SAndroid Build Coastguard Worker else
43*2d543d20SAndroid Build Coastguard Worker printf("%s\n", buf);
44*2d543d20SAndroid Build Coastguard Worker
45*2d543d20SAndroid Build Coastguard Worker freecon(buf);
46*2d543d20SAndroid Build Coastguard Worker return 0;
47*2d543d20SAndroid Build Coastguard Worker }
48*2d543d20SAndroid Build Coastguard Worker
string_to_mode(char * s)49*2d543d20SAndroid Build Coastguard Worker static mode_t string_to_mode(char *s)
50*2d543d20SAndroid Build Coastguard Worker {
51*2d543d20SAndroid Build Coastguard Worker switch (s[0]) {
52*2d543d20SAndroid Build Coastguard Worker case 'b':
53*2d543d20SAndroid Build Coastguard Worker return S_IFBLK;
54*2d543d20SAndroid Build Coastguard Worker case 'c':
55*2d543d20SAndroid Build Coastguard Worker return S_IFCHR;
56*2d543d20SAndroid Build Coastguard Worker case 'd':
57*2d543d20SAndroid Build Coastguard Worker return S_IFDIR;
58*2d543d20SAndroid Build Coastguard Worker case 'p':
59*2d543d20SAndroid Build Coastguard Worker return S_IFIFO;
60*2d543d20SAndroid Build Coastguard Worker case 'l':
61*2d543d20SAndroid Build Coastguard Worker return S_IFLNK;
62*2d543d20SAndroid Build Coastguard Worker case 's':
63*2d543d20SAndroid Build Coastguard Worker return S_IFSOCK;
64*2d543d20SAndroid Build Coastguard Worker case 'f':
65*2d543d20SAndroid Build Coastguard Worker return S_IFREG;
66*2d543d20SAndroid Build Coastguard Worker default:
67*2d543d20SAndroid Build Coastguard Worker return -1;
68*2d543d20SAndroid Build Coastguard Worker }
69*2d543d20SAndroid Build Coastguard Worker return -1;
70*2d543d20SAndroid Build Coastguard Worker }
71*2d543d20SAndroid Build Coastguard Worker
main(int argc,char ** argv)72*2d543d20SAndroid Build Coastguard Worker int main(int argc, char **argv)
73*2d543d20SAndroid Build Coastguard Worker {
74*2d543d20SAndroid Build Coastguard Worker int i, force_mode = 0;
75*2d543d20SAndroid Build Coastguard Worker int header = 1, opt;
76*2d543d20SAndroid Build Coastguard Worker int verify = 0;
77*2d543d20SAndroid Build Coastguard Worker int notrans = 0;
78*2d543d20SAndroid Build Coastguard Worker int error = 0;
79*2d543d20SAndroid Build Coastguard Worker int quiet = 0;
80*2d543d20SAndroid Build Coastguard Worker struct selabel_handle *hnd;
81*2d543d20SAndroid Build Coastguard Worker struct selinux_opt options[SELABEL_NOPT] = {};
82*2d543d20SAndroid Build Coastguard Worker
83*2d543d20SAndroid Build Coastguard Worker if (argc < 2)
84*2d543d20SAndroid Build Coastguard Worker usage(argv[0]);
85*2d543d20SAndroid Build Coastguard Worker
86*2d543d20SAndroid Build Coastguard Worker while ((opt = getopt(argc, argv, "m:Nnf:P:p:Vq")) > 0) {
87*2d543d20SAndroid Build Coastguard Worker switch (opt) {
88*2d543d20SAndroid Build Coastguard Worker case 'n':
89*2d543d20SAndroid Build Coastguard Worker header = 0;
90*2d543d20SAndroid Build Coastguard Worker break;
91*2d543d20SAndroid Build Coastguard Worker case 'm':
92*2d543d20SAndroid Build Coastguard Worker force_mode = string_to_mode(optarg);
93*2d543d20SAndroid Build Coastguard Worker if (force_mode < 0) {
94*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "%s: mode %s is invalid\n", argv[0], optarg);
95*2d543d20SAndroid Build Coastguard Worker exit(1);
96*2d543d20SAndroid Build Coastguard Worker }
97*2d543d20SAndroid Build Coastguard Worker break;
98*2d543d20SAndroid Build Coastguard Worker case 'V':
99*2d543d20SAndroid Build Coastguard Worker verify = 1;
100*2d543d20SAndroid Build Coastguard Worker break;
101*2d543d20SAndroid Build Coastguard Worker case 'N':
102*2d543d20SAndroid Build Coastguard Worker notrans = 1;
103*2d543d20SAndroid Build Coastguard Worker break;
104*2d543d20SAndroid Build Coastguard Worker case 'f':
105*2d543d20SAndroid Build Coastguard Worker options[SELABEL_OPT_PATH].type = SELABEL_OPT_PATH;
106*2d543d20SAndroid Build Coastguard Worker options[SELABEL_OPT_PATH].value = optarg;
107*2d543d20SAndroid Build Coastguard Worker break;
108*2d543d20SAndroid Build Coastguard Worker case 'P':
109*2d543d20SAndroid Build Coastguard Worker if (selinux_set_policy_root(optarg) < 0 ) {
110*2d543d20SAndroid Build Coastguard Worker fprintf(stderr,
111*2d543d20SAndroid Build Coastguard Worker "Error setting policy root %s: %s\n",
112*2d543d20SAndroid Build Coastguard Worker optarg,
113*2d543d20SAndroid Build Coastguard Worker errno ? strerror(errno) : "invalid");
114*2d543d20SAndroid Build Coastguard Worker exit(1);
115*2d543d20SAndroid Build Coastguard Worker }
116*2d543d20SAndroid Build Coastguard Worker break;
117*2d543d20SAndroid Build Coastguard Worker case 'p':
118*2d543d20SAndroid Build Coastguard Worker // This option has been deprecated since libselinux 2.5 (2016):
119*2d543d20SAndroid Build Coastguard Worker // https://github.com/SELinuxProject/selinux/commit/26e05da0fc2d0a4bd274320968a88f8acbb3b6a6
120*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "Warning: using %s -p is deprecated\n", argv[0]);
121*2d543d20SAndroid Build Coastguard Worker options[SELABEL_OPT_SUBSET].type = SELABEL_OPT_SUBSET;
122*2d543d20SAndroid Build Coastguard Worker options[SELABEL_OPT_SUBSET].value = optarg;
123*2d543d20SAndroid Build Coastguard Worker break;
124*2d543d20SAndroid Build Coastguard Worker case 'q':
125*2d543d20SAndroid Build Coastguard Worker quiet = 1;
126*2d543d20SAndroid Build Coastguard Worker break;
127*2d543d20SAndroid Build Coastguard Worker default:
128*2d543d20SAndroid Build Coastguard Worker usage(argv[0]);
129*2d543d20SAndroid Build Coastguard Worker }
130*2d543d20SAndroid Build Coastguard Worker }
131*2d543d20SAndroid Build Coastguard Worker hnd = selabel_open(SELABEL_CTX_FILE, options, SELABEL_NOPT);
132*2d543d20SAndroid Build Coastguard Worker if (!hnd) {
133*2d543d20SAndroid Build Coastguard Worker fprintf(stderr,
134*2d543d20SAndroid Build Coastguard Worker "Error while opening file contexts database: %s\n",
135*2d543d20SAndroid Build Coastguard Worker strerror(errno));
136*2d543d20SAndroid Build Coastguard Worker return -1;
137*2d543d20SAndroid Build Coastguard Worker }
138*2d543d20SAndroid Build Coastguard Worker for (i = optind; i < argc; i++) {
139*2d543d20SAndroid Build Coastguard Worker int rc, mode = 0;
140*2d543d20SAndroid Build Coastguard Worker struct stat buf;
141*2d543d20SAndroid Build Coastguard Worker char *path = argv[i];
142*2d543d20SAndroid Build Coastguard Worker int len = strlen(path);
143*2d543d20SAndroid Build Coastguard Worker if (len > 1 && path[len - 1 ] == '/')
144*2d543d20SAndroid Build Coastguard Worker path[len - 1 ] = '\0';
145*2d543d20SAndroid Build Coastguard Worker
146*2d543d20SAndroid Build Coastguard Worker if (lstat(path, &buf) == 0)
147*2d543d20SAndroid Build Coastguard Worker mode = buf.st_mode;
148*2d543d20SAndroid Build Coastguard Worker if (force_mode)
149*2d543d20SAndroid Build Coastguard Worker mode = force_mode;
150*2d543d20SAndroid Build Coastguard Worker
151*2d543d20SAndroid Build Coastguard Worker if (verify) {
152*2d543d20SAndroid Build Coastguard Worker rc = selinux_file_context_verify(path, mode);
153*2d543d20SAndroid Build Coastguard Worker
154*2d543d20SAndroid Build Coastguard Worker if (quiet) {
155*2d543d20SAndroid Build Coastguard Worker if (rc == 1)
156*2d543d20SAndroid Build Coastguard Worker continue;
157*2d543d20SAndroid Build Coastguard Worker else
158*2d543d20SAndroid Build Coastguard Worker exit(1);
159*2d543d20SAndroid Build Coastguard Worker }
160*2d543d20SAndroid Build Coastguard Worker
161*2d543d20SAndroid Build Coastguard Worker if (rc == -1) {
162*2d543d20SAndroid Build Coastguard Worker printf("%s error: %s\n", path, strerror(errno));
163*2d543d20SAndroid Build Coastguard Worker exit(1);
164*2d543d20SAndroid Build Coastguard Worker } else if (rc == 1) {
165*2d543d20SAndroid Build Coastguard Worker printf("%s verified.\n", path);
166*2d543d20SAndroid Build Coastguard Worker } else {
167*2d543d20SAndroid Build Coastguard Worker char * con;
168*2d543d20SAndroid Build Coastguard Worker error = 1;
169*2d543d20SAndroid Build Coastguard Worker if (notrans)
170*2d543d20SAndroid Build Coastguard Worker rc = lgetfilecon_raw(path, &con);
171*2d543d20SAndroid Build Coastguard Worker else
172*2d543d20SAndroid Build Coastguard Worker rc = lgetfilecon(path, &con);
173*2d543d20SAndroid Build Coastguard Worker
174*2d543d20SAndroid Build Coastguard Worker if (rc >= 0) {
175*2d543d20SAndroid Build Coastguard Worker printf("%s has context %s, should be ",
176*2d543d20SAndroid Build Coastguard Worker path, con);
177*2d543d20SAndroid Build Coastguard Worker printmatchpathcon(hnd, path, 0, mode, notrans);
178*2d543d20SAndroid Build Coastguard Worker freecon(con);
179*2d543d20SAndroid Build Coastguard Worker } else {
180*2d543d20SAndroid Build Coastguard Worker printf
181*2d543d20SAndroid Build Coastguard Worker ("actual context unknown: %s, should be ",
182*2d543d20SAndroid Build Coastguard Worker strerror(errno));
183*2d543d20SAndroid Build Coastguard Worker printmatchpathcon(hnd, path, 0, mode, notrans);
184*2d543d20SAndroid Build Coastguard Worker }
185*2d543d20SAndroid Build Coastguard Worker }
186*2d543d20SAndroid Build Coastguard Worker } else {
187*2d543d20SAndroid Build Coastguard Worker error |= printmatchpathcon(hnd, path, header, mode, notrans);
188*2d543d20SAndroid Build Coastguard Worker }
189*2d543d20SAndroid Build Coastguard Worker }
190*2d543d20SAndroid Build Coastguard Worker selabel_close(hnd);
191*2d543d20SAndroid Build Coastguard Worker return error;
192*2d543d20SAndroid Build Coastguard Worker }
193