ebitmap.c (0bd2af46839ad6262d25714a6ec0365db9d6b98f) ebitmap.c (02752760359db6b00a3ffb1acfc13ef8d9eb1e3f)
1/*
2 * Implementation of the extensible bitmap type.
3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */
6/*
7 * Updated: Hewlett-Packard <paul.moore@hp.com>
8 *
1/*
2 * Implementation of the extensible bitmap type.
3 *
4 * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
5 */
6/*
7 * Updated: Hewlett-Packard <paul.moore@hp.com>
8 *
9 * Added ebitmap_export() and ebitmap_import()
9 * Added support to import/export the NetLabel category bitmap
10 *
11 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
12 */
13
14#include <linux/kernel.h>
15#include <linux/slab.h>
16#include <linux/errno.h>
10 *
11 * (c) Copyright Hewlett-Packard Development Company, L.P., 2006
12 */
13
14#include <linux/kernel.h>
15#include <linux/slab.h>
16#include <linux/errno.h>
17#include <net/netlabel.h>
17#include "ebitmap.h"
18#include "policydb.h"
19
20int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
21{
22 struct ebitmap_node *n1, *n2;
23
24 if (e1->highbit != e2->highbit)

--- 37 unchanged lines hidden (view full) ---

62 prev = new;
63 n = n->next;
64 }
65
66 dst->highbit = src->highbit;
67 return 0;
68}
69
18#include "ebitmap.h"
19#include "policydb.h"
20
21int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
22{
23 struct ebitmap_node *n1, *n2;
24
25 if (e1->highbit != e2->highbit)

--- 37 unchanged lines hidden (view full) ---

63 prev = new;
64 n = n->next;
65 }
66
67 dst->highbit = src->highbit;
68 return 0;
69}
70
71#ifdef CONFIG_NETLABEL
70/**
72/**
71 * ebitmap_export - Export an ebitmap to a unsigned char bitmap string
72 * @src: the ebitmap to export
73 * @dst: the resulting bitmap string
74 * @dst_len: length of dst in bytes
73 * ebitmap_netlbl_export - Export an ebitmap into a NetLabel category bitmap
74 * @ebmap: the ebitmap to export
75 * @catmap: the NetLabel category bitmap
75 *
76 * Description:
76 *
77 * Description:
77 * Allocate a buffer at least src->highbit bits long and export the extensible
78 * bitmap into the buffer. The bitmap string will be in little endian format,
79 * i.e. LSB first. The value returned in dst_len may not the true size of the
80 * buffer as the length of the buffer is rounded up to a multiple of MAPTYPE.
81 * The caller must free the buffer when finished. Returns zero on success,
82 * negative values on failure.
78 * Export a SELinux extensibile bitmap into a NetLabel category bitmap.
79 * Returns zero on success, negative values on error.
83 *
84 */
80 *
81 */
85int ebitmap_export(const struct ebitmap *src,
86 unsigned char **dst,
87 size_t *dst_len)
82int ebitmap_netlbl_export(struct ebitmap *ebmap,
83 struct netlbl_lsm_secattr_catmap **catmap)
88{
84{
89 size_t bitmap_len;
90 unsigned char *bitmap;
91 struct ebitmap_node *iter_node;
92 MAPTYPE node_val;
93 size_t bitmap_byte;
94 unsigned char bitmask;
85 struct ebitmap_node *e_iter = ebmap->node;
86 struct netlbl_lsm_secattr_catmap *c_iter;
87 u32 cmap_idx;
95
88
96 if (src->highbit == 0) {
97 *dst = NULL;
98 *dst_len = 0;
89 /* This function is a much simpler because SELinux's MAPTYPE happens
90 * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is
91 * changed from a u64 this function will most likely need to be changed
92 * as well. It's not ideal but I think the tradeoff in terms of
93 * neatness and speed is worth it. */
94
95 if (e_iter == NULL) {
96 *catmap = NULL;
99 return 0;
100 }
101
97 return 0;
98 }
99
102 bitmap_len = src->highbit / 8;
103 if (src->highbit % 7)
104 bitmap_len += 1;
105
106 bitmap = kzalloc((bitmap_len & ~(sizeof(MAPTYPE) - 1)) +
107 sizeof(MAPTYPE),
108 GFP_ATOMIC);
109 if (bitmap == NULL)
100 c_iter = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
101 if (c_iter == NULL)
110 return -ENOMEM;
102 return -ENOMEM;
103 *catmap = c_iter;
104 c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1);
111
105
112 iter_node = src->node;
113 do {
114 bitmap_byte = iter_node->startbit / 8;
115 bitmask = 0x80;
116 node_val = iter_node->map;
117 do {
118 if (bitmask == 0) {
119 bitmap_byte++;
120 bitmask = 0x80;
121 }
122 if (node_val & (MAPTYPE)0x01)
123 bitmap[bitmap_byte] |= bitmask;
124 node_val >>= 1;
125 bitmask >>= 1;
126 } while (node_val > 0);
127 iter_node = iter_node->next;
128 } while (iter_node);
106 while (e_iter != NULL) {
107 if (e_iter->startbit >=
108 (c_iter->startbit + NETLBL_CATMAP_SIZE)) {
109 c_iter->next = netlbl_secattr_catmap_alloc(GFP_ATOMIC);
110 if (c_iter->next == NULL)
111 goto netlbl_export_failure;
112 c_iter = c_iter->next;
113 c_iter->startbit = e_iter->startbit &
114 ~(NETLBL_CATMAP_SIZE - 1);
115 }
116 cmap_idx = (e_iter->startbit - c_iter->startbit) /
117 NETLBL_CATMAP_MAPSIZE;
118 c_iter->bitmap[cmap_idx] = e_iter->map;
119 e_iter = e_iter->next;
120 }
129
121
130 *dst = bitmap;
131 *dst_len = bitmap_len;
132 return 0;
122 return 0;
123
124netlbl_export_failure:
125 netlbl_secattr_catmap_free(*catmap);
126 return -ENOMEM;
133}
134
135/**
127}
128
129/**
136 * ebitmap_import - Import an unsigned char bitmap string into an ebitmap
137 * @src: the bitmap string
138 * @src_len: the bitmap length in bytes
139 * @dst: the empty ebitmap
130 * ebitmap_netlbl_import - Import a NetLabel category bitmap into an ebitmap
131 * @ebmap: the ebitmap to export
132 * @catmap: the NetLabel category bitmap
140 *
141 * Description:
133 *
134 * Description:
142 * This function takes a little endian bitmap string in src and imports it into
143 * the ebitmap pointed to by dst. Returns zero on success, negative values on
144 * failure.
135 * Import a NetLabel category bitmap into a SELinux extensibile bitmap.
136 * Returns zero on success, negative values on error.
145 *
146 */
137 *
138 */
147int ebitmap_import(const unsigned char *src,
148 size_t src_len,
149 struct ebitmap *dst)
139int ebitmap_netlbl_import(struct ebitmap *ebmap,
140 struct netlbl_lsm_secattr_catmap *catmap)
150{
141{
151 size_t src_off = 0;
152 size_t node_limit;
153 struct ebitmap_node *node_new;
154 struct ebitmap_node *node_last = NULL;
155 u32 i_byte;
156 u32 i_bit;
157 unsigned char src_byte;
142 struct ebitmap_node *e_iter = NULL;
143 struct ebitmap_node *emap_prev = NULL;
144 struct netlbl_lsm_secattr_catmap *c_iter = catmap;
145 u32 c_idx;
158
146
159 while (src_off < src_len) {
160 if (src_len - src_off >= sizeof(MAPTYPE)) {
161 if (*(MAPTYPE *)&src[src_off] == 0) {
162 src_off += sizeof(MAPTYPE);
147 /* This function is a much simpler because SELinux's MAPTYPE happens
148 * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is
149 * changed from a u64 this function will most likely need to be changed
150 * as well. It's not ideal but I think the tradeoff in terms of
151 * neatness and speed is worth it. */
152
153 do {
154 for (c_idx = 0; c_idx < NETLBL_CATMAP_MAPCNT; c_idx++) {
155 if (c_iter->bitmap[c_idx] == 0)
163 continue;
156 continue;
164 }
165 node_limit = sizeof(MAPTYPE);
166 } else {
167 for (src_byte = 0, i_byte = src_off;
168 i_byte < src_len && src_byte == 0;
169 i_byte++)
170 src_byte |= src[i_byte];
171 if (src_byte == 0)
172 break;
173 node_limit = src_len - src_off;
174 }
175
157
176 node_new = kzalloc(sizeof(*node_new), GFP_ATOMIC);
177 if (unlikely(node_new == NULL)) {
178 ebitmap_destroy(dst);
179 return -ENOMEM;
180 }
181 node_new->startbit = src_off * 8;
182 for (i_byte = 0; i_byte < node_limit; i_byte++) {
183 src_byte = src[src_off++];
184 for (i_bit = i_byte * 8; src_byte != 0; i_bit++) {
185 if (src_byte & 0x80)
186 node_new->map |= MAPBIT << i_bit;
187 src_byte <<= 1;
188 }
189 }
158 e_iter = kzalloc(sizeof(*e_iter), GFP_ATOMIC);
159 if (e_iter == NULL)
160 goto netlbl_import_failure;
161 if (emap_prev == NULL)
162 ebmap->node = e_iter;
163 else
164 emap_prev->next = e_iter;
165 emap_prev = e_iter;
190
166
191 if (node_last != NULL)
192 node_last->next = node_new;
193 else
194 dst->node = node_new;
195 node_last = node_new;
196 }
197
198 if (likely(node_last != NULL))
199 dst->highbit = node_last->startbit + MAPSIZE;
167 e_iter->startbit = c_iter->startbit +
168 NETLBL_CATMAP_MAPSIZE * c_idx;
169 e_iter->map = c_iter->bitmap[c_idx];
170 }
171 c_iter = c_iter->next;
172 } while (c_iter != NULL);
173 if (e_iter != NULL)
174 ebmap->highbit = e_iter->startbit + MAPSIZE;
200 else
175 else
201 ebitmap_init(dst);
176 ebitmap_destroy(ebmap);
202
203 return 0;
177
178 return 0;
179
180netlbl_import_failure:
181 ebitmap_destroy(ebmap);
182 return -ENOMEM;
204}
183}
184#endif /* CONFIG_NETLABEL */
205
206int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
207{
208 struct ebitmap_node *n1, *n2;
209
210 if (e1->highbit < e2->highbit)
211 return 0;
212

--- 223 unchanged lines hidden ---
185
186int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
187{
188 struct ebitmap_node *n1, *n2;
189
190 if (e1->highbit < e2->highbit)
191 return 0;
192

--- 223 unchanged lines hidden ---