iterator.c

Go to the documentation of this file.
00001 /**
00002  * @file
00003  * Contains the implementation of the qpol_iterator API, both
00004  * public and private, for returning lists of components and rules
00005  * from the policy database.
00006  *
00007  * @author Kevin Carr kcarr@tresys.com
00008  * @author Jeremy A. Mowery jmowery@tresys.com
00009  * @author Jason Tang jtang@tresys.com
00010  *
00011  * Copyright (C) 2006-2008 Tresys Technology, LLC
00012  *
00013  *  This library is free software; you can redistribute it and/or
00014  *  modify it under the terms of the GNU Lesser General Public
00015  *  License as published by the Free Software Foundation; either
00016  *  version 2.1 of the License, or (at your option) any later version.
00017  *
00018  *  This library is distributed in the hope that it will be useful,
00019  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00021  *  Lesser General Public License for more details.
00022  *
00023  *  You should have received a copy of the GNU Lesser General Public
00024  *  License along with this library; if not, write to the Free Software
00025  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00026  */
00027 
00028 #include <config.h>
00029 
00030 #include <qpol/iterator.h>
00031 #include <qpol/policy.h>
00032 #include <qpol/mls_query.h>
00033 
00034 #include <stdlib.h>
00035 #include <errno.h>
00036 #include <string.h>
00037 
00038 #include <sepol/policydb/policydb.h>
00039 #include <sepol/policydb/util.h>
00040 #include <sepol/policydb.h>
00041 
00042 #include "qpol_internal.h"
00043 #include "iterator_internal.h"
00044 
00045 /**
00046  * Declaration of qpol_iterator, an arbitrary valued policy component
00047  * iterator used to return lists of components.
00048  *
00049  */
00050 struct qpol_iterator
00051 {
00052         policydb_t *policy;
00053         void *state;
00054         void *(*get_cur) (const qpol_iterator_t * iter);
00055         int (*next) (qpol_iterator_t * iter);
00056         int (*end) (const qpol_iterator_t * iter);
00057          size_t(*size) (const qpol_iterator_t * iter);
00058         void (*free_fn) (void *x);
00059 };
00060 
00061 /**
00062  * The number of buckets in sepol's av tables was statically set in
00063  * libsepol < 2.0.20.  With libsepol 2.0.20, this size was dynamically
00064  * calculated based upon the number of rules.
00065  */
00066 static uint32_t iterator_get_avtab_size(const avtab_t * avtab)
00067 {
00068 #ifdef SEPOL_DYNAMIC_AVTAB
00069         return avtab->nslot;
00070 #else
00071         return AVTAB_SIZE;
00072 #endif
00073 }
00074 
00075 int qpol_iterator_create(const qpol_policy_t * policy, void *state,
00076                          void *(*get_cur) (const qpol_iterator_t * iter),
00077                          int (*next) (qpol_iterator_t * iter),
00078                          int (*end) (const qpol_iterator_t * iter),
00079                          size_t(*size) (const qpol_iterator_t * iter), void (*free_fn) (void *x), qpol_iterator_t ** iter)
00080 {
00081         int error = 0;
00082 
00083         if (iter != NULL)
00084                 *iter = NULL;
00085 
00086         if (policy == NULL || state == NULL || iter == NULL || get_cur == NULL || next == NULL || end == NULL || size == NULL) {
00087                 ERR(policy, "%s", strerror(EINVAL));
00088                 errno = EINVAL;
00089                 return STATUS_ERR;
00090         }
00091 
00092         *iter = calloc(1, sizeof(struct qpol_iterator));
00093         if (*iter == NULL) {
00094                 error = errno;
00095                 ERR(policy, "%s", strerror(ENOMEM));
00096                 errno = error;
00097                 return STATUS_ERR;
00098         }
00099 
00100         (*iter)->policy = &policy->p->p;
00101         (*iter)->state = state;
00102         (*iter)->get_cur = get_cur;
00103         (*iter)->next = next;
00104         (*iter)->end = end;
00105         (*iter)->size = size;
00106         (*iter)->free_fn = free_fn;
00107 
00108         return STATUS_SUCCESS;
00109 }
00110 
00111 void *qpol_iterator_state(const qpol_iterator_t * iter)
00112 {
00113         if (iter == NULL || iter->state == NULL) {
00114                 errno = EINVAL;
00115                 return NULL;
00116         }
00117 
00118         return iter->state;
00119 }
00120 
00121 const policydb_t *qpol_iterator_policy(const qpol_iterator_t * iter)
00122 {
00123         if (iter == NULL || iter->policy == NULL) {
00124                 errno = EINVAL;
00125                 return NULL;
00126         }
00127 
00128         return iter->policy;
00129 }
00130 
00131 void *hash_state_get_cur(const qpol_iterator_t * iter)
00132 {
00133         hash_state_t *hs = NULL;
00134 
00135         if (iter == NULL || iter->state == NULL || hash_state_end(iter)) {
00136                 errno = EINVAL;
00137                 return NULL;
00138         }
00139 
00140         hs = (hash_state_t *) iter->state;
00141 
00142         return hs->node->datum;
00143 }
00144 
00145 void *hash_state_get_cur_key(const qpol_iterator_t * iter)
00146 {
00147         hash_state_t *hs = NULL;
00148 
00149         if (iter == NULL || iter->state == NULL || hash_state_end(iter)) {
00150                 errno = EINVAL;
00151                 return NULL;
00152         }
00153 
00154         hs = (hash_state_t *) iter->state;
00155 
00156         return hs->node->key;
00157 }
00158 
00159 void *ocon_state_get_cur(const qpol_iterator_t * iter)
00160 {
00161         ocon_state_t *os = NULL;
00162 
00163         if (iter == NULL || iter->state == NULL || ocon_state_end(iter)) {
00164                 errno = EINVAL;
00165                 return NULL;
00166         }
00167 
00168         os = (ocon_state_t *) iter->state;
00169 
00170         return os->cur;
00171 }
00172 
00173 void *avtab_state_get_cur(const qpol_iterator_t * iter)
00174 {
00175         avtab_state_t *state;
00176 
00177         if (iter == NULL || iter->state == NULL || avtab_state_end(iter)) {
00178                 errno = EINVAL;
00179                 return NULL;
00180         }
00181         state = (avtab_state_t *) iter->state;
00182         return state->node;
00183 }
00184 
00185 int hash_state_next(qpol_iterator_t * iter)
00186 {
00187         hash_state_t *hs = NULL;
00188 
00189         if (iter == NULL || iter->state == NULL) {
00190                 errno = EINVAL;
00191                 return STATUS_ERR;
00192         }
00193 
00194         hs = (hash_state_t *) iter->state;
00195 
00196         if (hs->table == NULL || *(hs->table) == NULL || hs->bucket >= (*(hs->table))->size) {
00197                 errno = ERANGE;
00198                 return STATUS_ERR;
00199         }
00200 
00201         if (hs->node != NULL && hs->node->next != NULL) {
00202                 hs->node = hs->node->next;
00203         } else {
00204                 do {
00205                         hs->bucket++;
00206                         if (hs->bucket < (*(hs->table))->size) {
00207                                 hs->node = (*(hs->table))->htable[hs->bucket];
00208                         } else {
00209                                 hs->node = NULL;
00210                         }
00211                 } while (hs->bucket < (*(hs->table))->size && hs->node == NULL);
00212         }
00213 
00214         return STATUS_SUCCESS;
00215 }
00216 
00217 int ebitmap_state_next(qpol_iterator_t * iter)
00218 {
00219         ebitmap_state_t *es = NULL;
00220 
00221         if (iter == NULL || iter->state == NULL) {
00222                 errno = EINVAL;
00223                 return STATUS_ERR;
00224         }
00225 
00226         es = (ebitmap_state_t *) iter->state;
00227 
00228         if (es->cur >= es->bmap->highbit) {
00229                 errno = ERANGE;
00230                 return STATUS_ERR;
00231         }
00232 
00233         do {
00234                 es->cur++;
00235         } while (es->cur < es->bmap->highbit && !ebitmap_get_bit(es->bmap, es->cur));
00236 
00237         return STATUS_SUCCESS;
00238 }
00239 
00240 int ocon_state_next(qpol_iterator_t * iter)
00241 {
00242         ocon_state_t *os = NULL;
00243 
00244         if (iter == NULL || iter->state == NULL) {
00245                 errno = EINVAL;
00246                 return STATUS_ERR;
00247         }
00248 
00249         os = (ocon_state_t *) iter->state;
00250 
00251         if (os->cur == NULL) {
00252                 errno = ERANGE;
00253                 return STATUS_ERR;
00254         }
00255 
00256         os->cur = os->cur->next;
00257 
00258         return STATUS_SUCCESS;
00259 }
00260 
00261 int avtab_state_next(qpol_iterator_t * iter)
00262 {
00263         avtab_t *avtab;
00264         avtab_state_t *state;
00265 
00266         if (iter == NULL || iter->state == NULL) {
00267                 errno = EINVAL;
00268                 return STATUS_ERR;
00269         }
00270 
00271         state = iter->state;
00272         avtab = (state->which == QPOL_AVTAB_STATE_AV ? state->ucond_tab : state->cond_tab);
00273 
00274         if ((!avtab->htable || state->bucket >= iterator_get_avtab_size(avtab)) && state->which == QPOL_AVTAB_STATE_COND) {
00275                 errno = ERANGE;
00276                 return STATUS_ERR;
00277         }
00278 
00279         do {
00280                 if (state->node != NULL && state->node->next != NULL) {
00281                         state->node = state->node->next;
00282                 } else {
00283                         /* find the next bucket */
00284                         do {
00285                                 state->bucket++;
00286                                 if (!avtab->htable || state->bucket >= iterator_get_avtab_size(avtab)) {
00287                                         if (state->which == QPOL_AVTAB_STATE_AV) {
00288                                                 state->bucket = 0;
00289                                                 avtab = state->cond_tab;
00290                                                 state->which = QPOL_AVTAB_STATE_COND;
00291                                         } else {
00292                                                 state->node = NULL;
00293                                                 break;
00294                                         }
00295                                 }
00296                                 if (avtab->htable && avtab->htable[state->bucket] != NULL) {
00297                                         state->node = avtab->htable[state->bucket];
00298                                         break;
00299                                 }
00300                         } while (avtab->htable && state->bucket < iterator_get_avtab_size(avtab));
00301                 }
00302         } while (avtab->htable && state->bucket < iterator_get_avtab_size(avtab) &&
00303                  state->node ? !(state->rule_type_mask & state->node->key.specified) : 0);
00304 
00305         return STATUS_SUCCESS;
00306 }
00307 
00308 int hash_state_end(const qpol_iterator_t * iter)
00309 {
00310         hash_state_t *hs = NULL;
00311 
00312         if (iter == NULL || iter->state == NULL) {
00313                 errno = EINVAL;
00314                 return STATUS_ERR;
00315         }
00316 
00317         hs = (hash_state_t *) iter->state;
00318 
00319         if (hs->table == NULL || *(hs->table) == NULL || (*(hs->table))->nel == 0 || hs->bucket >= (*(hs->table))->size)
00320                 return 1;
00321 
00322         return 0;
00323 }
00324 
00325 int ebitmap_state_end(const qpol_iterator_t * iter)
00326 {
00327         ebitmap_state_t *es = NULL;
00328 
00329         if (iter == NULL || iter->state == NULL) {
00330                 errno = EINVAL;
00331                 return STATUS_ERR;
00332         }
00333 
00334         es = (ebitmap_state_t *) iter->state;
00335 
00336         if (es->cur >= es->bmap->highbit)
00337                 return 1;
00338 
00339         return 0;
00340 }
00341 
00342 int ocon_state_end(const qpol_iterator_t * iter)
00343 {
00344         ocon_state_t *os = NULL;
00345 
00346         if (iter == NULL || iter->state == NULL) {
00347                 errno = EINVAL;
00348                 return STATUS_ERR;
00349         }
00350 
00351         os = (ocon_state_t *) iter->state;
00352 
00353         if (os->cur == NULL)
00354                 return 1;
00355 
00356         return 0;
00357 }
00358 
00359 int avtab_state_end(const qpol_iterator_t * iter)
00360 {
00361         avtab_state_t *state;
00362         avtab_t *avtab;
00363 
00364         if (iter == NULL || iter->state == NULL) {
00365                 errno = EINVAL;
00366                 return STATUS_ERR;
00367         }
00368         state = iter->state;
00369         avtab = (state->which == QPOL_AVTAB_STATE_AV ? state->ucond_tab : state->cond_tab);
00370         if ((!avtab->htable || state->bucket >= iterator_get_avtab_size(avtab)) && state->which == QPOL_AVTAB_STATE_COND)
00371                 return 1;
00372         return 0;
00373 }
00374 
00375 size_t hash_state_size(const qpol_iterator_t * iter)
00376 {
00377         hash_state_t *hs = NULL;
00378 
00379         if (iter == NULL || iter->state == NULL) {
00380                 errno = EINVAL;
00381                 return 0;
00382         }
00383 
00384         hs = (hash_state_t *) iter->state;
00385 
00386         return (*(hs->table))->nel;
00387 }
00388 
00389 size_t ebitmap_state_size(const qpol_iterator_t * iter)
00390 {
00391         ebitmap_state_t *es = NULL;
00392         size_t count = 0, bit = 0;
00393         ebitmap_node_t *node = NULL;
00394 
00395         if (iter == NULL || iter->state == NULL) {
00396                 errno = EINVAL;
00397                 return 0;
00398         }
00399 
00400         es = (ebitmap_state_t *) iter->state;
00401 
00402         ebitmap_for_each_bit(es->bmap, node, bit) {
00403                 count += ebitmap_get_bit(es->bmap, bit);
00404         }
00405 
00406         return count;
00407 }
00408 
00409 size_t ocon_state_size(const qpol_iterator_t * iter)
00410 {
00411         ocon_state_t *os = NULL;
00412         size_t count = 0;
00413         ocontext_t *ocon = NULL;
00414 
00415         if (iter == NULL || iter->state == NULL) {
00416                 errno = EINVAL;
00417                 return 0;
00418         }
00419 
00420         os = (ocon_state_t *) iter->state;
00421 
00422         for (ocon = os->head; ocon; ocon = ocon->next)
00423                 count++;
00424 
00425         return count;
00426 }
00427 
00428 size_t avtab_state_size(const qpol_iterator_t * iter)
00429 {
00430         avtab_state_t *state;
00431         avtab_t *avtab;
00432         size_t count = 0;
00433         avtab_ptr_t node = NULL;
00434         uint32_t bucket = 0;
00435 
00436         if (iter == NULL || iter->state == NULL || iter->policy == NULL) {
00437                 errno = EINVAL;
00438                 return STATUS_ERR;
00439         }
00440 
00441         state = iter->state;
00442         avtab = state->ucond_tab;
00443 
00444         for (bucket = 0; avtab->htable && bucket < iterator_get_avtab_size(avtab); bucket++) {
00445                 for (node = avtab->htable[bucket]; node; node = node->next) {
00446                         if (node->key.specified & state->rule_type_mask)
00447                                 count++;
00448                 }
00449         }
00450 
00451         avtab = state->cond_tab;
00452 
00453         for (bucket = 0; avtab->htable && bucket < iterator_get_avtab_size(avtab); bucket++) {
00454                 for (node = avtab->htable[bucket]; node; node = node->next) {
00455                         if (node->key.specified & state->rule_type_mask)
00456                                 count++;
00457                 }
00458         }
00459 
00460         return count;
00461 }
00462 
00463 void qpol_iterator_destroy(qpol_iterator_t ** iter)
00464 {
00465         if (iter == NULL || *iter == NULL)
00466                 return;
00467 
00468         if ((*iter)->free_fn)
00469                 (*iter)->free_fn((*iter)->state);
00470 
00471         free(*iter);
00472         *iter = NULL;
00473 }
00474 
00475 int qpol_iterator_get_item(const qpol_iterator_t * iter, void **item)
00476 {
00477         if (item != NULL)
00478                 *item = NULL;
00479 
00480         if (iter == NULL || iter->get_cur == NULL || item == NULL) {
00481                 errno = EINVAL;
00482                 return STATUS_ERR;
00483         }
00484 
00485         *item = iter->get_cur(iter);
00486         if (*item == NULL)
00487                 return STATUS_ERR;
00488 
00489         return STATUS_SUCCESS;
00490 }
00491 
00492 int qpol_iterator_next(qpol_iterator_t * iter)
00493 {
00494         if (iter == NULL || iter->next == NULL) {
00495                 errno = EINVAL;
00496                 return STATUS_ERR;
00497         }
00498 
00499         return iter->next(iter);
00500 }
00501 
00502 int qpol_iterator_end(const qpol_iterator_t * iter)
00503 {
00504         if (iter == NULL || iter->end == NULL) {
00505                 errno = EINVAL;
00506                 return STATUS_ERR;
00507         }
00508 
00509         return iter->end(iter);
00510 }
00511 
00512 int qpol_iterator_get_size(const qpol_iterator_t * iter, size_t * size)
00513 {
00514         if (size != NULL)
00515                 *size = 0;
00516 
00517         if (iter == NULL || size == NULL || iter->size == NULL) {
00518                 errno = EINVAL;
00519                 return STATUS_ERR;
00520         }
00521 
00522         *size = iter->size(iter);
00523 
00524         return STATUS_SUCCESS;
00525 }
00526 
00527 void *ebitmap_state_get_cur_type(const qpol_iterator_t * iter)
00528 {
00529         ebitmap_state_t *es = NULL;
00530         const policydb_t *db = NULL;
00531 
00532         if (iter == NULL) {
00533                 errno = EINVAL;
00534                 return NULL;
00535         }
00536         es = qpol_iterator_state(iter);
00537         if (es == NULL) {
00538                 errno = EINVAL;
00539                 return NULL;
00540         }
00541         db = qpol_iterator_policy(iter);
00542         if (db == NULL) {
00543                 errno = EINVAL;
00544                 return NULL;
00545         }
00546 
00547         return db->type_val_to_struct[es->cur];
00548 }
00549 
00550 void *ebitmap_state_get_cur_role(const qpol_iterator_t * iter)
00551 {
00552         ebitmap_state_t *es = NULL;
00553         const policydb_t *db = NULL;
00554 
00555         if (iter == NULL) {
00556                 errno = EINVAL;
00557                 return NULL;
00558         }
00559         es = qpol_iterator_state(iter);
00560         if (es == NULL) {
00561                 errno = EINVAL;
00562                 return NULL;
00563         }
00564         db = qpol_iterator_policy(iter);
00565         if (db == NULL) {
00566                 errno = EINVAL;
00567                 return NULL;
00568         }
00569 
00570         return db->role_val_to_struct[es->cur];
00571 }
00572 
00573 void *ebitmap_state_get_cur_cat(const qpol_iterator_t * iter)
00574 {
00575         ebitmap_state_t *es = NULL;
00576         const policydb_t *db = NULL;
00577         const qpol_cat_t *cat = NULL;
00578         sepol_policydb_t sp;
00579         qpol_policy_t qp;
00580 
00581         if (iter == NULL) {
00582                 errno = EINVAL;
00583                 return NULL;
00584         }
00585         es = qpol_iterator_state(iter);
00586         if (es == NULL) {
00587                 errno = EINVAL;
00588                 return NULL;
00589         }
00590         db = qpol_iterator_policy(iter);
00591         if (db == NULL) {
00592                 errno = EINVAL;
00593                 return NULL;
00594         }
00595 
00596         /* shallow copy is safe here */
00597         sp.p = *db;
00598         qp.p = &sp;
00599         qp.fn = NULL;
00600 
00601         qpol_policy_get_cat_by_name(&qp, db->p_cat_val_to_name[es->cur], &cat);
00602 
00603         /* There is no val_to_struct for categories; this requires that qpol
00604          * search for the struct, but it can't be returned as const here so
00605          * cast it to void* explicitly. */
00606         return (void *)cat;
00607 }
00608 
00609 void ebitmap_state_destroy(void *es)
00610 {
00611         ebitmap_state_t *ies = (ebitmap_state_t *) es;
00612 
00613         if (!es)
00614                 return;
00615 
00616         ebitmap_destroy(ies->bmap);
00617         free(ies->bmap);
00618         free(ies);
00619 }
00620 
00621 int perm_state_end(const qpol_iterator_t * iter)
00622 {
00623         perm_state_t *ps = NULL;
00624         const policydb_t *db = NULL;
00625         unsigned int perm_max = 0;
00626 
00627         if (iter == NULL || (ps = qpol_iterator_state(iter)) == NULL || (db = qpol_iterator_policy(iter)) == NULL) {
00628                 errno = EINVAL;
00629                 return STATUS_ERR;
00630         }
00631 
00632         /* permission max is number of permissions in the class which includes
00633          * the number of permissions in its common if it inherits one */
00634         perm_max = db->class_val_to_struct[ps->obj_class_val - 1]->permissions.nprim;
00635         if (perm_max > 32) {
00636                 errno = EDOM;          /* perms set mask is a uint32_t cannot use more than 32 bits */
00637                 return STATUS_ERR;
00638         }
00639 
00640         if (!(ps->perm_set) || ps->cur >= perm_max)
00641                 return 1;
00642 
00643         return 0;
00644 }
00645 
00646 void *perm_state_get_cur(const qpol_iterator_t * iter)
00647 {
00648         const policydb_t *db = NULL;
00649         class_datum_t *obj_class = NULL;
00650         common_datum_t *comm = NULL;
00651         perm_state_t *ps = NULL;
00652         unsigned int perm_max = 0;
00653         char *tmp = NULL;
00654 
00655         if (iter == NULL || (db = qpol_iterator_policy(iter)) == NULL ||
00656             (ps = (perm_state_t *) qpol_iterator_state(iter)) == NULL || perm_state_end(iter)) {
00657                 errno = EINVAL;
00658                 return NULL;
00659         }
00660 
00661         obj_class = db->class_val_to_struct[ps->obj_class_val - 1];
00662         comm = obj_class->comdatum;
00663 
00664         /* permission max is number of permissions in the class which includes
00665          * the number of permissions in its common if it inherits one */
00666         perm_max = obj_class->permissions.nprim;
00667         if (perm_max > 32) {
00668                 errno = EDOM;          /* perms set mask is a uint32_t cannot use more than 32 bits */
00669                 return NULL;
00670         }
00671         if (ps->cur >= perm_max) {
00672                 errno = ERANGE;
00673                 return NULL;
00674         }
00675         if (!(ps->perm_set & 1 << (ps->cur))) { /* perm bit not set? */
00676                 errno = EINVAL;
00677                 return NULL;
00678         }
00679 
00680         /* explicit const_cast for sepol */
00681         tmp = sepol_av_to_string((policydb_t *) db, ps->obj_class_val, (sepol_access_vector_t) 1 << (ps->cur));
00682         if (tmp) {
00683                 tmp++;                 /*sepol_av_to_string prepends a ' ' to the name */
00684                 return strdup(tmp);
00685         } else {
00686                 errno = EINVAL;
00687                 return NULL;
00688         }
00689 }
00690 
00691 int perm_state_next(qpol_iterator_t * iter)
00692 {
00693         perm_state_t *ps = NULL;
00694         const policydb_t *db = NULL;
00695         unsigned int perm_max = 0;
00696 
00697         if (iter == NULL || (ps = qpol_iterator_state(iter)) == NULL ||
00698             (db = qpol_iterator_policy(iter)) == NULL || perm_state_end(iter)) {
00699                 errno = EINVAL;
00700                 return STATUS_ERR;
00701         }
00702 
00703         /* permission max is number of permissions in the class which includes
00704          * the number of permissions in its common if it inherits one */
00705         perm_max = db->class_val_to_struct[ps->obj_class_val - 1]->permissions.nprim;
00706         if (perm_max > 32) {
00707                 errno = EDOM;          /* perms set mask is a uint32_t cannot use more than 32 bits */
00708                 return STATUS_ERR;
00709         }
00710 
00711         if (ps->cur >= perm_max) {
00712                 errno = ERANGE;
00713                 return STATUS_ERR;
00714         }
00715 
00716         do {
00717                 ps->cur++;
00718         } while (ps->cur < perm_max && !(ps->perm_set & 1 << (ps->cur)));
00719 
00720         return STATUS_SUCCESS;
00721 }
00722 
00723 size_t perm_state_size(const qpol_iterator_t * iter)
00724 {
00725         perm_state_t *ps = NULL;
00726         const policydb_t *db = NULL;
00727         unsigned int perm_max = 0;
00728         size_t i, count = 0;
00729 
00730         if (iter == NULL || (ps = qpol_iterator_state(iter)) == NULL ||
00731             (db = qpol_iterator_policy(iter)) == NULL || perm_state_end(iter)) {
00732                 errno = EINVAL;
00733                 return 0;              /* as a size_t 0 is error */
00734         }
00735 
00736         /* permission max is number of permissions in the class which includes
00737          * the number of permissions in its common if it inherits one */
00738         perm_max = db->class_val_to_struct[ps->obj_class_val - 1]->permissions.nprim;
00739         if (perm_max > 32) {
00740                 errno = EDOM;          /* perms set mask is a uint32_t cannot use more than 32 bits */
00741                 return 0;              /* as a size_t 0 is error */
00742         }
00743 
00744         for (i = 0; i < perm_max; i++) {
00745                 if (ps->perm_set & 1 << i)
00746                         count++;
00747         }
00748 
00749         return count;
00750 }