16cd6a6acSopenharmony_ci/* Author : Stephen Smalley, <sds@tycho.nsa.gov> */ 26cd6a6acSopenharmony_ci/* 36cd6a6acSopenharmony_ci * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> 46cd6a6acSopenharmony_ci * 56cd6a6acSopenharmony_ci * Support for enhanced MLS infrastructure. 66cd6a6acSopenharmony_ci * 76cd6a6acSopenharmony_ci * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. 86cd6a6acSopenharmony_ci * 96cd6a6acSopenharmony_ci * This library is free software; you can redistribute it and/or 106cd6a6acSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 116cd6a6acSopenharmony_ci * License as published by the Free Software Foundation; either 126cd6a6acSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 136cd6a6acSopenharmony_ci * 146cd6a6acSopenharmony_ci * This library is distributed in the hope that it will be useful, 156cd6a6acSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 166cd6a6acSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 176cd6a6acSopenharmony_ci * Lesser General Public License for more details. 186cd6a6acSopenharmony_ci * 196cd6a6acSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 206cd6a6acSopenharmony_ci * License along with this library; if not, write to the Free Software 216cd6a6acSopenharmony_ci * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 226cd6a6acSopenharmony_ci */ 236cd6a6acSopenharmony_ci 246cd6a6acSopenharmony_ci/* FLASK */ 256cd6a6acSopenharmony_ci 266cd6a6acSopenharmony_ci/* 276cd6a6acSopenharmony_ci * Implementation of the multi-level security (MLS) policy. 286cd6a6acSopenharmony_ci */ 296cd6a6acSopenharmony_ci 306cd6a6acSopenharmony_ci#include <sepol/context.h> 316cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h> 326cd6a6acSopenharmony_ci#include <sepol/policydb/services.h> 336cd6a6acSopenharmony_ci#include <sepol/policydb/context.h> 346cd6a6acSopenharmony_ci 356cd6a6acSopenharmony_ci#include <stdlib.h> 366cd6a6acSopenharmony_ci 376cd6a6acSopenharmony_ci#include "handle.h" 386cd6a6acSopenharmony_ci#include "debug.h" 396cd6a6acSopenharmony_ci#include "private.h" 406cd6a6acSopenharmony_ci#include "mls.h" 416cd6a6acSopenharmony_ci 426cd6a6acSopenharmony_ciint mls_to_string(sepol_handle_t * handle, 436cd6a6acSopenharmony_ci const policydb_t * policydb, 446cd6a6acSopenharmony_ci const context_struct_t * mls, char **str) 456cd6a6acSopenharmony_ci{ 466cd6a6acSopenharmony_ci 476cd6a6acSopenharmony_ci char *ptr = NULL, *ptr2 = NULL; 486cd6a6acSopenharmony_ci 496cd6a6acSopenharmony_ci /* Temporary buffer - length + NULL terminator */ 506cd6a6acSopenharmony_ci int len = mls_compute_context_len(policydb, mls) + 1; 516cd6a6acSopenharmony_ci 526cd6a6acSopenharmony_ci ptr = (char *)malloc(len); 536cd6a6acSopenharmony_ci if (ptr == NULL) 546cd6a6acSopenharmony_ci goto omem; 556cd6a6acSopenharmony_ci 566cd6a6acSopenharmony_ci /* Final string w/ ':' cut off */ 576cd6a6acSopenharmony_ci ptr2 = (char *)malloc(len - 1); 586cd6a6acSopenharmony_ci if (ptr2 == NULL) 596cd6a6acSopenharmony_ci goto omem; 606cd6a6acSopenharmony_ci 616cd6a6acSopenharmony_ci mls_sid_to_context(policydb, mls, &ptr); 626cd6a6acSopenharmony_ci ptr -= len - 1; 636cd6a6acSopenharmony_ci strcpy(ptr2, ptr + 1); 646cd6a6acSopenharmony_ci 656cd6a6acSopenharmony_ci free(ptr); 666cd6a6acSopenharmony_ci *str = ptr2; 676cd6a6acSopenharmony_ci return STATUS_SUCCESS; 686cd6a6acSopenharmony_ci 696cd6a6acSopenharmony_ci omem: 706cd6a6acSopenharmony_ci ERR(handle, "out of memory, could not convert mls context to string"); 716cd6a6acSopenharmony_ci 726cd6a6acSopenharmony_ci free(ptr); 736cd6a6acSopenharmony_ci free(ptr2); 746cd6a6acSopenharmony_ci return STATUS_ERR; 756cd6a6acSopenharmony_ci 766cd6a6acSopenharmony_ci} 776cd6a6acSopenharmony_ci 786cd6a6acSopenharmony_ciint mls_from_string(sepol_handle_t * handle, 796cd6a6acSopenharmony_ci const policydb_t * policydb, 806cd6a6acSopenharmony_ci const char *str, context_struct_t * mls) 816cd6a6acSopenharmony_ci{ 826cd6a6acSopenharmony_ci 836cd6a6acSopenharmony_ci char *tmp = strdup(str); 846cd6a6acSopenharmony_ci char *tmp_cp = tmp; 856cd6a6acSopenharmony_ci if (!tmp) 866cd6a6acSopenharmony_ci goto omem; 876cd6a6acSopenharmony_ci 886cd6a6acSopenharmony_ci if (mls_context_to_sid(policydb, '$', &tmp_cp, mls) < 0) { 896cd6a6acSopenharmony_ci ERR(handle, "invalid MLS context %s", str); 906cd6a6acSopenharmony_ci free(tmp); 916cd6a6acSopenharmony_ci goto err; 926cd6a6acSopenharmony_ci } 936cd6a6acSopenharmony_ci 946cd6a6acSopenharmony_ci free(tmp); 956cd6a6acSopenharmony_ci return STATUS_SUCCESS; 966cd6a6acSopenharmony_ci 976cd6a6acSopenharmony_ci omem: 986cd6a6acSopenharmony_ci ERR(handle, "out of memory"); 996cd6a6acSopenharmony_ci 1006cd6a6acSopenharmony_ci err: 1016cd6a6acSopenharmony_ci ERR(handle, "could not construct mls context structure"); 1026cd6a6acSopenharmony_ci return STATUS_ERR; 1036cd6a6acSopenharmony_ci} 1046cd6a6acSopenharmony_ci 1056cd6a6acSopenharmony_ci/* 1066cd6a6acSopenharmony_ci * Return the length in bytes for the MLS fields of the 1076cd6a6acSopenharmony_ci * security context string representation of `context'. 1086cd6a6acSopenharmony_ci */ 1096cd6a6acSopenharmony_ciint mls_compute_context_len(const policydb_t * policydb, 1106cd6a6acSopenharmony_ci const context_struct_t * context) 1116cd6a6acSopenharmony_ci{ 1126cd6a6acSopenharmony_ci 1136cd6a6acSopenharmony_ci unsigned int i, l, len, range; 1146cd6a6acSopenharmony_ci ebitmap_node_t *cnode; 1156cd6a6acSopenharmony_ci 1166cd6a6acSopenharmony_ci if (!policydb->mls) 1176cd6a6acSopenharmony_ci return 0; 1186cd6a6acSopenharmony_ci 1196cd6a6acSopenharmony_ci len = 1; /* for the beginning ":" */ 1206cd6a6acSopenharmony_ci for (l = 0; l < 2; l++) { 1216cd6a6acSopenharmony_ci range = 0; 1226cd6a6acSopenharmony_ci len += 1236cd6a6acSopenharmony_ci strlen(policydb-> 1246cd6a6acSopenharmony_ci p_sens_val_to_name[context->range.level[l].sens - 1256cd6a6acSopenharmony_ci 1]); 1266cd6a6acSopenharmony_ci 1276cd6a6acSopenharmony_ci ebitmap_for_each_bit(&context->range.level[l].cat, cnode, i) { 1286cd6a6acSopenharmony_ci if (ebitmap_node_get_bit(cnode, i)) { 1296cd6a6acSopenharmony_ci if (range) { 1306cd6a6acSopenharmony_ci range++; 1316cd6a6acSopenharmony_ci continue; 1326cd6a6acSopenharmony_ci } 1336cd6a6acSopenharmony_ci 1346cd6a6acSopenharmony_ci len += 1356cd6a6acSopenharmony_ci strlen(policydb->p_cat_val_to_name[i]) + 1; 1366cd6a6acSopenharmony_ci range++; 1376cd6a6acSopenharmony_ci } else { 1386cd6a6acSopenharmony_ci if (range > 1) 1396cd6a6acSopenharmony_ci len += 1406cd6a6acSopenharmony_ci strlen(policydb-> 1416cd6a6acSopenharmony_ci p_cat_val_to_name[i - 1]) + 1426cd6a6acSopenharmony_ci 1; 1436cd6a6acSopenharmony_ci range = 0; 1446cd6a6acSopenharmony_ci } 1456cd6a6acSopenharmony_ci } 1466cd6a6acSopenharmony_ci /* Handle case where last category is the end of range */ 1476cd6a6acSopenharmony_ci if (range > 1) 1486cd6a6acSopenharmony_ci len += strlen(policydb->p_cat_val_to_name[i - 1]) + 1; 1496cd6a6acSopenharmony_ci 1506cd6a6acSopenharmony_ci if (l == 0) { 1516cd6a6acSopenharmony_ci if (mls_level_eq(&context->range.level[0], 1526cd6a6acSopenharmony_ci &context->range.level[1])) 1536cd6a6acSopenharmony_ci break; 1546cd6a6acSopenharmony_ci else 1556cd6a6acSopenharmony_ci len++; 1566cd6a6acSopenharmony_ci } 1576cd6a6acSopenharmony_ci } 1586cd6a6acSopenharmony_ci 1596cd6a6acSopenharmony_ci return len; 1606cd6a6acSopenharmony_ci} 1616cd6a6acSopenharmony_ci 1626cd6a6acSopenharmony_ci/* 1636cd6a6acSopenharmony_ci * Write the security context string representation of 1646cd6a6acSopenharmony_ci * the MLS fields of `context' into the string `*scontext'. 1656cd6a6acSopenharmony_ci * Update `*scontext' to point to the end of the MLS fields. 1666cd6a6acSopenharmony_ci */ 1676cd6a6acSopenharmony_civoid mls_sid_to_context(const policydb_t * policydb, 1686cd6a6acSopenharmony_ci const context_struct_t * context, char **scontext) 1696cd6a6acSopenharmony_ci{ 1706cd6a6acSopenharmony_ci 1716cd6a6acSopenharmony_ci char *scontextp; 1726cd6a6acSopenharmony_ci unsigned int i, l, range, wrote_sep; 1736cd6a6acSopenharmony_ci ebitmap_node_t *cnode; 1746cd6a6acSopenharmony_ci 1756cd6a6acSopenharmony_ci if (!policydb->mls) 1766cd6a6acSopenharmony_ci return; 1776cd6a6acSopenharmony_ci 1786cd6a6acSopenharmony_ci scontextp = *scontext; 1796cd6a6acSopenharmony_ci 1806cd6a6acSopenharmony_ci *scontextp = ':'; 1816cd6a6acSopenharmony_ci scontextp++; 1826cd6a6acSopenharmony_ci 1836cd6a6acSopenharmony_ci for (l = 0; l < 2; l++) { 1846cd6a6acSopenharmony_ci range = 0; 1856cd6a6acSopenharmony_ci wrote_sep = 0; 1866cd6a6acSopenharmony_ci strcpy(scontextp, 1876cd6a6acSopenharmony_ci policydb->p_sens_val_to_name[context->range.level[l]. 1886cd6a6acSopenharmony_ci sens - 1]); 1896cd6a6acSopenharmony_ci scontextp += 1906cd6a6acSopenharmony_ci strlen(policydb-> 1916cd6a6acSopenharmony_ci p_sens_val_to_name[context->range.level[l].sens - 1926cd6a6acSopenharmony_ci 1]); 1936cd6a6acSopenharmony_ci /* categories */ 1946cd6a6acSopenharmony_ci ebitmap_for_each_bit(&context->range.level[l].cat, cnode, i) { 1956cd6a6acSopenharmony_ci if (ebitmap_node_get_bit(cnode, i)) { 1966cd6a6acSopenharmony_ci if (range) { 1976cd6a6acSopenharmony_ci range++; 1986cd6a6acSopenharmony_ci continue; 1996cd6a6acSopenharmony_ci } 2006cd6a6acSopenharmony_ci 2016cd6a6acSopenharmony_ci if (!wrote_sep) { 2026cd6a6acSopenharmony_ci *scontextp++ = ':'; 2036cd6a6acSopenharmony_ci wrote_sep = 1; 2046cd6a6acSopenharmony_ci } else 2056cd6a6acSopenharmony_ci *scontextp++ = ','; 2066cd6a6acSopenharmony_ci strcpy(scontextp, 2076cd6a6acSopenharmony_ci policydb->p_cat_val_to_name[i]); 2086cd6a6acSopenharmony_ci scontextp += 2096cd6a6acSopenharmony_ci strlen(policydb->p_cat_val_to_name[i]); 2106cd6a6acSopenharmony_ci range++; 2116cd6a6acSopenharmony_ci } else { 2126cd6a6acSopenharmony_ci if (range > 1) { 2136cd6a6acSopenharmony_ci if (range > 2) 2146cd6a6acSopenharmony_ci *scontextp++ = '.'; 2156cd6a6acSopenharmony_ci else 2166cd6a6acSopenharmony_ci *scontextp++ = ','; 2176cd6a6acSopenharmony_ci 2186cd6a6acSopenharmony_ci strcpy(scontextp, 2196cd6a6acSopenharmony_ci policydb->p_cat_val_to_name[i - 2206cd6a6acSopenharmony_ci 1]); 2216cd6a6acSopenharmony_ci scontextp += 2226cd6a6acSopenharmony_ci strlen(policydb-> 2236cd6a6acSopenharmony_ci p_cat_val_to_name[i - 1]); 2246cd6a6acSopenharmony_ci } 2256cd6a6acSopenharmony_ci range = 0; 2266cd6a6acSopenharmony_ci } 2276cd6a6acSopenharmony_ci } 2286cd6a6acSopenharmony_ci /* Handle case where last category is the end of range */ 2296cd6a6acSopenharmony_ci if (range > 1) { 2306cd6a6acSopenharmony_ci if (range > 2) 2316cd6a6acSopenharmony_ci *scontextp++ = '.'; 2326cd6a6acSopenharmony_ci else 2336cd6a6acSopenharmony_ci *scontextp++ = ','; 2346cd6a6acSopenharmony_ci 2356cd6a6acSopenharmony_ci strcpy(scontextp, policydb->p_cat_val_to_name[i - 1]); 2366cd6a6acSopenharmony_ci scontextp += strlen(policydb->p_cat_val_to_name[i - 1]); 2376cd6a6acSopenharmony_ci } 2386cd6a6acSopenharmony_ci 2396cd6a6acSopenharmony_ci if (l == 0) { 2406cd6a6acSopenharmony_ci if (mls_level_eq(&context->range.level[0], 2416cd6a6acSopenharmony_ci &context->range.level[1])) 2426cd6a6acSopenharmony_ci break; 2436cd6a6acSopenharmony_ci else { 2446cd6a6acSopenharmony_ci *scontextp = '-'; 2456cd6a6acSopenharmony_ci scontextp++; 2466cd6a6acSopenharmony_ci } 2476cd6a6acSopenharmony_ci } 2486cd6a6acSopenharmony_ci } 2496cd6a6acSopenharmony_ci 2506cd6a6acSopenharmony_ci *scontext = scontextp; 2516cd6a6acSopenharmony_ci return; 2526cd6a6acSopenharmony_ci} 2536cd6a6acSopenharmony_ci 2546cd6a6acSopenharmony_ci/* 2556cd6a6acSopenharmony_ci * Return 1 if the MLS fields in the security context 2566cd6a6acSopenharmony_ci * structure `c' are valid. Return 0 otherwise. 2576cd6a6acSopenharmony_ci */ 2586cd6a6acSopenharmony_ciint mls_context_isvalid(const policydb_t * p, const context_struct_t * c) 2596cd6a6acSopenharmony_ci{ 2606cd6a6acSopenharmony_ci 2616cd6a6acSopenharmony_ci level_datum_t *levdatum; 2626cd6a6acSopenharmony_ci user_datum_t *usrdatum; 2636cd6a6acSopenharmony_ci unsigned int i, l; 2646cd6a6acSopenharmony_ci ebitmap_node_t *cnode; 2656cd6a6acSopenharmony_ci hashtab_key_t key; 2666cd6a6acSopenharmony_ci 2676cd6a6acSopenharmony_ci if (!p->mls) 2686cd6a6acSopenharmony_ci return 1; 2696cd6a6acSopenharmony_ci 2706cd6a6acSopenharmony_ci /* 2716cd6a6acSopenharmony_ci * MLS range validity checks: high must dominate low, low level must 2726cd6a6acSopenharmony_ci * be valid (category set <-> sensitivity check), and high level must 2736cd6a6acSopenharmony_ci * be valid (category set <-> sensitivity check) 2746cd6a6acSopenharmony_ci */ 2756cd6a6acSopenharmony_ci if (!mls_level_dom(&c->range.level[1], &c->range.level[0])) 2766cd6a6acSopenharmony_ci /* High does not dominate low. */ 2776cd6a6acSopenharmony_ci return 0; 2786cd6a6acSopenharmony_ci 2796cd6a6acSopenharmony_ci for (l = 0; l < 2; l++) { 2806cd6a6acSopenharmony_ci if (!c->range.level[l].sens 2816cd6a6acSopenharmony_ci || c->range.level[l].sens > p->p_levels.nprim) 2826cd6a6acSopenharmony_ci return 0; 2836cd6a6acSopenharmony_ci 2846cd6a6acSopenharmony_ci key = p->p_sens_val_to_name[c->range.level[l].sens - 1]; 2856cd6a6acSopenharmony_ci if (!key) 2866cd6a6acSopenharmony_ci return 0; 2876cd6a6acSopenharmony_ci 2886cd6a6acSopenharmony_ci levdatum = (level_datum_t *) hashtab_search(p->p_levels.table, key); 2896cd6a6acSopenharmony_ci if (!levdatum) 2906cd6a6acSopenharmony_ci return 0; 2916cd6a6acSopenharmony_ci 2926cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&c->range.level[l].cat, cnode, i) { 2936cd6a6acSopenharmony_ci if (i > p->p_cats.nprim) 2946cd6a6acSopenharmony_ci return 0; 2956cd6a6acSopenharmony_ci if (!ebitmap_get_bit(&levdatum->level->cat, i)) 2966cd6a6acSopenharmony_ci /* 2976cd6a6acSopenharmony_ci * Category may not be associated with 2986cd6a6acSopenharmony_ci * sensitivity in low level. 2996cd6a6acSopenharmony_ci */ 3006cd6a6acSopenharmony_ci return 0; 3016cd6a6acSopenharmony_ci } 3026cd6a6acSopenharmony_ci } 3036cd6a6acSopenharmony_ci 3046cd6a6acSopenharmony_ci if (c->role == OBJECT_R_VAL) 3056cd6a6acSopenharmony_ci return 1; 3066cd6a6acSopenharmony_ci 3076cd6a6acSopenharmony_ci /* 3086cd6a6acSopenharmony_ci * User must be authorized for the MLS range. 3096cd6a6acSopenharmony_ci */ 3106cd6a6acSopenharmony_ci if (!c->user || c->user > p->p_users.nprim) 3116cd6a6acSopenharmony_ci return 0; 3126cd6a6acSopenharmony_ci usrdatum = p->user_val_to_struct[c->user - 1]; 3136cd6a6acSopenharmony_ci if (!usrdatum || !mls_range_contains(usrdatum->exp_range, c->range)) 3146cd6a6acSopenharmony_ci return 0; /* user may not be associated with range */ 3156cd6a6acSopenharmony_ci 3166cd6a6acSopenharmony_ci return 1; 3176cd6a6acSopenharmony_ci} 3186cd6a6acSopenharmony_ci 3196cd6a6acSopenharmony_ci/* 3206cd6a6acSopenharmony_ci * Set the MLS fields in the security context structure 3216cd6a6acSopenharmony_ci * `context' based on the string representation in 3226cd6a6acSopenharmony_ci * the string `*scontext'. Update `*scontext' to 3236cd6a6acSopenharmony_ci * point to the end of the string representation of 3246cd6a6acSopenharmony_ci * the MLS fields. 3256cd6a6acSopenharmony_ci * 3266cd6a6acSopenharmony_ci * This function modifies the string in place, inserting 3276cd6a6acSopenharmony_ci * NULL characters to terminate the MLS fields. 3286cd6a6acSopenharmony_ci */ 3296cd6a6acSopenharmony_ciint mls_context_to_sid(const policydb_t * policydb, 3306cd6a6acSopenharmony_ci char oldc, char **scontext, context_struct_t * context) 3316cd6a6acSopenharmony_ci{ 3326cd6a6acSopenharmony_ci 3336cd6a6acSopenharmony_ci char delim; 3346cd6a6acSopenharmony_ci char *scontextp, *p, *rngptr; 3356cd6a6acSopenharmony_ci level_datum_t *levdatum; 3366cd6a6acSopenharmony_ci cat_datum_t *catdatum, *rngdatum; 3376cd6a6acSopenharmony_ci unsigned int l; 3386cd6a6acSopenharmony_ci 3396cd6a6acSopenharmony_ci if (!policydb->mls) 3406cd6a6acSopenharmony_ci return 0; 3416cd6a6acSopenharmony_ci 3426cd6a6acSopenharmony_ci /* No MLS component to the security context */ 3436cd6a6acSopenharmony_ci if (!oldc) 3446cd6a6acSopenharmony_ci goto err; 3456cd6a6acSopenharmony_ci 3466cd6a6acSopenharmony_ci /* Extract low sensitivity. */ 3476cd6a6acSopenharmony_ci scontextp = p = *scontext; 3486cd6a6acSopenharmony_ci while (*p && *p != ':' && *p != '-') 3496cd6a6acSopenharmony_ci p++; 3506cd6a6acSopenharmony_ci 3516cd6a6acSopenharmony_ci delim = *p; 3526cd6a6acSopenharmony_ci if (delim != 0) 3536cd6a6acSopenharmony_ci *p++ = 0; 3546cd6a6acSopenharmony_ci 3556cd6a6acSopenharmony_ci for (l = 0; l < 2; l++) { 3566cd6a6acSopenharmony_ci levdatum = 3576cd6a6acSopenharmony_ci (level_datum_t *) hashtab_search(policydb->p_levels.table, 3586cd6a6acSopenharmony_ci (hashtab_key_t) scontextp); 3596cd6a6acSopenharmony_ci 3606cd6a6acSopenharmony_ci if (!levdatum) 3616cd6a6acSopenharmony_ci goto err; 3626cd6a6acSopenharmony_ci 3636cd6a6acSopenharmony_ci context->range.level[l].sens = levdatum->level->sens; 3646cd6a6acSopenharmony_ci 3656cd6a6acSopenharmony_ci if (delim == ':') { 3666cd6a6acSopenharmony_ci /* Extract category set. */ 3676cd6a6acSopenharmony_ci while (1) { 3686cd6a6acSopenharmony_ci scontextp = p; 3696cd6a6acSopenharmony_ci while (*p && *p != ',' && *p != '-') 3706cd6a6acSopenharmony_ci p++; 3716cd6a6acSopenharmony_ci delim = *p; 3726cd6a6acSopenharmony_ci if (delim != 0) 3736cd6a6acSopenharmony_ci *p++ = 0; 3746cd6a6acSopenharmony_ci 3756cd6a6acSopenharmony_ci /* Separate into range if exists */ 3766cd6a6acSopenharmony_ci if ((rngptr = strchr(scontextp, '.')) != NULL) { 3776cd6a6acSopenharmony_ci /* Remove '.' */ 3786cd6a6acSopenharmony_ci *rngptr++ = 0; 3796cd6a6acSopenharmony_ci } 3806cd6a6acSopenharmony_ci 3816cd6a6acSopenharmony_ci catdatum = 3826cd6a6acSopenharmony_ci (cat_datum_t *) hashtab_search(policydb-> 3836cd6a6acSopenharmony_ci p_cats.table, 3846cd6a6acSopenharmony_ci (hashtab_key_t) 3856cd6a6acSopenharmony_ci scontextp); 3866cd6a6acSopenharmony_ci if (!catdatum) 3876cd6a6acSopenharmony_ci goto err; 3886cd6a6acSopenharmony_ci 3896cd6a6acSopenharmony_ci if (ebitmap_set_bit 3906cd6a6acSopenharmony_ci (&context->range.level[l].cat, 3916cd6a6acSopenharmony_ci catdatum->s.value - 1, 1)) 3926cd6a6acSopenharmony_ci goto err; 3936cd6a6acSopenharmony_ci 3946cd6a6acSopenharmony_ci /* If range, set all categories in range */ 3956cd6a6acSopenharmony_ci if (rngptr) { 3966cd6a6acSopenharmony_ci unsigned int i; 3976cd6a6acSopenharmony_ci 3986cd6a6acSopenharmony_ci rngdatum = (cat_datum_t *) 3996cd6a6acSopenharmony_ci hashtab_search(policydb->p_cats. 4006cd6a6acSopenharmony_ci table, 4016cd6a6acSopenharmony_ci (hashtab_key_t) 4026cd6a6acSopenharmony_ci rngptr); 4036cd6a6acSopenharmony_ci if (!rngdatum) 4046cd6a6acSopenharmony_ci goto err; 4056cd6a6acSopenharmony_ci 4066cd6a6acSopenharmony_ci if (catdatum->s.value >= 4076cd6a6acSopenharmony_ci rngdatum->s.value) 4086cd6a6acSopenharmony_ci goto err; 4096cd6a6acSopenharmony_ci 4106cd6a6acSopenharmony_ci for (i = catdatum->s.value; 4116cd6a6acSopenharmony_ci i < rngdatum->s.value; i++) { 4126cd6a6acSopenharmony_ci if (ebitmap_set_bit 4136cd6a6acSopenharmony_ci (&context->range.level[l]. 4146cd6a6acSopenharmony_ci cat, i, 1)) 4156cd6a6acSopenharmony_ci goto err; 4166cd6a6acSopenharmony_ci } 4176cd6a6acSopenharmony_ci } 4186cd6a6acSopenharmony_ci 4196cd6a6acSopenharmony_ci if (delim != ',') 4206cd6a6acSopenharmony_ci break; 4216cd6a6acSopenharmony_ci } 4226cd6a6acSopenharmony_ci } 4236cd6a6acSopenharmony_ci if (delim == '-') { 4246cd6a6acSopenharmony_ci /* Extract high sensitivity. */ 4256cd6a6acSopenharmony_ci scontextp = p; 4266cd6a6acSopenharmony_ci while (*p && *p != ':') 4276cd6a6acSopenharmony_ci p++; 4286cd6a6acSopenharmony_ci 4296cd6a6acSopenharmony_ci delim = *p; 4306cd6a6acSopenharmony_ci if (delim != 0) 4316cd6a6acSopenharmony_ci *p++ = 0; 4326cd6a6acSopenharmony_ci } else 4336cd6a6acSopenharmony_ci break; 4346cd6a6acSopenharmony_ci } 4356cd6a6acSopenharmony_ci 4366cd6a6acSopenharmony_ci /* High level is missing, copy low level */ 4376cd6a6acSopenharmony_ci if (l == 0) { 4386cd6a6acSopenharmony_ci if (mls_level_cpy(&context->range.level[1], 4396cd6a6acSopenharmony_ci &context->range.level[0]) < 0) 4406cd6a6acSopenharmony_ci goto err; 4416cd6a6acSopenharmony_ci } 4426cd6a6acSopenharmony_ci *scontext = ++p; 4436cd6a6acSopenharmony_ci 4446cd6a6acSopenharmony_ci return STATUS_SUCCESS; 4456cd6a6acSopenharmony_ci 4466cd6a6acSopenharmony_ci err: 4476cd6a6acSopenharmony_ci return STATUS_ERR; 4486cd6a6acSopenharmony_ci} 4496cd6a6acSopenharmony_ci 4506cd6a6acSopenharmony_ci/* 4516cd6a6acSopenharmony_ci * Copies the MLS range from `src' into `dst'. 4526cd6a6acSopenharmony_ci */ 4536cd6a6acSopenharmony_cistatic inline int mls_copy_context(context_struct_t * dst, 4546cd6a6acSopenharmony_ci const context_struct_t * src) 4556cd6a6acSopenharmony_ci{ 4566cd6a6acSopenharmony_ci int l, rc = 0; 4576cd6a6acSopenharmony_ci 4586cd6a6acSopenharmony_ci /* Copy the MLS range from the source context */ 4596cd6a6acSopenharmony_ci for (l = 0; l < 2; l++) { 4606cd6a6acSopenharmony_ci dst->range.level[l].sens = src->range.level[l].sens; 4616cd6a6acSopenharmony_ci rc = ebitmap_cpy(&dst->range.level[l].cat, 4626cd6a6acSopenharmony_ci &src->range.level[l].cat); 4636cd6a6acSopenharmony_ci if (rc) 4646cd6a6acSopenharmony_ci break; 4656cd6a6acSopenharmony_ci } 4666cd6a6acSopenharmony_ci 4676cd6a6acSopenharmony_ci return rc; 4686cd6a6acSopenharmony_ci} 4696cd6a6acSopenharmony_ci 4706cd6a6acSopenharmony_ci/* 4716cd6a6acSopenharmony_ci * Copies the effective MLS range from `src' into `dst'. 4726cd6a6acSopenharmony_ci */ 4736cd6a6acSopenharmony_cistatic inline int mls_scopy_context(context_struct_t * dst, 4746cd6a6acSopenharmony_ci const context_struct_t * src) 4756cd6a6acSopenharmony_ci{ 4766cd6a6acSopenharmony_ci int l, rc = 0; 4776cd6a6acSopenharmony_ci 4786cd6a6acSopenharmony_ci /* Copy the MLS range from the source context */ 4796cd6a6acSopenharmony_ci for (l = 0; l < 2; l++) { 4806cd6a6acSopenharmony_ci dst->range.level[l].sens = src->range.level[0].sens; 4816cd6a6acSopenharmony_ci rc = ebitmap_cpy(&dst->range.level[l].cat, 4826cd6a6acSopenharmony_ci &src->range.level[0].cat); 4836cd6a6acSopenharmony_ci if (rc) 4846cd6a6acSopenharmony_ci break; 4856cd6a6acSopenharmony_ci } 4866cd6a6acSopenharmony_ci 4876cd6a6acSopenharmony_ci return rc; 4886cd6a6acSopenharmony_ci} 4896cd6a6acSopenharmony_ci 4906cd6a6acSopenharmony_ci/* 4916cd6a6acSopenharmony_ci * Copies the MLS range `range' into `context'. 4926cd6a6acSopenharmony_ci */ 4936cd6a6acSopenharmony_cistatic inline int mls_range_set(context_struct_t * context, const mls_range_t * range) 4946cd6a6acSopenharmony_ci{ 4956cd6a6acSopenharmony_ci int l, rc = 0; 4966cd6a6acSopenharmony_ci 4976cd6a6acSopenharmony_ci /* Copy the MLS range into the context */ 4986cd6a6acSopenharmony_ci for (l = 0; l < 2; l++) { 4996cd6a6acSopenharmony_ci context->range.level[l].sens = range->level[l].sens; 5006cd6a6acSopenharmony_ci rc = ebitmap_cpy(&context->range.level[l].cat, 5016cd6a6acSopenharmony_ci &range->level[l].cat); 5026cd6a6acSopenharmony_ci if (rc) 5036cd6a6acSopenharmony_ci break; 5046cd6a6acSopenharmony_ci } 5056cd6a6acSopenharmony_ci 5066cd6a6acSopenharmony_ci return rc; 5076cd6a6acSopenharmony_ci} 5086cd6a6acSopenharmony_ci 5096cd6a6acSopenharmony_ciint mls_setup_user_range(context_struct_t * fromcon, user_datum_t * user, 5106cd6a6acSopenharmony_ci context_struct_t * usercon, int mls) 5116cd6a6acSopenharmony_ci{ 5126cd6a6acSopenharmony_ci if (mls) { 5136cd6a6acSopenharmony_ci mls_level_t *fromcon_sen = &(fromcon->range.level[0]); 5146cd6a6acSopenharmony_ci mls_level_t *fromcon_clr = &(fromcon->range.level[1]); 5156cd6a6acSopenharmony_ci mls_level_t *user_low = &(user->exp_range.level[0]); 5166cd6a6acSopenharmony_ci mls_level_t *user_clr = &(user->exp_range.level[1]); 5176cd6a6acSopenharmony_ci mls_level_t *user_def = &(user->exp_dfltlevel); 5186cd6a6acSopenharmony_ci mls_level_t *usercon_sen = &(usercon->range.level[0]); 5196cd6a6acSopenharmony_ci mls_level_t *usercon_clr = &(usercon->range.level[1]); 5206cd6a6acSopenharmony_ci 5216cd6a6acSopenharmony_ci /* Honor the user's default level if we can */ 5226cd6a6acSopenharmony_ci if (mls_level_between(user_def, fromcon_sen, fromcon_clr)) { 5236cd6a6acSopenharmony_ci *usercon_sen = *user_def; 5246cd6a6acSopenharmony_ci } else if (mls_level_between(fromcon_sen, user_def, user_clr)) { 5256cd6a6acSopenharmony_ci *usercon_sen = *fromcon_sen; 5266cd6a6acSopenharmony_ci } else if (mls_level_between(fromcon_clr, user_low, user_def)) { 5276cd6a6acSopenharmony_ci *usercon_sen = *user_low; 5286cd6a6acSopenharmony_ci } else 5296cd6a6acSopenharmony_ci return -EINVAL; 5306cd6a6acSopenharmony_ci 5316cd6a6acSopenharmony_ci /* Lower the clearance of available contexts 5326cd6a6acSopenharmony_ci if the clearance of "fromcon" is lower than 5336cd6a6acSopenharmony_ci that of the user's default clearance (but 5346cd6a6acSopenharmony_ci only if the "fromcon" clearance dominates 5356cd6a6acSopenharmony_ci the user's computed sensitivity level) */ 5366cd6a6acSopenharmony_ci if (mls_level_dom(user_clr, fromcon_clr)) { 5376cd6a6acSopenharmony_ci *usercon_clr = *fromcon_clr; 5386cd6a6acSopenharmony_ci } else if (mls_level_dom(fromcon_clr, user_clr)) { 5396cd6a6acSopenharmony_ci *usercon_clr = *user_clr; 5406cd6a6acSopenharmony_ci } else 5416cd6a6acSopenharmony_ci return -EINVAL; 5426cd6a6acSopenharmony_ci } 5436cd6a6acSopenharmony_ci 5446cd6a6acSopenharmony_ci return 0; 5456cd6a6acSopenharmony_ci} 5466cd6a6acSopenharmony_ci 5476cd6a6acSopenharmony_ci/* 5486cd6a6acSopenharmony_ci * Convert the MLS fields in the security context 5496cd6a6acSopenharmony_ci * structure `c' from the values specified in the 5506cd6a6acSopenharmony_ci * policy `oldp' to the values specified in the policy `newp'. 5516cd6a6acSopenharmony_ci */ 5526cd6a6acSopenharmony_ciint mls_convert_context(policydb_t * oldp, 5536cd6a6acSopenharmony_ci policydb_t * newp, context_struct_t * c) 5546cd6a6acSopenharmony_ci{ 5556cd6a6acSopenharmony_ci level_datum_t *levdatum; 5566cd6a6acSopenharmony_ci cat_datum_t *catdatum; 5576cd6a6acSopenharmony_ci ebitmap_t bitmap; 5586cd6a6acSopenharmony_ci unsigned int l, i; 5596cd6a6acSopenharmony_ci ebitmap_node_t *cnode; 5606cd6a6acSopenharmony_ci 5616cd6a6acSopenharmony_ci if (!oldp->mls) 5626cd6a6acSopenharmony_ci return 0; 5636cd6a6acSopenharmony_ci 5646cd6a6acSopenharmony_ci for (l = 0; l < 2; l++) { 5656cd6a6acSopenharmony_ci levdatum = 5666cd6a6acSopenharmony_ci (level_datum_t *) hashtab_search(newp->p_levels.table, 5676cd6a6acSopenharmony_ci oldp-> 5686cd6a6acSopenharmony_ci p_sens_val_to_name[c-> 5696cd6a6acSopenharmony_ci range. 5706cd6a6acSopenharmony_ci level 5716cd6a6acSopenharmony_ci [l]. 5726cd6a6acSopenharmony_ci sens - 5736cd6a6acSopenharmony_ci 1]); 5746cd6a6acSopenharmony_ci 5756cd6a6acSopenharmony_ci if (!levdatum) 5766cd6a6acSopenharmony_ci return -EINVAL; 5776cd6a6acSopenharmony_ci c->range.level[l].sens = levdatum->level->sens; 5786cd6a6acSopenharmony_ci 5796cd6a6acSopenharmony_ci ebitmap_init(&bitmap); 5806cd6a6acSopenharmony_ci ebitmap_for_each_positive_bit(&c->range.level[l].cat, cnode, i) { 5816cd6a6acSopenharmony_ci int rc; 5826cd6a6acSopenharmony_ci 5836cd6a6acSopenharmony_ci catdatum = 5846cd6a6acSopenharmony_ci (cat_datum_t *) hashtab_search(newp->p_cats. 5856cd6a6acSopenharmony_ci table, 5866cd6a6acSopenharmony_ci oldp-> 5876cd6a6acSopenharmony_ci p_cat_val_to_name 5886cd6a6acSopenharmony_ci [i]); 5896cd6a6acSopenharmony_ci if (!catdatum) 5906cd6a6acSopenharmony_ci return -EINVAL; 5916cd6a6acSopenharmony_ci rc = ebitmap_set_bit(&bitmap, 5926cd6a6acSopenharmony_ci catdatum->s.value - 1, 1); 5936cd6a6acSopenharmony_ci if (rc) 5946cd6a6acSopenharmony_ci return rc; 5956cd6a6acSopenharmony_ci } 5966cd6a6acSopenharmony_ci ebitmap_destroy(&c->range.level[l].cat); 5976cd6a6acSopenharmony_ci c->range.level[l].cat = bitmap; 5986cd6a6acSopenharmony_ci } 5996cd6a6acSopenharmony_ci 6006cd6a6acSopenharmony_ci return 0; 6016cd6a6acSopenharmony_ci} 6026cd6a6acSopenharmony_ci 6036cd6a6acSopenharmony_ciint mls_compute_sid(policydb_t * policydb, 6046cd6a6acSopenharmony_ci const context_struct_t * scontext, 6056cd6a6acSopenharmony_ci const context_struct_t * tcontext, 6066cd6a6acSopenharmony_ci sepol_security_class_t tclass, 6076cd6a6acSopenharmony_ci uint32_t specified, context_struct_t * newcontext) 6086cd6a6acSopenharmony_ci{ 6096cd6a6acSopenharmony_ci range_trans_t rtr; 6106cd6a6acSopenharmony_ci struct mls_range *r; 6116cd6a6acSopenharmony_ci struct class_datum *cladatum; 6126cd6a6acSopenharmony_ci int default_range = 0; 6136cd6a6acSopenharmony_ci 6146cd6a6acSopenharmony_ci if (!policydb->mls) 6156cd6a6acSopenharmony_ci return 0; 6166cd6a6acSopenharmony_ci 6176cd6a6acSopenharmony_ci switch (specified) { 6186cd6a6acSopenharmony_ci case AVTAB_TRANSITION: 6196cd6a6acSopenharmony_ci /* Look for a range transition rule. */ 6206cd6a6acSopenharmony_ci rtr.source_type = scontext->type; 6216cd6a6acSopenharmony_ci rtr.target_type = tcontext->type; 6226cd6a6acSopenharmony_ci rtr.target_class = tclass; 6236cd6a6acSopenharmony_ci r = hashtab_search(policydb->range_tr, (hashtab_key_t) &rtr); 6246cd6a6acSopenharmony_ci if (r) 6256cd6a6acSopenharmony_ci return mls_range_set(newcontext, r); 6266cd6a6acSopenharmony_ci 6276cd6a6acSopenharmony_ci if (tclass && tclass <= policydb->p_classes.nprim) { 6286cd6a6acSopenharmony_ci cladatum = policydb->class_val_to_struct[tclass - 1]; 6296cd6a6acSopenharmony_ci if (cladatum) 6306cd6a6acSopenharmony_ci default_range = cladatum->default_range; 6316cd6a6acSopenharmony_ci } 6326cd6a6acSopenharmony_ci 6336cd6a6acSopenharmony_ci switch (default_range) { 6346cd6a6acSopenharmony_ci case DEFAULT_SOURCE_LOW: 6356cd6a6acSopenharmony_ci return mls_context_cpy_low(newcontext, scontext); 6366cd6a6acSopenharmony_ci case DEFAULT_SOURCE_HIGH: 6376cd6a6acSopenharmony_ci return mls_context_cpy_high(newcontext, scontext); 6386cd6a6acSopenharmony_ci case DEFAULT_SOURCE_LOW_HIGH: 6396cd6a6acSopenharmony_ci return mls_context_cpy(newcontext, scontext); 6406cd6a6acSopenharmony_ci case DEFAULT_TARGET_LOW: 6416cd6a6acSopenharmony_ci return mls_context_cpy_low(newcontext, tcontext); 6426cd6a6acSopenharmony_ci case DEFAULT_TARGET_HIGH: 6436cd6a6acSopenharmony_ci return mls_context_cpy_high(newcontext, tcontext); 6446cd6a6acSopenharmony_ci case DEFAULT_TARGET_LOW_HIGH: 6456cd6a6acSopenharmony_ci return mls_context_cpy(newcontext, tcontext); 6466cd6a6acSopenharmony_ci case DEFAULT_GLBLUB: 6476cd6a6acSopenharmony_ci return mls_context_glblub(newcontext, scontext, tcontext); 6486cd6a6acSopenharmony_ci } 6496cd6a6acSopenharmony_ci 6506cd6a6acSopenharmony_ci /* Fallthrough */ 6516cd6a6acSopenharmony_ci case AVTAB_CHANGE: 6526cd6a6acSopenharmony_ci if (tclass == policydb->process_class) 6536cd6a6acSopenharmony_ci /* Use the process MLS attributes. */ 6546cd6a6acSopenharmony_ci return mls_copy_context(newcontext, scontext); 6556cd6a6acSopenharmony_ci else 6566cd6a6acSopenharmony_ci /* Use the process effective MLS attributes. */ 6576cd6a6acSopenharmony_ci return mls_scopy_context(newcontext, scontext); 6586cd6a6acSopenharmony_ci case AVTAB_MEMBER: 6596cd6a6acSopenharmony_ci /* Use the process effective MLS attributes. */ 6606cd6a6acSopenharmony_ci return mls_context_cpy_low(newcontext, scontext); 6616cd6a6acSopenharmony_ci default: 6626cd6a6acSopenharmony_ci return -EINVAL; 6636cd6a6acSopenharmony_ci } 6646cd6a6acSopenharmony_ci return -EINVAL; 6656cd6a6acSopenharmony_ci} 6666cd6a6acSopenharmony_ci 6676cd6a6acSopenharmony_ciint sepol_mls_contains(sepol_handle_t * handle, 6686cd6a6acSopenharmony_ci const sepol_policydb_t * policydb, 6696cd6a6acSopenharmony_ci const char *mls1, const char *mls2, int *response) 6706cd6a6acSopenharmony_ci{ 6716cd6a6acSopenharmony_ci 6726cd6a6acSopenharmony_ci context_struct_t *ctx1 = NULL, *ctx2 = NULL; 6736cd6a6acSopenharmony_ci ctx1 = malloc(sizeof(context_struct_t)); 6746cd6a6acSopenharmony_ci ctx2 = malloc(sizeof(context_struct_t)); 6756cd6a6acSopenharmony_ci if (ctx1 == NULL || ctx2 == NULL) 6766cd6a6acSopenharmony_ci goto omem; 6776cd6a6acSopenharmony_ci context_init(ctx1); 6786cd6a6acSopenharmony_ci context_init(ctx2); 6796cd6a6acSopenharmony_ci 6806cd6a6acSopenharmony_ci if (mls_from_string(handle, &policydb->p, mls1, ctx1) < 0) 6816cd6a6acSopenharmony_ci goto err; 6826cd6a6acSopenharmony_ci 6836cd6a6acSopenharmony_ci if (mls_from_string(handle, &policydb->p, mls2, ctx2) < 0) 6846cd6a6acSopenharmony_ci goto err; 6856cd6a6acSopenharmony_ci 6866cd6a6acSopenharmony_ci *response = mls_range_contains(ctx1->range, ctx2->range); 6876cd6a6acSopenharmony_ci context_destroy(ctx1); 6886cd6a6acSopenharmony_ci context_destroy(ctx2); 6896cd6a6acSopenharmony_ci free(ctx1); 6906cd6a6acSopenharmony_ci free(ctx2); 6916cd6a6acSopenharmony_ci return STATUS_SUCCESS; 6926cd6a6acSopenharmony_ci 6936cd6a6acSopenharmony_ci omem: 6946cd6a6acSopenharmony_ci ERR(handle, "out of memory"); 6956cd6a6acSopenharmony_ci 6966cd6a6acSopenharmony_ci err: 6976cd6a6acSopenharmony_ci ERR(handle, "could not check if mls context %s contains %s", 6986cd6a6acSopenharmony_ci mls1, mls2); 6996cd6a6acSopenharmony_ci context_destroy(ctx1); 7006cd6a6acSopenharmony_ci context_destroy(ctx2); 7016cd6a6acSopenharmony_ci free(ctx1); 7026cd6a6acSopenharmony_ci free(ctx2); 7036cd6a6acSopenharmony_ci return STATUS_ERR; 7046cd6a6acSopenharmony_ci} 7056cd6a6acSopenharmony_ci 7066cd6a6acSopenharmony_ciint sepol_mls_check(sepol_handle_t * handle, 7076cd6a6acSopenharmony_ci const sepol_policydb_t * policydb, const char *mls) 7086cd6a6acSopenharmony_ci{ 7096cd6a6acSopenharmony_ci 7106cd6a6acSopenharmony_ci int ret; 7116cd6a6acSopenharmony_ci context_struct_t *con = malloc(sizeof(context_struct_t)); 7126cd6a6acSopenharmony_ci if (!con) { 7136cd6a6acSopenharmony_ci ERR(handle, "out of memory, could not check if " 7146cd6a6acSopenharmony_ci "mls context %s is valid", mls); 7156cd6a6acSopenharmony_ci return STATUS_ERR; 7166cd6a6acSopenharmony_ci } 7176cd6a6acSopenharmony_ci context_init(con); 7186cd6a6acSopenharmony_ci 7196cd6a6acSopenharmony_ci ret = mls_from_string(handle, &policydb->p, mls, con); 7206cd6a6acSopenharmony_ci context_destroy(con); 7216cd6a6acSopenharmony_ci free(con); 7226cd6a6acSopenharmony_ci return ret; 7236cd6a6acSopenharmony_ci} 7246cd6a6acSopenharmony_ci 7256cd6a6acSopenharmony_civoid mls_semantic_cat_init(mls_semantic_cat_t * c) 7266cd6a6acSopenharmony_ci{ 7276cd6a6acSopenharmony_ci memset(c, 0, sizeof(mls_semantic_cat_t)); 7286cd6a6acSopenharmony_ci} 7296cd6a6acSopenharmony_ci 7306cd6a6acSopenharmony_civoid mls_semantic_cat_destroy(mls_semantic_cat_t * c __attribute__ ((unused))) 7316cd6a6acSopenharmony_ci{ 7326cd6a6acSopenharmony_ci /* it's currently a simple struct - really nothing to destroy */ 7336cd6a6acSopenharmony_ci return; 7346cd6a6acSopenharmony_ci} 7356cd6a6acSopenharmony_ci 7366cd6a6acSopenharmony_civoid mls_semantic_level_init(mls_semantic_level_t * l) 7376cd6a6acSopenharmony_ci{ 7386cd6a6acSopenharmony_ci memset(l, 0, sizeof(mls_semantic_level_t)); 7396cd6a6acSopenharmony_ci} 7406cd6a6acSopenharmony_ci 7416cd6a6acSopenharmony_civoid mls_semantic_level_destroy(mls_semantic_level_t * l) 7426cd6a6acSopenharmony_ci{ 7436cd6a6acSopenharmony_ci mls_semantic_cat_t *cur, *next; 7446cd6a6acSopenharmony_ci 7456cd6a6acSopenharmony_ci if (l == NULL) 7466cd6a6acSopenharmony_ci return; 7476cd6a6acSopenharmony_ci 7486cd6a6acSopenharmony_ci next = l->cat; 7496cd6a6acSopenharmony_ci while (next) { 7506cd6a6acSopenharmony_ci cur = next; 7516cd6a6acSopenharmony_ci next = cur->next; 7526cd6a6acSopenharmony_ci mls_semantic_cat_destroy(cur); 7536cd6a6acSopenharmony_ci free(cur); 7546cd6a6acSopenharmony_ci } 7556cd6a6acSopenharmony_ci} 7566cd6a6acSopenharmony_ci 7576cd6a6acSopenharmony_ciint mls_semantic_level_cpy(mls_semantic_level_t * dst, 7586cd6a6acSopenharmony_ci const mls_semantic_level_t * src) 7596cd6a6acSopenharmony_ci{ 7606cd6a6acSopenharmony_ci const mls_semantic_cat_t *cat; 7616cd6a6acSopenharmony_ci mls_semantic_cat_t *newcat, *lnewcat = NULL; 7626cd6a6acSopenharmony_ci 7636cd6a6acSopenharmony_ci mls_semantic_level_init(dst); 7646cd6a6acSopenharmony_ci dst->sens = src->sens; 7656cd6a6acSopenharmony_ci cat = src->cat; 7666cd6a6acSopenharmony_ci while (cat) { 7676cd6a6acSopenharmony_ci newcat = 7686cd6a6acSopenharmony_ci (mls_semantic_cat_t *) malloc(sizeof(mls_semantic_cat_t)); 7696cd6a6acSopenharmony_ci if (!newcat) 7706cd6a6acSopenharmony_ci goto err; 7716cd6a6acSopenharmony_ci 7726cd6a6acSopenharmony_ci mls_semantic_cat_init(newcat); 7736cd6a6acSopenharmony_ci if (lnewcat) 7746cd6a6acSopenharmony_ci lnewcat->next = newcat; 7756cd6a6acSopenharmony_ci else 7766cd6a6acSopenharmony_ci dst->cat = newcat; 7776cd6a6acSopenharmony_ci 7786cd6a6acSopenharmony_ci newcat->low = cat->low; 7796cd6a6acSopenharmony_ci newcat->high = cat->high; 7806cd6a6acSopenharmony_ci 7816cd6a6acSopenharmony_ci lnewcat = newcat; 7826cd6a6acSopenharmony_ci cat = cat->next; 7836cd6a6acSopenharmony_ci } 7846cd6a6acSopenharmony_ci return 0; 7856cd6a6acSopenharmony_ci 7866cd6a6acSopenharmony_ci err: 7876cd6a6acSopenharmony_ci mls_semantic_level_destroy(dst); 7886cd6a6acSopenharmony_ci return -1; 7896cd6a6acSopenharmony_ci} 7906cd6a6acSopenharmony_ci 7916cd6a6acSopenharmony_civoid mls_semantic_range_init(mls_semantic_range_t * r) 7926cd6a6acSopenharmony_ci{ 7936cd6a6acSopenharmony_ci mls_semantic_level_init(&r->level[0]); 7946cd6a6acSopenharmony_ci mls_semantic_level_init(&r->level[1]); 7956cd6a6acSopenharmony_ci} 7966cd6a6acSopenharmony_ci 7976cd6a6acSopenharmony_civoid mls_semantic_range_destroy(mls_semantic_range_t * r) 7986cd6a6acSopenharmony_ci{ 7996cd6a6acSopenharmony_ci mls_semantic_level_destroy(&r->level[0]); 8006cd6a6acSopenharmony_ci mls_semantic_level_destroy(&r->level[1]); 8016cd6a6acSopenharmony_ci} 8026cd6a6acSopenharmony_ci 8036cd6a6acSopenharmony_ciint mls_semantic_range_cpy(mls_semantic_range_t * dst, 8046cd6a6acSopenharmony_ci const mls_semantic_range_t * src) 8056cd6a6acSopenharmony_ci{ 8066cd6a6acSopenharmony_ci if (mls_semantic_level_cpy(&dst->level[0], &src->level[0]) < 0) 8076cd6a6acSopenharmony_ci return -1; 8086cd6a6acSopenharmony_ci 8096cd6a6acSopenharmony_ci if (mls_semantic_level_cpy(&dst->level[1], &src->level[1]) < 0) { 8106cd6a6acSopenharmony_ci mls_semantic_level_destroy(&dst->level[0]); 8116cd6a6acSopenharmony_ci return -1; 8126cd6a6acSopenharmony_ci } 8136cd6a6acSopenharmony_ci 8146cd6a6acSopenharmony_ci return 0; 8156cd6a6acSopenharmony_ci} 816