16cd6a6acSopenharmony_ci#include <stdlib.h>
26cd6a6acSopenharmony_ci#include <stddef.h>
36cd6a6acSopenharmony_ci#include <string.h>
46cd6a6acSopenharmony_ci
56cd6a6acSopenharmony_ci#include "private.h"
66cd6a6acSopenharmony_ci#include "debug.h"
76cd6a6acSopenharmony_ci#include "handle.h"
86cd6a6acSopenharmony_ci
96cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h>
106cd6a6acSopenharmony_ci#include <sepol/policydb/hashtab.h>
116cd6a6acSopenharmony_ci#include <sepol/policydb/expand.h>
126cd6a6acSopenharmony_ci#include "user_internal.h"
136cd6a6acSopenharmony_ci#include "mls.h"
146cd6a6acSopenharmony_ci
156cd6a6acSopenharmony_cistatic int user_to_record(sepol_handle_t * handle,
166cd6a6acSopenharmony_ci			  const policydb_t * policydb,
176cd6a6acSopenharmony_ci			  int user_idx, sepol_user_t ** record)
186cd6a6acSopenharmony_ci{
196cd6a6acSopenharmony_ci
206cd6a6acSopenharmony_ci	const char *name = policydb->p_user_val_to_name[user_idx];
216cd6a6acSopenharmony_ci	user_datum_t *usrdatum = policydb->user_val_to_struct[user_idx];
226cd6a6acSopenharmony_ci	ebitmap_t *roles;
236cd6a6acSopenharmony_ci	ebitmap_node_t *rnode;
246cd6a6acSopenharmony_ci	unsigned bit;
256cd6a6acSopenharmony_ci
266cd6a6acSopenharmony_ci	sepol_user_t *tmp_record = NULL;
276cd6a6acSopenharmony_ci
286cd6a6acSopenharmony_ci	if (!usrdatum)
296cd6a6acSopenharmony_ci		goto err;
306cd6a6acSopenharmony_ci
316cd6a6acSopenharmony_ci	roles = &(usrdatum->roles.roles);
326cd6a6acSopenharmony_ci
336cd6a6acSopenharmony_ci	if (sepol_user_create(handle, &tmp_record) < 0)
346cd6a6acSopenharmony_ci		goto err;
356cd6a6acSopenharmony_ci
366cd6a6acSopenharmony_ci	if (sepol_user_set_name(handle, tmp_record, name) < 0)
376cd6a6acSopenharmony_ci		goto err;
386cd6a6acSopenharmony_ci
396cd6a6acSopenharmony_ci	/* Extract roles */
406cd6a6acSopenharmony_ci	ebitmap_for_each_positive_bit(roles, rnode, bit) {
416cd6a6acSopenharmony_ci		char *role = policydb->p_role_val_to_name[bit];
426cd6a6acSopenharmony_ci		if (sepol_user_add_role(handle, tmp_record, role) < 0)
436cd6a6acSopenharmony_ci			goto err;
446cd6a6acSopenharmony_ci	}
456cd6a6acSopenharmony_ci
466cd6a6acSopenharmony_ci	/* Extract MLS info */
476cd6a6acSopenharmony_ci	if (policydb->mls) {
486cd6a6acSopenharmony_ci		context_struct_t context;
496cd6a6acSopenharmony_ci		char *str;
506cd6a6acSopenharmony_ci
516cd6a6acSopenharmony_ci		context_init(&context);
526cd6a6acSopenharmony_ci		if (mls_level_cpy(&context.range.level[0],
536cd6a6acSopenharmony_ci				  &usrdatum->exp_dfltlevel) < 0) {
546cd6a6acSopenharmony_ci			ERR(handle, "could not copy MLS level");
556cd6a6acSopenharmony_ci			context_destroy(&context);
566cd6a6acSopenharmony_ci			goto err;
576cd6a6acSopenharmony_ci		}
586cd6a6acSopenharmony_ci		if (mls_level_cpy(&context.range.level[1],
596cd6a6acSopenharmony_ci				  &usrdatum->exp_dfltlevel) < 0) {
606cd6a6acSopenharmony_ci			ERR(handle, "could not copy MLS level");
616cd6a6acSopenharmony_ci			context_destroy(&context);
626cd6a6acSopenharmony_ci			goto err;
636cd6a6acSopenharmony_ci		}
646cd6a6acSopenharmony_ci		if (mls_to_string(handle, policydb, &context, &str) < 0) {
656cd6a6acSopenharmony_ci			context_destroy(&context);
666cd6a6acSopenharmony_ci			goto err;
676cd6a6acSopenharmony_ci		}
686cd6a6acSopenharmony_ci		context_destroy(&context);
696cd6a6acSopenharmony_ci
706cd6a6acSopenharmony_ci		if (sepol_user_set_mlslevel(handle, tmp_record, str) < 0) {
716cd6a6acSopenharmony_ci			free(str);
726cd6a6acSopenharmony_ci			goto err;
736cd6a6acSopenharmony_ci		}
746cd6a6acSopenharmony_ci		free(str);
756cd6a6acSopenharmony_ci
766cd6a6acSopenharmony_ci		context_init(&context);
776cd6a6acSopenharmony_ci		if (mls_range_cpy(&context.range, &usrdatum->exp_range) < 0) {
786cd6a6acSopenharmony_ci			ERR(handle, "could not copy MLS range");
796cd6a6acSopenharmony_ci			context_destroy(&context);
806cd6a6acSopenharmony_ci			goto err;
816cd6a6acSopenharmony_ci		}
826cd6a6acSopenharmony_ci		if (mls_to_string(handle, policydb, &context, &str) < 0) {
836cd6a6acSopenharmony_ci			context_destroy(&context);
846cd6a6acSopenharmony_ci			goto err;
856cd6a6acSopenharmony_ci		}
866cd6a6acSopenharmony_ci		context_destroy(&context);
876cd6a6acSopenharmony_ci
886cd6a6acSopenharmony_ci		if (sepol_user_set_mlsrange(handle, tmp_record, str) < 0) {
896cd6a6acSopenharmony_ci			free(str);
906cd6a6acSopenharmony_ci			goto err;
916cd6a6acSopenharmony_ci		}
926cd6a6acSopenharmony_ci		free(str);
936cd6a6acSopenharmony_ci	}
946cd6a6acSopenharmony_ci
956cd6a6acSopenharmony_ci	*record = tmp_record;
966cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
976cd6a6acSopenharmony_ci
986cd6a6acSopenharmony_ci      err:
996cd6a6acSopenharmony_ci	/* FIXME: handle error */
1006cd6a6acSopenharmony_ci	sepol_user_free(tmp_record);
1016cd6a6acSopenharmony_ci	return STATUS_ERR;
1026cd6a6acSopenharmony_ci}
1036cd6a6acSopenharmony_ci
1046cd6a6acSopenharmony_ciint sepol_user_modify(sepol_handle_t * handle,
1056cd6a6acSopenharmony_ci		      sepol_policydb_t * p,
1066cd6a6acSopenharmony_ci		      const sepol_user_key_t * key, const sepol_user_t * user)
1076cd6a6acSopenharmony_ci{
1086cd6a6acSopenharmony_ci
1096cd6a6acSopenharmony_ci	policydb_t *policydb = &p->p;
1106cd6a6acSopenharmony_ci
1116cd6a6acSopenharmony_ci	/* For user data */
1126cd6a6acSopenharmony_ci	const char *cname, *cmls_level, *cmls_range;
1136cd6a6acSopenharmony_ci	char *name = NULL;
1146cd6a6acSopenharmony_ci
1156cd6a6acSopenharmony_ci	const char **roles = NULL;
1166cd6a6acSopenharmony_ci	unsigned int num_roles = 0;
1176cd6a6acSopenharmony_ci
1186cd6a6acSopenharmony_ci	/* Low-level representation */
1196cd6a6acSopenharmony_ci	user_datum_t *usrdatum = NULL;
1206cd6a6acSopenharmony_ci	role_datum_t *roldatum;
1216cd6a6acSopenharmony_ci	unsigned int i;
1226cd6a6acSopenharmony_ci
1236cd6a6acSopenharmony_ci	context_struct_t context;
1246cd6a6acSopenharmony_ci	unsigned bit;
1256cd6a6acSopenharmony_ci	int new = 0;
1266cd6a6acSopenharmony_ci
1276cd6a6acSopenharmony_ci	ebitmap_node_t *rnode;
1286cd6a6acSopenharmony_ci
1296cd6a6acSopenharmony_ci	/* First, extract all the data */
1306cd6a6acSopenharmony_ci	sepol_user_key_unpack(key, &cname);
1316cd6a6acSopenharmony_ci
1326cd6a6acSopenharmony_ci	cmls_level = sepol_user_get_mlslevel(user);
1336cd6a6acSopenharmony_ci	cmls_range = sepol_user_get_mlsrange(user);
1346cd6a6acSopenharmony_ci
1356cd6a6acSopenharmony_ci	/* Make sure that worked properly */
1366cd6a6acSopenharmony_ci	if (sepol_user_get_roles(handle, user, &roles, &num_roles) < 0)
1376cd6a6acSopenharmony_ci		goto err;
1386cd6a6acSopenharmony_ci
1396cd6a6acSopenharmony_ci	/* Now, see if a user exists */
1406cd6a6acSopenharmony_ci	usrdatum = hashtab_search(policydb->p_users.table, cname);
1416cd6a6acSopenharmony_ci
1426cd6a6acSopenharmony_ci	/* If it does, we will modify it */
1436cd6a6acSopenharmony_ci	if (usrdatum) {
1446cd6a6acSopenharmony_ci
1456cd6a6acSopenharmony_ci		int value_cp = usrdatum->s.value;
1466cd6a6acSopenharmony_ci		user_datum_destroy(usrdatum);
1476cd6a6acSopenharmony_ci		user_datum_init(usrdatum);
1486cd6a6acSopenharmony_ci		usrdatum->s.value = value_cp;
1496cd6a6acSopenharmony_ci
1506cd6a6acSopenharmony_ci		/* Otherwise, create a new one */
1516cd6a6acSopenharmony_ci	} else {
1526cd6a6acSopenharmony_ci		usrdatum = (user_datum_t *) malloc(sizeof(user_datum_t));
1536cd6a6acSopenharmony_ci		if (!usrdatum)
1546cd6a6acSopenharmony_ci			goto omem;
1556cd6a6acSopenharmony_ci		user_datum_init(usrdatum);
1566cd6a6acSopenharmony_ci		new = 1;
1576cd6a6acSopenharmony_ci	}
1586cd6a6acSopenharmony_ci
1596cd6a6acSopenharmony_ci	/* For every role */
1606cd6a6acSopenharmony_ci	for (i = 0; i < num_roles; i++) {
1616cd6a6acSopenharmony_ci
1626cd6a6acSopenharmony_ci		/* Search for the role */
1636cd6a6acSopenharmony_ci		roldatum = hashtab_search(policydb->p_roles.table, roles[i]);
1646cd6a6acSopenharmony_ci		if (!roldatum) {
1656cd6a6acSopenharmony_ci			ERR(handle, "undefined role %s for user %s",
1666cd6a6acSopenharmony_ci			    roles[i], cname);
1676cd6a6acSopenharmony_ci			goto err;
1686cd6a6acSopenharmony_ci		}
1696cd6a6acSopenharmony_ci
1706cd6a6acSopenharmony_ci		/* Set the role and every role it dominates */
1716cd6a6acSopenharmony_ci		ebitmap_for_each_positive_bit(&roldatum->dominates, rnode, bit) {
1726cd6a6acSopenharmony_ci			if (ebitmap_set_bit(&(usrdatum->roles.roles), bit, 1))
1736cd6a6acSopenharmony_ci				goto omem;
1746cd6a6acSopenharmony_ci		}
1756cd6a6acSopenharmony_ci	}
1766cd6a6acSopenharmony_ci
1776cd6a6acSopenharmony_ci	/* For MLS systems */
1786cd6a6acSopenharmony_ci	if (policydb->mls) {
1796cd6a6acSopenharmony_ci
1806cd6a6acSopenharmony_ci		/* MLS level */
1816cd6a6acSopenharmony_ci		if (cmls_level == NULL) {
1826cd6a6acSopenharmony_ci			ERR(handle, "MLS is enabled, but no MLS "
1836cd6a6acSopenharmony_ci			    "default level was defined for user %s", cname);
1846cd6a6acSopenharmony_ci			goto err;
1856cd6a6acSopenharmony_ci		}
1866cd6a6acSopenharmony_ci
1876cd6a6acSopenharmony_ci		context_init(&context);
1886cd6a6acSopenharmony_ci		if (mls_from_string(handle, policydb, cmls_level, &context) < 0) {
1896cd6a6acSopenharmony_ci			context_destroy(&context);
1906cd6a6acSopenharmony_ci			goto err;
1916cd6a6acSopenharmony_ci		}
1926cd6a6acSopenharmony_ci		if (mls_level_cpy(&usrdatum->exp_dfltlevel,
1936cd6a6acSopenharmony_ci				  &context.range.level[0]) < 0) {
1946cd6a6acSopenharmony_ci			ERR(handle, "could not copy MLS level %s", cmls_level);
1956cd6a6acSopenharmony_ci			context_destroy(&context);
1966cd6a6acSopenharmony_ci			goto err;
1976cd6a6acSopenharmony_ci		}
1986cd6a6acSopenharmony_ci		context_destroy(&context);
1996cd6a6acSopenharmony_ci
2006cd6a6acSopenharmony_ci		/* MLS range */
2016cd6a6acSopenharmony_ci		if (cmls_range == NULL) {
2026cd6a6acSopenharmony_ci			ERR(handle, "MLS is enabled, but no MLS"
2036cd6a6acSopenharmony_ci			    "range was defined for user %s", cname);
2046cd6a6acSopenharmony_ci			goto err;
2056cd6a6acSopenharmony_ci		}
2066cd6a6acSopenharmony_ci
2076cd6a6acSopenharmony_ci		context_init(&context);
2086cd6a6acSopenharmony_ci		if (mls_from_string(handle, policydb, cmls_range, &context) < 0) {
2096cd6a6acSopenharmony_ci			context_destroy(&context);
2106cd6a6acSopenharmony_ci			goto err;
2116cd6a6acSopenharmony_ci		}
2126cd6a6acSopenharmony_ci		if (mls_range_cpy(&usrdatum->exp_range, &context.range) < 0) {
2136cd6a6acSopenharmony_ci			ERR(handle, "could not copy MLS range %s", cmls_range);
2146cd6a6acSopenharmony_ci			context_destroy(&context);
2156cd6a6acSopenharmony_ci			goto err;
2166cd6a6acSopenharmony_ci		}
2176cd6a6acSopenharmony_ci		context_destroy(&context);
2186cd6a6acSopenharmony_ci	} else if (cmls_level != NULL || cmls_range != NULL) {
2196cd6a6acSopenharmony_ci		ERR(handle, "MLS is disabled, but MLS level/range "
2206cd6a6acSopenharmony_ci		    "was found for user %s", cname);
2216cd6a6acSopenharmony_ci		goto err;
2226cd6a6acSopenharmony_ci	}
2236cd6a6acSopenharmony_ci
2246cd6a6acSopenharmony_ci	/* If there are no errors, and this is a new user, add the user to policy */
2256cd6a6acSopenharmony_ci	if (new) {
2266cd6a6acSopenharmony_ci		void *tmp_ptr;
2276cd6a6acSopenharmony_ci
2286cd6a6acSopenharmony_ci		/* Ensure reverse lookup array has enough space */
2296cd6a6acSopenharmony_ci		tmp_ptr = reallocarray(policydb->user_val_to_struct,
2306cd6a6acSopenharmony_ci				  policydb->p_users.nprim + 1,
2316cd6a6acSopenharmony_ci				  sizeof(user_datum_t *));
2326cd6a6acSopenharmony_ci		if (!tmp_ptr)
2336cd6a6acSopenharmony_ci			goto omem;
2346cd6a6acSopenharmony_ci		policydb->user_val_to_struct = tmp_ptr;
2356cd6a6acSopenharmony_ci		policydb->user_val_to_struct[policydb->p_users.nprim] = NULL;
2366cd6a6acSopenharmony_ci
2376cd6a6acSopenharmony_ci		tmp_ptr = reallocarray(policydb->sym_val_to_name[SYM_USERS],
2386cd6a6acSopenharmony_ci				  policydb->p_users.nprim + 1,
2396cd6a6acSopenharmony_ci				  sizeof(char *));
2406cd6a6acSopenharmony_ci		if (!tmp_ptr)
2416cd6a6acSopenharmony_ci			goto omem;
2426cd6a6acSopenharmony_ci		policydb->sym_val_to_name[SYM_USERS] = tmp_ptr;
2436cd6a6acSopenharmony_ci		policydb->p_user_val_to_name[policydb->p_users.nprim] = NULL;
2446cd6a6acSopenharmony_ci
2456cd6a6acSopenharmony_ci		/* Need to copy the user name */
2466cd6a6acSopenharmony_ci		name = strdup(cname);
2476cd6a6acSopenharmony_ci		if (!name)
2486cd6a6acSopenharmony_ci			goto omem;
2496cd6a6acSopenharmony_ci
2506cd6a6acSopenharmony_ci		/* Store user */
2516cd6a6acSopenharmony_ci		usrdatum->s.value = ++policydb->p_users.nprim;
2526cd6a6acSopenharmony_ci		if (hashtab_insert(policydb->p_users.table, name,
2536cd6a6acSopenharmony_ci				   (hashtab_datum_t) usrdatum) < 0)
2546cd6a6acSopenharmony_ci			goto omem;
2556cd6a6acSopenharmony_ci
2566cd6a6acSopenharmony_ci		/* Set up reverse entry */
2576cd6a6acSopenharmony_ci		policydb->p_user_val_to_name[usrdatum->s.value - 1] = name;
2586cd6a6acSopenharmony_ci		policydb->user_val_to_struct[usrdatum->s.value - 1] = usrdatum;
2596cd6a6acSopenharmony_ci		name = NULL;
2606cd6a6acSopenharmony_ci
2616cd6a6acSopenharmony_ci		/* Expand roles */
2626cd6a6acSopenharmony_ci		if (role_set_expand(&usrdatum->roles, &usrdatum->cache,
2636cd6a6acSopenharmony_ci				    policydb, NULL, NULL)) {
2646cd6a6acSopenharmony_ci			ERR(handle, "unable to expand role set");
2656cd6a6acSopenharmony_ci			goto err;
2666cd6a6acSopenharmony_ci		}
2676cd6a6acSopenharmony_ci	}
2686cd6a6acSopenharmony_ci
2696cd6a6acSopenharmony_ci	free(roles);
2706cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
2716cd6a6acSopenharmony_ci
2726cd6a6acSopenharmony_ci      omem:
2736cd6a6acSopenharmony_ci	ERR(handle, "out of memory");
2746cd6a6acSopenharmony_ci
2756cd6a6acSopenharmony_ci      err:
2766cd6a6acSopenharmony_ci	ERR(handle, "could not load %s into policy", name);
2776cd6a6acSopenharmony_ci
2786cd6a6acSopenharmony_ci	free(name);
2796cd6a6acSopenharmony_ci	free(roles);
2806cd6a6acSopenharmony_ci	if (new && usrdatum) {
2816cd6a6acSopenharmony_ci		role_set_destroy(&usrdatum->roles);
2826cd6a6acSopenharmony_ci		free(usrdatum);
2836cd6a6acSopenharmony_ci	}
2846cd6a6acSopenharmony_ci	return STATUS_ERR;
2856cd6a6acSopenharmony_ci}
2866cd6a6acSopenharmony_ci
2876cd6a6acSopenharmony_ciint sepol_user_exists(sepol_handle_t * handle __attribute__ ((unused)),
2886cd6a6acSopenharmony_ci		      const sepol_policydb_t * p,
2896cd6a6acSopenharmony_ci		      const sepol_user_key_t * key, int *response)
2906cd6a6acSopenharmony_ci{
2916cd6a6acSopenharmony_ci
2926cd6a6acSopenharmony_ci	const policydb_t *policydb = &p->p;
2936cd6a6acSopenharmony_ci
2946cd6a6acSopenharmony_ci	const char *cname;
2956cd6a6acSopenharmony_ci	sepol_user_key_unpack(key, &cname);
2966cd6a6acSopenharmony_ci
2976cd6a6acSopenharmony_ci	*response = (hashtab_search(policydb->p_users.table, cname) != NULL);
2986cd6a6acSopenharmony_ci
2996cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
3006cd6a6acSopenharmony_ci}
3016cd6a6acSopenharmony_ci
3026cd6a6acSopenharmony_ciint sepol_user_count(sepol_handle_t * handle __attribute__ ((unused)),
3036cd6a6acSopenharmony_ci		     const sepol_policydb_t * p, unsigned int *response)
3046cd6a6acSopenharmony_ci{
3056cd6a6acSopenharmony_ci
3066cd6a6acSopenharmony_ci	const policydb_t *policydb = &p->p;
3076cd6a6acSopenharmony_ci	*response = policydb->p_users.nprim;
3086cd6a6acSopenharmony_ci
3096cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
3106cd6a6acSopenharmony_ci}
3116cd6a6acSopenharmony_ci
3126cd6a6acSopenharmony_ciint sepol_user_query(sepol_handle_t * handle,
3136cd6a6acSopenharmony_ci		     const sepol_policydb_t * p,
3146cd6a6acSopenharmony_ci		     const sepol_user_key_t * key, sepol_user_t ** response)
3156cd6a6acSopenharmony_ci{
3166cd6a6acSopenharmony_ci
3176cd6a6acSopenharmony_ci	const policydb_t *policydb = &p->p;
3186cd6a6acSopenharmony_ci	user_datum_t *usrdatum = NULL;
3196cd6a6acSopenharmony_ci
3206cd6a6acSopenharmony_ci	const char *cname;
3216cd6a6acSopenharmony_ci	sepol_user_key_unpack(key, &cname);
3226cd6a6acSopenharmony_ci
3236cd6a6acSopenharmony_ci	usrdatum = hashtab_search(policydb->p_users.table, cname);
3246cd6a6acSopenharmony_ci
3256cd6a6acSopenharmony_ci	if (!usrdatum) {
3266cd6a6acSopenharmony_ci		*response = NULL;
3276cd6a6acSopenharmony_ci		return STATUS_SUCCESS;
3286cd6a6acSopenharmony_ci	}
3296cd6a6acSopenharmony_ci
3306cd6a6acSopenharmony_ci	if (user_to_record(handle, policydb, usrdatum->s.value - 1, response) <
3316cd6a6acSopenharmony_ci	    0)
3326cd6a6acSopenharmony_ci		goto err;
3336cd6a6acSopenharmony_ci
3346cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
3356cd6a6acSopenharmony_ci
3366cd6a6acSopenharmony_ci      err:
3376cd6a6acSopenharmony_ci	ERR(handle, "could not query user %s", cname);
3386cd6a6acSopenharmony_ci	return STATUS_ERR;
3396cd6a6acSopenharmony_ci}
3406cd6a6acSopenharmony_ci
3416cd6a6acSopenharmony_ciint sepol_user_iterate(sepol_handle_t * handle,
3426cd6a6acSopenharmony_ci		       const sepol_policydb_t * p,
3436cd6a6acSopenharmony_ci		       int (*fn) (const sepol_user_t * user,
3446cd6a6acSopenharmony_ci				  void *fn_arg), void *arg)
3456cd6a6acSopenharmony_ci{
3466cd6a6acSopenharmony_ci
3476cd6a6acSopenharmony_ci	const policydb_t *policydb = &p->p;
3486cd6a6acSopenharmony_ci	unsigned int nusers = policydb->p_users.nprim;
3496cd6a6acSopenharmony_ci	sepol_user_t *user = NULL;
3506cd6a6acSopenharmony_ci	unsigned int i;
3516cd6a6acSopenharmony_ci
3526cd6a6acSopenharmony_ci	/* For each user */
3536cd6a6acSopenharmony_ci	for (i = 0; i < nusers; i++) {
3546cd6a6acSopenharmony_ci
3556cd6a6acSopenharmony_ci		int status;
3566cd6a6acSopenharmony_ci
3576cd6a6acSopenharmony_ci		if (user_to_record(handle, policydb, i, &user) < 0)
3586cd6a6acSopenharmony_ci			goto err;
3596cd6a6acSopenharmony_ci
3606cd6a6acSopenharmony_ci		/* Invoke handler */
3616cd6a6acSopenharmony_ci		status = fn(user, arg);
3626cd6a6acSopenharmony_ci		if (status < 0)
3636cd6a6acSopenharmony_ci			goto err;
3646cd6a6acSopenharmony_ci
3656cd6a6acSopenharmony_ci		sepol_user_free(user);
3666cd6a6acSopenharmony_ci		user = NULL;
3676cd6a6acSopenharmony_ci
3686cd6a6acSopenharmony_ci		/* Handler requested exit */
3696cd6a6acSopenharmony_ci		if (status > 0)
3706cd6a6acSopenharmony_ci			break;
3716cd6a6acSopenharmony_ci	}
3726cd6a6acSopenharmony_ci
3736cd6a6acSopenharmony_ci	return STATUS_SUCCESS;
3746cd6a6acSopenharmony_ci
3756cd6a6acSopenharmony_ci      err:
3766cd6a6acSopenharmony_ci	ERR(handle, "could not iterate over users");
3776cd6a6acSopenharmony_ci	sepol_user_free(user);
3786cd6a6acSopenharmony_ci	return STATUS_ERR;
3796cd6a6acSopenharmony_ci}
380