145916cd2Sjpk /* 245916cd2Sjpk * CDDL HEADER START 345916cd2Sjpk * 445916cd2Sjpk * The contents of this file are subject to the terms of the 545916cd2Sjpk * Common Development and Distribution License (the "License"). 645916cd2Sjpk * You may not use this file except in compliance with the License. 745916cd2Sjpk * 845916cd2Sjpk * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 945916cd2Sjpk * or http://www.opensolaris.org/os/licensing. 1045916cd2Sjpk * See the License for the specific language governing permissions 1145916cd2Sjpk * and limitations under the License. 1245916cd2Sjpk * 1345916cd2Sjpk * When distributing Covered Code, include this CDDL HEADER in each 1445916cd2Sjpk * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1545916cd2Sjpk * If applicable, add the following below this CDDL HEADER, with the 1645916cd2Sjpk * fields enclosed by brackets "[]" replaced with your own identifying 1745916cd2Sjpk * information: Portions Copyright [yyyy] [name of copyright owner] 1845916cd2Sjpk * 1945916cd2Sjpk * CDDL HEADER END 2045916cd2Sjpk */ 2145916cd2Sjpk /* 2245916cd2Sjpk * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 2345916cd2Sjpk * Use is subject to license terms. 2445916cd2Sjpk */ 2545916cd2Sjpk 2645916cd2Sjpk #pragma ident "%Z%%M% %I% %E% SMI" 2745916cd2Sjpk 2845916cd2Sjpk 2945916cd2Sjpk /* 3045916cd2Sjpk * Miscellaneous user interfaces to trusted label functions. 3145916cd2Sjpk * 3245916cd2Sjpk */ 3345916cd2Sjpk 3445916cd2Sjpk 3545916cd2Sjpk #include <ctype.h> 3645916cd2Sjpk #include <stdlib.h> 3745916cd2Sjpk #include <strings.h> 3845916cd2Sjpk 3945916cd2Sjpk #include <sys/mman.h> 4045916cd2Sjpk 4145916cd2Sjpk #include <tsol/label.h> 4245916cd2Sjpk 4345916cd2Sjpk #include "labeld.h" 4445916cd2Sjpk #include "clnt.h" 4545916cd2Sjpk #include <sys/tsol/label_macro.h> 4645916cd2Sjpk #include <secdb.h> 4745916cd2Sjpk #include <user_attr.h> 4845916cd2Sjpk 4945916cd2Sjpk static bslabel_t slow, shigh; /* static Admin Low and High SLs */ 5045916cd2Sjpk static bclear_t clow, chigh; /* static Admin Low and High CLRs */ 5145916cd2Sjpk 5245916cd2Sjpk static char color[MAXCOLOR]; 5345916cd2Sjpk 5445916cd2Sjpk 5545916cd2Sjpk #define incall callp->param.acall.cargs.inset_arg 5645916cd2Sjpk #define inret callp->param.aret.rvals.inset_ret 5745916cd2Sjpk /* 5845916cd2Sjpk * blinset - Check in a label set. 5945916cd2Sjpk * 6045916cd2Sjpk * Entry label = Sensitivity Label to check. 6145916cd2Sjpk * id = Label set identifier of set to check. 6245916cd2Sjpk * 6345916cd2Sjpk * Exit None. 6445916cd2Sjpk * 6545916cd2Sjpk * Returns -1, If label set unavailable, or server failure. 6645916cd2Sjpk * 0, If label not in label set. 6745916cd2Sjpk * 1, If label is in the label set. 6845916cd2Sjpk * 6945916cd2Sjpk * Calls __call_labeld(BLINSET), BLTYPE, BSLLOW, BSLHIGH. 7045916cd2Sjpk * 7145916cd2Sjpk * Uses slow, shigh. 7245916cd2Sjpk */ 7345916cd2Sjpk 7445916cd2Sjpk int 7545916cd2Sjpk blinset(const bslabel_t *label, const set_id *id) 7645916cd2Sjpk { 7745916cd2Sjpk if (id->type == SYSTEM_ACCREDITATION_RANGE) { 7845916cd2Sjpk if (!BLTYPE(&slow, SUN_SL_ID)) { 7945916cd2Sjpk /* initialize static labels. */ 8045916cd2Sjpk 8145916cd2Sjpk BSLLOW(&slow); 8245916cd2Sjpk BSLHIGH(&shigh); 8345916cd2Sjpk } 8445916cd2Sjpk 8545916cd2Sjpk if (BLTYPE(label, SUN_SL_ID) && 8645916cd2Sjpk (BLEQUAL(label, &slow) || BLEQUAL(label, &shigh))) 8745916cd2Sjpk 8845916cd2Sjpk return (1); 8945916cd2Sjpk } 9045916cd2Sjpk if (id->type == USER_ACCREDITATION_RANGE || 9145916cd2Sjpk id->type == SYSTEM_ACCREDITATION_RANGE) { 9245916cd2Sjpk labeld_data_t call; 9345916cd2Sjpk labeld_data_t *callp = &call; 9445916cd2Sjpk size_t bufsize = sizeof (labeld_data_t); 9545916cd2Sjpk size_t datasize = CALL_SIZE(inset_call_t, 0); 9645916cd2Sjpk 9745916cd2Sjpk call.callop = BLINSET; 9845916cd2Sjpk incall.label = *label; 9945916cd2Sjpk incall.type = id->type; 10045916cd2Sjpk 10145916cd2Sjpk if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) { 10245916cd2Sjpk /* process error */ 10345916cd2Sjpk 10445916cd2Sjpk return (-1); 10545916cd2Sjpk } 10645916cd2Sjpk return (inret.inset); 10745916cd2Sjpk } else { 10845916cd2Sjpk /* 10945916cd2Sjpk * Only System and User Accreditation Ranges presently 11045916cd2Sjpk * implemented. 11145916cd2Sjpk */ 11245916cd2Sjpk return (-1); 11345916cd2Sjpk } 11445916cd2Sjpk } 11545916cd2Sjpk #undef incall 11645916cd2Sjpk #undef inret 11745916cd2Sjpk 11845916cd2Sjpk #define slvcall callp->param.acall.cargs.slvalid_arg 11945916cd2Sjpk #define slvret callp->param.aret.rvals.slvalid_ret 12045916cd2Sjpk /* 12145916cd2Sjpk * bslvalid - Check Sensitivity Label for validity. 12245916cd2Sjpk * 12345916cd2Sjpk * Entry label = Sensitivity Label to check. 12445916cd2Sjpk * 12545916cd2Sjpk * Exit None. 12645916cd2Sjpk * 12745916cd2Sjpk * Returns -1, If unable to access label encodings file, or server failure. 12845916cd2Sjpk * 0, If label not valid. 12945916cd2Sjpk * 1, If label is valid. 13045916cd2Sjpk * 13145916cd2Sjpk * Calls __call_labeld(BSLVALID), BLTYPE, BSLLOW, BSLHIGH. 13245916cd2Sjpk * 13345916cd2Sjpk * Uses slow, shigh. 13445916cd2Sjpk * 13545916cd2Sjpk */ 13645916cd2Sjpk 13745916cd2Sjpk int 13845916cd2Sjpk bslvalid(const bslabel_t *label) 13945916cd2Sjpk { 14045916cd2Sjpk labeld_data_t call; 14145916cd2Sjpk labeld_data_t *callp = &call; 14245916cd2Sjpk size_t bufsize = sizeof (labeld_data_t); 14345916cd2Sjpk size_t datasize = CALL_SIZE(slvalid_call_t, 0); 14445916cd2Sjpk 14545916cd2Sjpk if (!BLTYPE(&slow, SUN_SL_ID)) { 14645916cd2Sjpk /* initialize static labels. */ 14745916cd2Sjpk 14845916cd2Sjpk BSLLOW(&slow); 14945916cd2Sjpk BSLHIGH(&shigh); 15045916cd2Sjpk } 15145916cd2Sjpk 15245916cd2Sjpk if (BLTYPE(label, SUN_SL_ID) && 15345916cd2Sjpk (BLEQUAL(label, &slow) || BLEQUAL(label, &shigh))) { 15445916cd2Sjpk 15545916cd2Sjpk return (1); 15645916cd2Sjpk } 15745916cd2Sjpk 15845916cd2Sjpk call.callop = BSLVALID; 15945916cd2Sjpk slvcall.label = *label; 16045916cd2Sjpk 16145916cd2Sjpk if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) { 16245916cd2Sjpk /* process error */ 16345916cd2Sjpk 16445916cd2Sjpk return (-1); 16545916cd2Sjpk } 16645916cd2Sjpk return (slvret.valid); 16745916cd2Sjpk } 16845916cd2Sjpk #undef slvcall 16945916cd2Sjpk #undef slvret 17045916cd2Sjpk 17145916cd2Sjpk #define clrvcall callp->param.acall.cargs.clrvalid_arg 17245916cd2Sjpk #define clrvret callp->param.aret.rvals.clrvalid_ret 17345916cd2Sjpk /* 17445916cd2Sjpk * bclearvalid - Check Clearance for validity. 17545916cd2Sjpk * 17645916cd2Sjpk * Entry clearance = Clearance to check. 17745916cd2Sjpk * 17845916cd2Sjpk * Exit None. 17945916cd2Sjpk * 18045916cd2Sjpk * Returns -1, If unable to access label encodings file, or server failure. 18145916cd2Sjpk * 0, If label not valid. 18245916cd2Sjpk * 1, If label is valid. 18345916cd2Sjpk * 18445916cd2Sjpk * Calls __call_labeld(BCLEARVALID), BLTYPE, BCLEARLOW, BCLEARHIGH. 18545916cd2Sjpk * 18645916cd2Sjpk * Uses clow, chigh. 18745916cd2Sjpk * 18845916cd2Sjpk */ 18945916cd2Sjpk 19045916cd2Sjpk int 19145916cd2Sjpk bclearvalid(const bclear_t *clearance) 19245916cd2Sjpk { 19345916cd2Sjpk labeld_data_t call; 19445916cd2Sjpk labeld_data_t *callp = &call; 19545916cd2Sjpk size_t bufsize = sizeof (labeld_data_t); 19645916cd2Sjpk size_t datasize = CALL_SIZE(clrvalid_call_t, 0); 19745916cd2Sjpk 19845916cd2Sjpk if (!BLTYPE(&clow, SUN_CLR_ID)) { 19945916cd2Sjpk /* initialize static labels. */ 20045916cd2Sjpk 20145916cd2Sjpk BCLEARLOW(&clow); 20245916cd2Sjpk BCLEARHIGH(&chigh); 20345916cd2Sjpk } 20445916cd2Sjpk 20545916cd2Sjpk if (BLTYPE(clearance, SUN_CLR_ID) && 20645916cd2Sjpk (BLEQUAL(clearance, &clow) || BLEQUAL(clearance, &chigh))) { 20745916cd2Sjpk 20845916cd2Sjpk return (1); 20945916cd2Sjpk } 21045916cd2Sjpk 21145916cd2Sjpk call.callop = BCLEARVALID; 21245916cd2Sjpk clrvcall.clear = *clearance; 21345916cd2Sjpk 21445916cd2Sjpk if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) { 21545916cd2Sjpk /* process error */ 21645916cd2Sjpk 21745916cd2Sjpk return (-1); 21845916cd2Sjpk } 21945916cd2Sjpk return (clrvret.valid); 22045916cd2Sjpk } 22145916cd2Sjpk #undef clrvcall 22245916cd2Sjpk #undef clrvret 22345916cd2Sjpk 22445916cd2Sjpk #define inforet callp->param.aret.rvals.info_ret 22545916cd2Sjpk /* 22645916cd2Sjpk * labelinfo - Get information about the label encodings file. 22745916cd2Sjpk * 22845916cd2Sjpk * Entry info = Address of label_info structure to update. 22945916cd2Sjpk * 23045916cd2Sjpk * Exit info = Updated. 23145916cd2Sjpk * 23245916cd2Sjpk * Returns -1, If unable to access label encodings file, or server failure. 23345916cd2Sjpk * 1, If successful. 23445916cd2Sjpk * 23545916cd2Sjpk * Calls __call_labeld(LABELINFO). 23645916cd2Sjpk */ 23745916cd2Sjpk 23845916cd2Sjpk int 23945916cd2Sjpk labelinfo(struct label_info *info) 24045916cd2Sjpk { 24145916cd2Sjpk labeld_data_t call; 24245916cd2Sjpk labeld_data_t *callp = &call; 24345916cd2Sjpk size_t bufsize = sizeof (labeld_data_t); 24445916cd2Sjpk size_t datasize = CALL_SIZE(info_call_t, 0); 24545916cd2Sjpk int rval; 24645916cd2Sjpk 24745916cd2Sjpk call.callop = LABELINFO; 24845916cd2Sjpk 24945916cd2Sjpk if ((rval = __call_labeld(&callp, &bufsize, &datasize)) != SUCCESS) { 25045916cd2Sjpk /* process error */ 25145916cd2Sjpk 25245916cd2Sjpk return (-1); 25345916cd2Sjpk } 25445916cd2Sjpk *info = inforet.info; 25545916cd2Sjpk return (rval); 25645916cd2Sjpk } 25745916cd2Sjpk #undef inforet 25845916cd2Sjpk 25945916cd2Sjpk #define lvret callp->param.aret.rvals.vers_ret 26045916cd2Sjpk /* 26145916cd2Sjpk * labelvers - Get version string of the label encodings file. 26245916cd2Sjpk * 26345916cd2Sjpk * Entry version = Address of string pointer to return. 26445916cd2Sjpk * len = Length of string if pre-allocated. 26545916cd2Sjpk * 26645916cd2Sjpk * Exit version = Updated. 26745916cd2Sjpk * 26845916cd2Sjpk * Returns -1, If unable to access label encodings file, or server failure. 26945916cd2Sjpk * 0, If unable to allocate version string, 27045916cd2Sjpk * or pre-allocated version string to short 27145916cd2Sjpk * (and **version = '\0'). 27245916cd2Sjpk * length (including null) of version string, If successful. 27345916cd2Sjpk * 27445916cd2Sjpk * Calls __call_labeld(LABELVERS) 27545916cd2Sjpk * malloc, strlen. 27645916cd2Sjpk */ 27745916cd2Sjpk 27845916cd2Sjpk ssize_t 27945916cd2Sjpk labelvers(char **version, size_t len) 28045916cd2Sjpk { 28145916cd2Sjpk labeld_data_t call; 28245916cd2Sjpk labeld_data_t *callp = &call; 28345916cd2Sjpk size_t bufsize = sizeof (labeld_data_t); 28445916cd2Sjpk size_t datasize = CALL_SIZE(vers_call_t, 0); 28545916cd2Sjpk size_t ver_len; 28645916cd2Sjpk 28745916cd2Sjpk call.callop = LABELVERS; 28845916cd2Sjpk 28945916cd2Sjpk if (__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) { 29045916cd2Sjpk 29145916cd2Sjpk if (callp != &call) 29245916cd2Sjpk /* release return buffer */ 29345916cd2Sjpk (void) munmap((void *)callp, bufsize); 29445916cd2Sjpk return (-1); 29545916cd2Sjpk } 29645916cd2Sjpk 29745916cd2Sjpk /* unpack length */ 29845916cd2Sjpk 29945916cd2Sjpk ver_len = strlen(lvret.vers) + 1; 30045916cd2Sjpk if (*version == NULL) { 30145916cd2Sjpk if ((*version = malloc(ver_len)) == NULL) { 30245916cd2Sjpk if (callp != &call) 30345916cd2Sjpk /* release return buffer */ 30445916cd2Sjpk (void) munmap((void *)callp, bufsize); 30545916cd2Sjpk return (0); 30645916cd2Sjpk } 30745916cd2Sjpk } else if (ver_len > len) { 30845916cd2Sjpk **version = '\0'; 30945916cd2Sjpk if (callp != &call) 31045916cd2Sjpk /* release return buffer */ 31145916cd2Sjpk (void) munmap((void *)callp, bufsize); 31245916cd2Sjpk return (0); 31345916cd2Sjpk } 31445916cd2Sjpk (void) strcpy(*version, lvret.vers); 31545916cd2Sjpk 31645916cd2Sjpk if (callp != &call) 31745916cd2Sjpk /* release return buffer */ 31845916cd2Sjpk (void) munmap((void *)callp, bufsize); 31945916cd2Sjpk return (ver_len); 32045916cd2Sjpk } /* labelvers */ 32145916cd2Sjpk #undef lvret 32245916cd2Sjpk 32345916cd2Sjpk #define ccall callp->param.acall.cargs.color_arg 32445916cd2Sjpk #define cret callp->param.aret.rvals.color_ret 32545916cd2Sjpk /* 32645916cd2Sjpk * bltocolor - get ASCII color name of label. 32745916cd2Sjpk * 32845916cd2Sjpk * Entry label = Sensitivity Level of color to get. 32945916cd2Sjpk * size = Size of the color_name array. 33045916cd2Sjpk * color_name = Storage for ASCII color name string to be returned. 33145916cd2Sjpk * 33245916cd2Sjpk * Exit None. 33345916cd2Sjpk * 33445916cd2Sjpk * Returns NULL, If error (label encodings file not accessible, 33545916cd2Sjpk * invalid label, no color for this label). 33645916cd2Sjpk * Address of color_name parameter containing ASCII color name 33745916cd2Sjpk * defined for the label. 33845916cd2Sjpk * 33945916cd2Sjpk * Calls __call_labeld(BLTOCOLOR), strlen. 34045916cd2Sjpk */ 34145916cd2Sjpk 34245916cd2Sjpk char * 34345916cd2Sjpk bltocolor_r(const blevel_t *label, size_t size, char *color_name) 34445916cd2Sjpk { 34545916cd2Sjpk labeld_data_t call; 34645916cd2Sjpk labeld_data_t *callp = &call; 34745916cd2Sjpk size_t bufsize = sizeof (labeld_data_t); 34845916cd2Sjpk size_t datasize = CALL_SIZE(color_call_t, 0); 34945916cd2Sjpk char *colorp; 35045916cd2Sjpk 35145916cd2Sjpk call.callop = BLTOCOLOR; 35245916cd2Sjpk ccall.label = *label; 35345916cd2Sjpk 35445916cd2Sjpk if ((__call_labeld(&callp, &bufsize, &datasize) != SUCCESS) || 35545916cd2Sjpk (callp->reterr != 0) || 35645916cd2Sjpk (strlen(cret.color) >= size)) { 35745916cd2Sjpk 35845916cd2Sjpk if (callp != &call) 35945916cd2Sjpk /* release return buffer */ 36045916cd2Sjpk (void) munmap((void *)callp, bufsize); 36145916cd2Sjpk return (NULL); 36245916cd2Sjpk } 36345916cd2Sjpk 36445916cd2Sjpk colorp = strcpy(color_name, cret.color); 36545916cd2Sjpk 36645916cd2Sjpk if (callp != &call) 36745916cd2Sjpk /* release return buffer */ 36845916cd2Sjpk (void) munmap((void *)callp, bufsize); 36945916cd2Sjpk return (colorp); 37045916cd2Sjpk } /* bltocolor_r */ 37145916cd2Sjpk #undef ccall 37245916cd2Sjpk #undef cret 37345916cd2Sjpk 37445916cd2Sjpk /* 37545916cd2Sjpk * bltocolor - get ASCII color name of label. 37645916cd2Sjpk * 37745916cd2Sjpk * Entry label = Sensitivity Level of color to get. 37845916cd2Sjpk * 37945916cd2Sjpk * Exit None. 38045916cd2Sjpk * 38145916cd2Sjpk * Returns NULL, If error (label encodings file not accessible, 38245916cd2Sjpk * invalid label, no color for this label). 38345916cd2Sjpk * Address of statically allocated string containing ASCII 38445916cd2Sjpk * color name defined for the classification contained 38545916cd2Sjpk * in label. 38645916cd2Sjpk * 38745916cd2Sjpk * Uses color. 38845916cd2Sjpk * 38945916cd2Sjpk * Calls bltocolor_r. 39045916cd2Sjpk */ 39145916cd2Sjpk 39245916cd2Sjpk char * 39345916cd2Sjpk bltocolor(const blevel_t *label) 39445916cd2Sjpk { 39545916cd2Sjpk return (bltocolor_r(label, sizeof (color), color)); 39645916cd2Sjpk } /* bltocolor */ 39745916cd2Sjpk 39845916cd2Sjpk blevel_t * 39945916cd2Sjpk blabel_alloc(void) 40045916cd2Sjpk { 40145916cd2Sjpk return (m_label_alloc(MAC_LABEL)); 40245916cd2Sjpk } 40345916cd2Sjpk 40445916cd2Sjpk void 40545916cd2Sjpk blabel_free(blevel_t *label_p) 40645916cd2Sjpk { 40745916cd2Sjpk free(label_p); 40845916cd2Sjpk } 40945916cd2Sjpk 41045916cd2Sjpk size_t 41145916cd2Sjpk blabel_size(void) 41245916cd2Sjpk { 41345916cd2Sjpk return (sizeof (blevel_t)); 41445916cd2Sjpk } 41545916cd2Sjpk 41645916cd2Sjpk /* 41745916cd2Sjpk * getuserrange - get label range for user 41845916cd2Sjpk * 41945916cd2Sjpk * Entry username of user 42045916cd2Sjpk * 42145916cd2Sjpk * Exit None. 42245916cd2Sjpk * 42345916cd2Sjpk * Returns NULL, If memory allocation failure or userdefs failure. 42445916cd2Sjpk * otherwise returns the allocates m_range_t with the 42545916cd2Sjpk * user's min and max labels set. 42645916cd2Sjpk */ 42745916cd2Sjpk 42845916cd2Sjpk m_range_t * 42945916cd2Sjpk getuserrange(const char *username) 43045916cd2Sjpk { 43145916cd2Sjpk char *kv_str = NULL; 43245916cd2Sjpk userattr_t *userp = NULL; 43345916cd2Sjpk m_range_t *range; 434*aa2e15f6Srica m_label_t *def_min, *def_clr; 43545916cd2Sjpk 43645916cd2Sjpk /* 43745916cd2Sjpk * Get some memory 43845916cd2Sjpk */ 43945916cd2Sjpk 44045916cd2Sjpk if ((range = malloc(sizeof (m_range_t))) == NULL) { 44145916cd2Sjpk return (NULL); 44245916cd2Sjpk } 44345916cd2Sjpk if ((range->lower_bound = m_label_alloc(MAC_LABEL)) == NULL) { 44445916cd2Sjpk free(range); 44545916cd2Sjpk return (NULL); 44645916cd2Sjpk } 447*aa2e15f6Srica def_min = range->lower_bound; 44845916cd2Sjpk if ((range->upper_bound = m_label_alloc(USER_CLEAR)) == NULL) { 44945916cd2Sjpk m_label_free(range->lower_bound); 45045916cd2Sjpk free(range); 45145916cd2Sjpk return (NULL); 45245916cd2Sjpk } 453*aa2e15f6Srica def_clr = range->upper_bound; 454*aa2e15f6Srica 455*aa2e15f6Srica /* If the user has an explicit min_label or clearance, use it. */ 456*aa2e15f6Srica if ((userp = getusernam(username)) != NULL) { 457*aa2e15f6Srica if ((kv_str = kva_match(userp->attr, USERATTR_MINLABEL)) 458*aa2e15f6Srica != NULL) { 459*aa2e15f6Srica (void) str_to_label(kv_str, &range->lower_bound, 460*aa2e15f6Srica MAC_LABEL, L_NO_CORRECTION, NULL); 461*aa2e15f6Srica def_min = NULL; /* don't get default later */ 462*aa2e15f6Srica } 463*aa2e15f6Srica if ((kv_str = kva_match(userp->attr, USERATTR_CLEARANCE)) 464*aa2e15f6Srica != NULL) { 465*aa2e15f6Srica (void) str_to_label(kv_str, &range->upper_bound, 466*aa2e15f6Srica USER_CLEAR, L_NO_CORRECTION, NULL); 467*aa2e15f6Srica def_clr = NULL; /* don't get default later */ 468*aa2e15f6Srica } 469*aa2e15f6Srica free_userattr(userp); 470*aa2e15f6Srica } 471*aa2e15f6Srica if (def_min || def_clr) { 472*aa2e15f6Srica /* Need to use system default clearance and/or min_label */ 473*aa2e15f6Srica if ((userdefs(def_min, def_clr)) == -1) { 47445916cd2Sjpk m_label_free(range->lower_bound); 47545916cd2Sjpk m_label_free(range->upper_bound); 47645916cd2Sjpk free(range); 47745916cd2Sjpk return (NULL); 47845916cd2Sjpk } 47945916cd2Sjpk } 480*aa2e15f6Srica 48145916cd2Sjpk return (range); 48245916cd2Sjpk } 483