• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Generalized labeling frontend for userspace object managers.
3  *
4  * Author : Eamon Walsh <ewalsh@epoch.ncsc.mil>
5  */
6 
7 #include <sys/types.h>
8 #include <ctype.h>
9 #include <errno.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <selinux/selinux.h>
14 #include "callbacks.h"
15 #include "label_internal.h"
16 
17 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
18 
19 typedef int (*selabel_initfunc)(struct selabel_handle *rec,
20 				const struct selinux_opt *opts,
21 				unsigned nopts);
22 
23 static selabel_initfunc initfuncs[] = {
24 	&selabel_file_init,
25 	NULL,
26 	NULL,
27 	NULL,
28 	&selabel_property_init,
29 };
30 
31 /*
32  * Validation functions
33  */
34 
selabel_is_validate_set(const struct selinux_opt * opts,unsigned n)35 static inline int selabel_is_validate_set(const struct selinux_opt *opts,
36 					  unsigned n)
37 {
38 	while (n--)
39 		if (opts[n].type == SELABEL_OPT_VALIDATE)
40 			return !!opts[n].value;
41 
42 	return 0;
43 }
44 
selabel_validate(struct selabel_handle * rec,struct selabel_lookup_rec * contexts)45 int selabel_validate(struct selabel_handle *rec,
46 		     struct selabel_lookup_rec *contexts)
47 {
48 	int rc = 0;
49 
50 	if (!rec->validating || contexts->validated)
51 		goto out;
52 
53 	rc = selinux_validate(&contexts->ctx_raw);
54 	if (rc < 0)
55 		goto out;
56 
57 	contexts->validated = 1;
58 out:
59 	return rc;
60 }
61 
62 /*
63  * Public API
64  */
65 
selabel_open(unsigned int backend,const struct selinux_opt * opts,unsigned nopts)66 struct selabel_handle *selabel_open(unsigned int backend,
67 				    const struct selinux_opt *opts,
68 				    unsigned nopts)
69 {
70 	struct selabel_handle *rec = NULL;
71 
72 	if (backend >= ARRAY_SIZE(initfuncs)) {
73 		errno = EINVAL;
74 		goto out;
75 	}
76 
77 	if (initfuncs[backend] == NULL)
78 		goto out;
79 
80 	rec = (struct selabel_handle *)malloc(sizeof(*rec));
81 	if (!rec)
82 		goto out;
83 
84 	memset(rec, 0, sizeof(*rec));
85 	rec->backend = backend;
86 	rec->validating = selabel_is_validate_set(opts, nopts);
87 
88 	if ((*initfuncs[backend])(rec, opts, nopts)) {
89 		free(rec->spec_file);
90 		free(rec);
91 		rec = NULL;
92 	}
93 
94 out:
95 	return rec;
96 }
97 
98 static struct selabel_lookup_rec *
selabel_lookup_common(struct selabel_handle * rec,const char * key,int type)99 selabel_lookup_common(struct selabel_handle *rec,
100 		      const char *key, int type)
101 {
102 	struct selabel_lookup_rec *lr;
103 	lr = rec->func_lookup(rec, key, type);
104 	if (!lr)
105 		return NULL;
106 
107 	return lr;
108 }
109 
selabel_lookup(struct selabel_handle * rec,char ** con,const char * key,int type)110 int selabel_lookup(struct selabel_handle *rec, char **con,
111 		   const char *key, int type)
112 {
113 	struct selabel_lookup_rec *lr;
114 
115 	lr = selabel_lookup_common(rec, key, type);
116 	if (!lr)
117 		return -1;
118 
119 	*con = strdup(lr->ctx_raw);
120 	return *con ? 0 : -1;
121 }
122 
selabel_partial_match(struct selabel_handle * rec,const char * key)123 bool selabel_partial_match(struct selabel_handle *rec, const char *key)
124 {
125 	if (!rec->func_partial_match) {
126 		/*
127 		 * If the label backend does not support partial matching,
128 		 * then assume a match is possible.
129 		 */
130 		return true;
131 	}
132 	return rec->func_partial_match(rec, key);
133 }
134 
selabel_lookup_best_match(struct selabel_handle * rec,char ** con,const char * key,const char ** aliases,int type)135 int selabel_lookup_best_match(struct selabel_handle *rec, char **con,
136 			      const char *key, const char **aliases, int type)
137 {
138 	struct selabel_lookup_rec *lr;
139 
140 	if (!rec->func_lookup_best_match) {
141 		errno = ENOTSUP;
142 		return -1;
143 	}
144 
145 	lr = rec->func_lookup_best_match(rec, key, aliases, type);
146 	if (!lr)
147 		return -1;
148 
149 	*con = strdup(lr->ctx_raw);
150 	return *con ? 0 : -1;
151 }
152 
selabel_cmp(struct selabel_handle * h1,struct selabel_handle * h2)153 enum selabel_cmp_result selabel_cmp(struct selabel_handle *h1,
154 				    struct selabel_handle *h2)
155 {
156 	if (!h1->func_cmp || h1->func_cmp != h2->func_cmp)
157 		return SELABEL_INCOMPARABLE;
158 
159 	return h1->func_cmp(h1, h2);
160 }
161 
selabel_close(struct selabel_handle * rec)162 void selabel_close(struct selabel_handle *rec)
163 {
164 	rec->func_close(rec);
165 	free(rec->spec_file);
166 	free(rec);
167 }
168 
selabel_stats(struct selabel_handle * rec)169 void selabel_stats(struct selabel_handle *rec)
170 {
171 	rec->func_stats(rec);
172 }
173