File: selabel_lookup_best_match.c

package info (click to toggle)
libselinux 2.8-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, experimental, sid
  • size: 2,080 kB
  • sloc: ansic: 16,057; makefile: 379; sh: 23
file content (162 lines) | stat: -rw-r--r-- 3,707 bytes parent folder | download | duplicates (3)
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;
}