/* * Check to see if all the bits set in e2 are also set in e1. Optionally, * if last_e2bit is non-zero, the highest set bit in e2 cannot exceed * last_e2bit.
*/ int ebitmap_contains(conststruct ebitmap *e1, conststruct ebitmap *e2,
u32 last_e2bit)
{ conststruct ebitmap_node *n1, *n2; int i;
if (e1->highbit < e2->highbit) return 0;
n1 = e1->node;
n2 = e2->node;
while (n1 && n2 && (n1->startbit <= n2->startbit)) { if (n1->startbit < n2->startbit) {
n1 = n1->next; continue;
} for (i = EBITMAP_UNIT_NUMS - 1; (i >= 0) && !n2->maps[i];)
i--; /* Skip trailing NULL map entries */ if (last_e2bit && (i >= 0)) {
u32 lastsetbit = n2->startbit + i * EBITMAP_UNIT_SIZE +
__fls(n2->maps[i]); if (lastsetbit > last_e2bit) return 0;
}
while (i >= 0) { if ((n1->maps[i] & n2->maps[i]) != n2->maps[i]) return 0;
i--;
}
n1 = n1->next;
n2 = n2->next;
}
if (n2) return 0;
return 1;
}
int ebitmap_get_bit(conststruct ebitmap *e, u32 bit)
{ conststruct ebitmap_node *n;
if (e->highbit < bit) return 0;
n = e->node; while (n && (n->startbit <= bit)) { if ((n->startbit + EBITMAP_SIZE) > bit) return ebitmap_node_get_bit(n, bit);
n = n->next;
}
return 0;
}
int ebitmap_set_bit(struct ebitmap *e, u32 bit, int value)
{ struct ebitmap_node *n, *prev, *new;
prev = NULL;
n = e->node; while (n && n->startbit <= bit) { if ((n->startbit + EBITMAP_SIZE) > bit) { if (value) {
ebitmap_node_set_bit(n, bit);
} else {
u32 s;
ebitmap_node_clr_bit(n, bit);
s = find_first_bit(n->maps, EBITMAP_SIZE); if (s < EBITMAP_SIZE) return 0;
/* drop this node from the bitmap */ if (!n->next) { /* * this was the highest map * within the bitmap
*/ if (prev)
e->highbit = prev->startbit +
EBITMAP_SIZE; else
e->highbit = 0;
} if (prev)
prev->next = n->next; else
e->node = n->next;
kmem_cache_free(ebitmap_node_cachep, n);
} return 0;
}
prev = n;
n = n->next;
}
if (!value) return 0;
new = kmem_cache_zalloc(ebitmap_node_cachep, GFP_ATOMIC); if (!new) return -ENOMEM;
new->startbit = bit - (bit % EBITMAP_SIZE);
ebitmap_node_set_bit(new, bit);
if (!n) /* this node will be the highest map within the bitmap */
e->highbit = new->startbit + EBITMAP_SIZE;
if (mapunit != BITS_PER_U64) {
pr_err("SELinux: ebitmap: map size %u does not " "match my size %u (high bit was %u)\n",
mapunit, BITS_PER_U64, e->highbit); goto bad;
}
for (i = 0; i < count; i++) {
rc = next_entry(&ebitmap_start, fp, sizeof(u32)); if (rc < 0) {
pr_err("SELinux: ebitmap: truncated map\n"); goto bad;
}
startbit = le32_to_cpu(ebitmap_start);
if (startbit & (mapunit - 1)) {
pr_err("SELinux: ebitmap start bit (%u) is " "not a multiple of the map unit size (%u)\n",
startbit, mapunit); goto bad;
} if (startbit > e->highbit - mapunit) {
pr_err("SELinux: ebitmap start bit (%u) is " "beyond the end of the bitmap (%u)\n",
startbit, (e->highbit - mapunit)); goto bad;
}
if (!n || startbit >= n->startbit + EBITMAP_SIZE) { struct ebitmap_node *tmp;
tmp = kmem_cache_zalloc(ebitmap_node_cachep,
GFP_KERNEL); if (!tmp) {
pr_err("SELinux: ebitmap: out of memory\n");
rc = -ENOMEM; goto bad;
} /* round down */
tmp->startbit = startbit - (startbit % EBITMAP_SIZE); if (n)
n->next = tmp; else
e->node = tmp;
n = tmp;
} elseif (startbit <= n->startbit) {
pr_err("SELinux: ebitmap: start bit %u" " comes after start bit %u\n",
startbit, n->startbit); goto bad;
}
index = (startbit - n->startbit) / EBITMAP_UNIT_SIZE; while (map) {
n->maps[index++] = map & (-1UL);
map = EBITMAP_SHIFT_UNIT_SIZE(map);
}
}
if (n && n->startbit + EBITMAP_SIZE != e->highbit) {
pr_err("SELinux: ebitmap: high bit %u is not equal to the expected value %zu\n",
e->highbit, n->startbit + EBITMAP_SIZE); goto bad;
}
/* set up for the next node */
map = 0;
last_startbit = rounddown(bit, BITS_PER_U64);
}
map |= (u64)1 << (bit - last_startbit);
} /* write the last node */ if (map) {
__le64 buf64[1];
/* write the last node */
buf[0] = cpu_to_le32(last_startbit);
rc = put_entry(buf, sizeof(u32), 1, fp); if (rc) return rc;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.