113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/*
213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Generalized labeling frontend for userspace object managers.
313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle *
413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Author : Eamon Walsh <ewalsh@epoch.ncsc.mil>
513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <sys/types.h>
820271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh#include <ctype.h>
913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <errno.h>
1013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdio.h>
1113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <stdlib.h>
1213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include <string.h>
13e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines#include <sys/stat.h>
1420271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh#include <selinux/selinux.h>
1513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "callbacks.h"
1613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#include "label_internal.h"
1713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
1813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
1913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
2084d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts#ifdef NO_MEDIA_BACKEND
2184d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts#define CONFIG_MEDIA_BACKEND(fnptr) NULL
2284d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts#else
2384d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts#define CONFIG_MEDIA_BACKEND(fnptr) &fnptr
2484d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts#endif
2584d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts
2684d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts#ifdef NO_X_BACKEND
2784d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts#define CONFIG_X_BACKEND(fnptr) NULL
2884d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts#else
2984d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts#define CONFIG_X_BACKEND(fnptr) &fnptr
3084d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts#endif
3184d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts
3284d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts#ifdef NO_DB_BACKEND
3384d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts#define CONFIG_DB_BACKEND(fnptr) NULL
3484d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts#else
3584d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts#define CONFIG_DB_BACKEND(fnptr) &fnptr
3684d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts#endif
3784d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts
38e029ace4d92eee8ba0990e1afbe356ae77b114ccJanis Danisevskis#ifdef NO_ANDROID_BACKEND
39e029ace4d92eee8ba0990e1afbe356ae77b114ccJanis Danisevskis#define CONFIG_ANDROID_BACKEND(fnptr) NULL
40e029ace4d92eee8ba0990e1afbe356ae77b114ccJanis Danisevskis#else
41e029ace4d92eee8ba0990e1afbe356ae77b114ccJanis Danisevskis#define CONFIG_ANDROID_BACKEND(fnptr) (&(fnptr))
42e029ace4d92eee8ba0990e1afbe356ae77b114ccJanis Danisevskis#endif
43e029ace4d92eee8ba0990e1afbe356ae77b114ccJanis Danisevskis
4413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindletypedef int (*selabel_initfunc)(struct selabel_handle *rec,
45f2cd2f821fa34e8c7a12744626e19208463aa4e2Richard Haines				const struct selinux_opt *opts,
46f2cd2f821fa34e8c7a12744626e19208463aa4e2Richard Haines				unsigned nopts);
4713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestatic selabel_initfunc initfuncs[] = {
4913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	&selabel_file_init,
5084d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts	CONFIG_MEDIA_BACKEND(selabel_media_init),
5184d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts	CONFIG_X_BACKEND(selabel_x_init),
5284d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts	CONFIG_DB_BACKEND(selabel_db_init),
53e029ace4d92eee8ba0990e1afbe356ae77b114ccJanis Danisevskis	CONFIG_ANDROID_BACKEND(selabel_property_init),
54e029ace4d92eee8ba0990e1afbe356ae77b114ccJanis Danisevskis	CONFIG_ANDROID_BACKEND(selabel_service_init),
5513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle};
5613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
57a00fd94a46e92a233f4e613660e9962918f28207Eamon Walshstatic void selabel_subs_fini(struct selabel_sub *ptr)
58a00fd94a46e92a233f4e613660e9962918f28207Eamon Walsh{
5920271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh	struct selabel_sub *next;
6020271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh
6120271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh	while (ptr) {
6220271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh		next = ptr->next;
6320271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh		free(ptr->src);
6420271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh		free(ptr->dst);
6520271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh		free(ptr);
6620271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh		ptr = next;
6720271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh	}
6820271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh}
6920271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh
70a00fd94a46e92a233f4e613660e9962918f28207Eamon Walshstatic char *selabel_sub(struct selabel_sub *ptr, const char *src)
7120271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh{
7220271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh	char *dst = NULL;
7322671378f1ace857be4697a3b3aaf1645076d398Dan Walsh	int len;
74a00fd94a46e92a233f4e613660e9962918f28207Eamon Walsh
7520271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh	while (ptr) {
7620271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh		if (strncmp(src, ptr->src, ptr->slen) == 0 ) {
7720271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh			if (src[ptr->slen] == '/' ||
7820271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh			    src[ptr->slen] == 0) {
7922671378f1ace857be4697a3b3aaf1645076d398Dan Walsh				if ((src[ptr->slen] == '/') &&
8022671378f1ace857be4697a3b3aaf1645076d398Dan Walsh				    (strcmp(ptr->dst, "/") == 0))
8122671378f1ace857be4697a3b3aaf1645076d398Dan Walsh					len = ptr->slen + 1;
8222671378f1ace857be4697a3b3aaf1645076d398Dan Walsh				else
8322671378f1ace857be4697a3b3aaf1645076d398Dan Walsh					len = ptr->slen;
8422671378f1ace857be4697a3b3aaf1645076d398Dan Walsh				if (asprintf(&dst, "%s%s", ptr->dst, &src[len]) < 0)
852ca19f3f676a2747a38cf2d7dcf5037ccc8a9eb1Dan Walsh					return NULL;
8620271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh				return dst;
8720271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh			}
8820271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh		}
8920271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh		ptr = ptr->next;
9020271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh	}
9120271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh	return NULL;
9220271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh}
9320271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh
94e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Hainesstruct selabel_sub *selabel_subs_init(const char *path,
95e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines					    struct selabel_sub *list,
96e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines					    struct selabel_digest *digest)
9720271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh{
9820271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh	char buf[1024];
9920b43b3fd3d392c4f12a963a4e46c264e7ed5163Daniel J Walsh	FILE *cfg = fopen(path, "r");
100e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	struct selabel_sub *sub = NULL;
101e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	struct stat sb;
102a00fd94a46e92a233f4e613660e9962918f28207Eamon Walsh
103023c9c1fdee963606d830b70db108bd9031390f4Eric Paris	if (!cfg)
104023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		return list;
105023c9c1fdee963606d830b70db108bd9031390f4Eric Paris
106e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	if (fstat(fileno(cfg), &sb) < 0)
107e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines		return list;
108e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines
109023c9c1fdee963606d830b70db108bd9031390f4Eric Paris	while (fgets_unlocked(buf, sizeof(buf) - 1, cfg)) {
110023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		char *ptr = NULL;
111023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		char *src = buf;
112023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		char *dst = NULL;
113023c9c1fdee963606d830b70db108bd9031390f4Eric Paris
114023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		while (*src && isspace(*src))
115023c9c1fdee963606d830b70db108bd9031390f4Eric Paris			src++;
116023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		if (src[0] == '#') continue;
117023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		ptr = src;
118023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		while (*ptr && ! isspace(*ptr))
119023c9c1fdee963606d830b70db108bd9031390f4Eric Paris			ptr++;
120023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		*ptr++ = '\0';
121023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		if (! *src) continue;
122023c9c1fdee963606d830b70db108bd9031390f4Eric Paris
123023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		dst = ptr;
124023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		while (*dst && isspace(*dst))
125023c9c1fdee963606d830b70db108bd9031390f4Eric Paris			dst++;
126023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		ptr=dst;
127023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		while (*ptr && ! isspace(*ptr))
128023c9c1fdee963606d830b70db108bd9031390f4Eric Paris			ptr++;
129023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		*ptr='\0';
130023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		if (! *dst)
131023c9c1fdee963606d830b70db108bd9031390f4Eric Paris			continue;
132023c9c1fdee963606d830b70db108bd9031390f4Eric Paris
133023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		sub = malloc(sizeof(*sub));
134023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		if (! sub)
135023c9c1fdee963606d830b70db108bd9031390f4Eric Paris			goto err;
136023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		memset(sub, 0, sizeof(*sub));
137023c9c1fdee963606d830b70db108bd9031390f4Eric Paris
138023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		sub->src=strdup(src);
139023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		if (! sub->src)
140023c9c1fdee963606d830b70db108bd9031390f4Eric Paris			goto err;
141023c9c1fdee963606d830b70db108bd9031390f4Eric Paris
142023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		sub->dst=strdup(dst);
143023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		if (! sub->dst)
144023c9c1fdee963606d830b70db108bd9031390f4Eric Paris			goto err;
145023c9c1fdee963606d830b70db108bd9031390f4Eric Paris
146023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		sub->slen = strlen(src);
147023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		sub->next = list;
148023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		list = sub;
14920271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh	}
150e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines
151e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	if (digest_add_specfile(digest, cfg, NULL, sb.st_size, path) < 0)
152e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines		goto err;
153e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines
154023c9c1fdee963606d830b70db108bd9031390f4Eric Parisout:
155023c9c1fdee963606d830b70db108bd9031390f4Eric Paris	fclose(cfg);
156a00fd94a46e92a233f4e613660e9962918f28207Eamon Walsh	return list;
157023c9c1fdee963606d830b70db108bd9031390f4Eric Pariserr:
158023c9c1fdee963606d830b70db108bd9031390f4Eric Paris	if (sub)
159023c9c1fdee963606d830b70db108bd9031390f4Eric Paris		free(sub->src);
160023c9c1fdee963606d830b70db108bd9031390f4Eric Paris	free(sub);
161023c9c1fdee963606d830b70db108bd9031390f4Eric Paris	goto out;
16220271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh}
16320271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh
164e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Hainesstatic inline struct selabel_digest *selabel_is_digest_set
165e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines				    (const struct selinux_opt *opts,
166e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines				    unsigned n,
167e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines				    struct selabel_digest *entry)
168e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines{
169e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	struct selabel_digest *digest = NULL;
170e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines
171e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	while (n--) {
172e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines		if (opts[n].type == SELABEL_OPT_DIGEST &&
173e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines					    opts[n].value == (char *)1) {
174e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines			digest = calloc(1, sizeof(*digest));
175e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines			if (!digest)
176e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines				goto err;
177e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines
178e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines			digest->digest = calloc(1, DIGEST_SPECFILE_SIZE + 1);
179e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines			if (!digest->digest)
180e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines				goto err;
181e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines
182e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines			digest->specfile_list = calloc(DIGEST_FILES_MAX,
183e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines							    sizeof(char *));
184e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines			if (!digest->specfile_list)
185e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines				goto err;
186e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines
187e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines			entry = digest;
188e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines			return entry;
189e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines		}
190e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	}
191e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	return NULL;
192e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines
193e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haineserr:
194e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	free(digest->digest);
195e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	free(digest->specfile_list);
196e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	free(digest);
197e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	return NULL;
198e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines}
199e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines
200e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Hainesstatic void selabel_digest_fini(struct selabel_digest *ptr)
201e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines{
202e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	int i;
203e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines
204e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	free(ptr->digest);
205e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	free(ptr->hashbuf);
206e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines
207e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	if (ptr->specfile_list) {
208e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines		for (i = 0; ptr->specfile_list[i]; i++)
209e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines			free(ptr->specfile_list[i]);
210e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines		free(ptr->specfile_list);
211e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	}
212e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	free(ptr);
213e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines}
214e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines
21513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/*
21613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Validation functions
21713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
21813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
219f2cd2f821fa34e8c7a12744626e19208463aa4e2Richard Hainesstatic inline int selabel_is_validate_set(const struct selinux_opt *opts,
220f2cd2f821fa34e8c7a12744626e19208463aa4e2Richard Haines					  unsigned n)
22113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
22213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	while (n--)
22313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		if (opts[n].type == SELABEL_OPT_VALIDATE)
22413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle			return !!opts[n].value;
22513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
22613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return 0;
22713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
22813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
22913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleint selabel_validate(struct selabel_handle *rec,
23013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		     struct selabel_lookup_rec *contexts)
23113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
23213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	int rc = 0;
23313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
23413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!rec->validating || contexts->validated)
23513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out;
23613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
23713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	rc = selinux_validate(&contexts->ctx_raw);
23813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (rc < 0)
23913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out;
24013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
24113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	contexts->validated = 1;
24213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleout:
24313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return rc;
24413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
24513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
246e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines/* Public API helpers */
247e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Hainesstatic char *selabel_sub_key(struct selabel_handle *rec, const char *key)
248e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines{
249e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	char *ptr = NULL;
250e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	char *dptr = NULL;
251e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
252e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	ptr = selabel_sub(rec->subs, key);
253e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	if (ptr) {
254e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		dptr = selabel_sub(rec->dist_subs, ptr);
255e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		if (dptr) {
256e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines			free(ptr);
257e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines			ptr = dptr;
258e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		}
259e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	} else {
260e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		ptr = selabel_sub(rec->dist_subs, key);
261e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	}
262e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	if (ptr)
263e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		return ptr;
264e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
265e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	return NULL;
266e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines}
267e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
268e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Hainesstatic int selabel_fini(struct selabel_handle *rec,
269e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines			    struct selabel_lookup_rec *lr,
270e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines			    int translating)
271e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines{
27250400d38203e4db08314168e60c281cc61a717a8dcashman	char *path = NULL;
27350400d38203e4db08314168e60c281cc61a717a8dcashman
27450400d38203e4db08314168e60c281cc61a717a8dcashman	if (rec->spec_files)
27550400d38203e4db08314168e60c281cc61a717a8dcashman		path = rec->spec_files[0];
27650400d38203e4db08314168e60c281cc61a717a8dcashman	if (compat_validate(rec, lr, path, 0))
277e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		return -1;
278e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
279e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	if (translating && !lr->ctx_trans &&
280e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	    selinux_raw_to_trans_context(lr->ctx_raw, &lr->ctx_trans))
281e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		return -1;
282e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
283e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	return 0;
284e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines}
285e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
286e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Hainesstatic struct selabel_lookup_rec *
287e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Hainesselabel_lookup_common(struct selabel_handle *rec, int translating,
288e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		      const char *key, int type)
289e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines{
290e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	struct selabel_lookup_rec *lr;
291e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	char *ptr = NULL;
292e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
293e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	if (key == NULL) {
294e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		errno = EINVAL;
295e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		return NULL;
296e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	}
297e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
298e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	ptr = selabel_sub_key(rec, key);
299e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	if (ptr) {
300e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		lr = rec->func_lookup(rec, ptr, type);
301e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		free(ptr);
302e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	} else {
303e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		lr = rec->func_lookup(rec, key, type);
304e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	}
305e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	if (!lr)
306e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		return NULL;
307e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
308e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	if (selabel_fini(rec, lr, translating))
309e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		return NULL;
310e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
311e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	return lr;
312e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines}
313e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
314e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Hainesstatic struct selabel_lookup_rec *
315e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Hainesselabel_lookup_bm_common(struct selabel_handle *rec, int translating,
316e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		      const char *key, int type, const char **aliases)
317e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines{
318e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	struct selabel_lookup_rec *lr;
319e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	char *ptr = NULL;
320e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
321e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	if (key == NULL) {
322e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		errno = EINVAL;
323e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		return NULL;
324e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	}
325e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
326e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	ptr = selabel_sub_key(rec, key);
327e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	if (ptr) {
328e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		lr = rec->func_lookup_best_match(rec, ptr, aliases, type);
329e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		free(ptr);
330e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	} else {
331e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		lr = rec->func_lookup_best_match(rec, key, aliases, type);
332e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	}
333e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	if (!lr)
334e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		return NULL;
335e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
336e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	if (selabel_fini(rec, lr, translating))
337e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		return NULL;
338e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
339e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	return lr;
340e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines}
341e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
34213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle/*
34313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle * Public API
34413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle */
34513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
34613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlestruct selabel_handle *selabel_open(unsigned int backend,
347f2cd2f821fa34e8c7a12744626e19208463aa4e2Richard Haines				    const struct selinux_opt *opts,
348f2cd2f821fa34e8c7a12744626e19208463aa4e2Richard Haines				    unsigned nopts)
34913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
35013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct selabel_handle *rec = NULL;
35113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
35213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (backend >= ARRAY_SIZE(initfuncs)) {
35313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		errno = EINVAL;
35413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out;
35513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
35613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
35784d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts	if (!initfuncs[backend]) {
35884d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts		errno = ENOTSUP;
35984d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts		goto out;
36084d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts	}
36184d07ebd48c85902c8ac54359f2b345881f64ad2William Roberts
36213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	rec = (struct selabel_handle *)malloc(sizeof(*rec));
36313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!rec)
36413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		goto out;
36513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
36613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	memset(rec, 0, sizeof(*rec));
36713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	rec->backend = backend;
36813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	rec->validating = selabel_is_validate_set(opts, nopts);
36920b43b3fd3d392c4f12a963a4e46c264e7ed5163Daniel J Walsh
37020b43b3fd3d392c4f12a963a4e46c264e7ed5163Daniel J Walsh	rec->subs = NULL;
371fd56c5230cea6b81fbe74d1d0a228936a6797923Dan Walsh	rec->dist_subs = NULL;
372e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	rec->digest = selabel_is_digest_set(opts, nopts, rec->digest);
37313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
37413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if ((*initfuncs[backend])(rec, opts, nopts)) {
37550400d38203e4db08314168e60c281cc61a717a8dcashman		selabel_close(rec);
37613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		rec = NULL;
37713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	}
37813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindleout:
37913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return rec;
38013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
38113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
382e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Hainesint selabel_lookup(struct selabel_handle *rec, char **con,
383e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		   const char *key, int type)
38413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
38520271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh	struct selabel_lookup_rec *lr;
38616a37c9f94c1e2dfb865e17e4200d2824d4971f5Richard Haines
387e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	lr = selabel_lookup_common(rec, 1, key, type);
388e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	if (!lr)
389e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		return -1;
39016a37c9f94c1e2dfb865e17e4200d2824d4971f5Richard Haines
391e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	*con = strdup(lr->ctx_trans);
392e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	return *con ? 0 : -1;
393e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines}
394e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
395e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Hainesint selabel_lookup_raw(struct selabel_handle *rec, char **con,
396e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		       const char *key, int type)
397e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines{
398e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	struct selabel_lookup_rec *lr;
399e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
400e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	lr = selabel_lookup_common(rec, 0, key, type);
401e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	if (!lr)
402e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		return -1;
403e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
404e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	*con = strdup(lr->ctx_raw);
405e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	return *con ? 0 : -1;
406e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines}
407e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
408e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Hainesbool selabel_partial_match(struct selabel_handle *rec, const char *key)
409e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines{
410e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	char *ptr;
411e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	bool ret;
412e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
413e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	if (!rec->func_partial_match) {
414e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		/*
415e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		 * If the label backend does not support partial matching,
416e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		 * then assume a match is possible.
417e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		 */
418e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		return true;
419fd56c5230cea6b81fbe74d1d0a228936a6797923Dan Walsh	}
420e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
421e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	ptr = selabel_sub_key(rec, key);
42220271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh	if (ptr) {
423e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		ret = rec->func_partial_match(rec, ptr);
42420271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh		free(ptr);
42520271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh	} else {
426e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		ret = rec->func_partial_match(rec, key);
42720271d94ed2b26b94b052ba6ed90b63566cecbb7Daniel J Walsh	}
42813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
429e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	return ret;
43013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
43113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
432e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Hainesint selabel_lookup_best_match(struct selabel_handle *rec, char **con,
433e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines			      const char *key, const char **aliases, int type)
43413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
43513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct selabel_lookup_rec *lr;
43613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
437e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	if (!rec->func_lookup_best_match) {
438e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		errno = ENOTSUP;
439e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		return -1;
440e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	}
441e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
442e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	lr = selabel_lookup_bm_common(rec, 1, key, type, aliases);
44313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!lr)
44413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
44513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
44613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*con = strdup(lr->ctx_trans);
44713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return *con ? 0 : -1;
44813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
44913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
450e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Hainesint selabel_lookup_best_match_raw(struct selabel_handle *rec, char **con,
451e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines			      const char *key, const char **aliases, int type)
45213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
45313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	struct selabel_lookup_rec *lr;
45413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
455e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	if (!rec->func_lookup_best_match) {
456e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		errno = ENOTSUP;
457e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines		return -1;
458e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	}
459e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines
460e7f970ffd1a8dbb26051405719a2288d34e856f6Richard Haines	lr = selabel_lookup_bm_common(rec, 0, key, type, aliases);
46113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	if (!lr)
46213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle		return -1;
46313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
46413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	*con = strdup(lr->ctx_raw);
46513cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	return *con ? 0 : -1;
46613cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
46713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
4686f295008efd72baac05ecd88587b706e50a77e49Stephen Smalleyenum selabel_cmp_result selabel_cmp(struct selabel_handle *h1,
4696f295008efd72baac05ecd88587b706e50a77e49Stephen Smalley				    struct selabel_handle *h2)
4706f295008efd72baac05ecd88587b706e50a77e49Stephen Smalley{
4716f295008efd72baac05ecd88587b706e50a77e49Stephen Smalley	if (!h1->func_cmp || h1->func_cmp != h2->func_cmp)
4726f295008efd72baac05ecd88587b706e50a77e49Stephen Smalley		return SELABEL_INCOMPARABLE;
4736f295008efd72baac05ecd88587b706e50a77e49Stephen Smalley
4746f295008efd72baac05ecd88587b706e50a77e49Stephen Smalley	return h1->func_cmp(h1, h2);
4756f295008efd72baac05ecd88587b706e50a77e49Stephen Smalley}
4766f295008efd72baac05ecd88587b706e50a77e49Stephen Smalley
477e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Hainesint selabel_digest(struct selabel_handle *rec,
478e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines				    unsigned char **digest, size_t *digest_len,
479e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines				    char ***specfiles, size_t *num_specfiles)
480e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines{
481e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	if (!rec->digest) {
482e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines		errno = EINVAL;
483e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines		return -1;
484e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	}
485e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines
486e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	*digest = rec->digest->digest;
487e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	*digest_len = DIGEST_SPECFILE_SIZE;
488e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	*specfiles = rec->digest->specfile_list;
489e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	*num_specfiles = rec->digest->specfile_cnt;
490e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	return 0;
491e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines}
492e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines
49313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlevoid selabel_close(struct selabel_handle *rec)
49413cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
49550400d38203e4db08314168e60c281cc61a717a8dcashman	size_t i;
496a00fd94a46e92a233f4e613660e9962918f28207Eamon Walsh	selabel_subs_fini(rec->subs);
497fd56c5230cea6b81fbe74d1d0a228936a6797923Dan Walsh	selabel_subs_fini(rec->dist_subs);
49850400d38203e4db08314168e60c281cc61a717a8dcashman	if (rec->spec_files) {
49950400d38203e4db08314168e60c281cc61a717a8dcashman		for (i = 0; i < rec->spec_files_len; i++)
50050400d38203e4db08314168e60c281cc61a717a8dcashman			free(rec->spec_files[i]);
50150400d38203e4db08314168e60c281cc61a717a8dcashman		free(rec->spec_files);
50250400d38203e4db08314168e60c281cc61a717a8dcashman	}
503e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines	if (rec->digest)
504e40bbea95f555fe9708cbbc39895bd67a8ac6c48Richard Haines		selabel_digest_fini(rec->digest);
50550400d38203e4db08314168e60c281cc61a717a8dcashman	if (rec->func_close)
50650400d38203e4db08314168e60c281cc61a717a8dcashman		rec->func_close(rec);
50713cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	free(rec);
50813cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
50913cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle
51013cd4c8960688af11ad23b4c946149015c80d54Joshua Brindlevoid selabel_stats(struct selabel_handle *rec)
51113cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle{
51213cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle	rec->func_stats(rec);
51313cd4c8960688af11ad23b4c946149015c80d54Joshua Brindle}
514