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