diff options
author | Paul Moore <paul.moore@hp.com> | 2006-11-29 13:18:18 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-03 00:31:36 -0500 |
commit | 02752760359db6b00a3ffb1acfc13ef8d9eb1e3f (patch) | |
tree | 796cd65fd4cd732b295e61dac194efbf36b78842 /security/selinux/ss/ebitmap.c | |
parent | ef91fd522ba3c88d9c68261c243567bc4c5a8f55 (diff) |
NetLabel: convert to an extensibile/sparse category bitmap
The original NetLabel category bitmap was a straight char bitmap which worked
fine for the initial release as it only supported 240 bits due to limitations
in the CIPSO restricted bitmap tag (tag type 0x01). This patch converts that
straight char bitmap into an extensibile/sparse bitmap in order to lay the
foundation for other CIPSO tag types and protocols.
This patch also has a nice side effect in that all of the security attributes
passed by NetLabel into the LSM are now in a format which is in the host's
native byte/bit ordering which makes the LSM specific code much simpler; look
at the changes in security/selinux/ss/ebitmap.c as an example.
Signed-off-by: Paul Moore <paul.moore@hp.com>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/selinux/ss/ebitmap.c')
-rw-r--r-- | security/selinux/ss/ebitmap.c | 198 |
1 files changed, 89 insertions, 109 deletions
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index d539346ab3a2..ce492a6b38ed 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c | |||
@@ -6,7 +6,7 @@ | |||
6 | /* | 6 | /* |
7 | * Updated: Hewlett-Packard <paul.moore@hp.com> | 7 | * Updated: Hewlett-Packard <paul.moore@hp.com> |
8 | * | 8 | * |
9 | * Added ebitmap_export() and ebitmap_import() | 9 | * Added support to import/export the NetLabel category bitmap |
10 | * | 10 | * |
11 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 | 11 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 |
12 | */ | 12 | */ |
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
17 | #include <net/netlabel.h> | ||
17 | #include "ebitmap.h" | 18 | #include "ebitmap.h" |
18 | #include "policydb.h" | 19 | #include "policydb.h" |
19 | 20 | ||
@@ -67,141 +68,120 @@ int ebitmap_cpy(struct ebitmap *dst, struct ebitmap *src) | |||
67 | return 0; | 68 | return 0; |
68 | } | 69 | } |
69 | 70 | ||
71 | #ifdef CONFIG_NETLABEL | ||
70 | /** | 72 | /** |
71 | * ebitmap_export - Export an ebitmap to a unsigned char bitmap string | 73 | * ebitmap_netlbl_export - Export an ebitmap into a NetLabel category bitmap |
72 | * @src: the ebitmap to export | 74 | * @ebmap: the ebitmap to export |
73 | * @dst: the resulting bitmap string | 75 | * @catmap: the NetLabel category bitmap |
74 | * @dst_len: length of dst in bytes | ||
75 | * | 76 | * |
76 | * Description: | 77 | * Description: |
77 | * Allocate a buffer at least src->highbit bits long and export the extensible | 78 | * Export a SELinux extensibile bitmap into a NetLabel category bitmap. |
78 | * bitmap into the buffer. The bitmap string will be in little endian format, | 79 | * Returns zero on success, negative values on error. |
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. | ||
83 | * | 80 | * |
84 | */ | 81 | */ |
85 | int ebitmap_export(const struct ebitmap *src, | 82 | int ebitmap_netlbl_export(struct ebitmap *ebmap, |
86 | unsigned char **dst, | 83 | struct netlbl_lsm_secattr_catmap **catmap) |
87 | size_t *dst_len) | ||
88 | { | 84 | { |
89 | size_t bitmap_len; | 85 | struct ebitmap_node *e_iter = ebmap->node; |
90 | unsigned char *bitmap; | 86 | struct netlbl_lsm_secattr_catmap *c_iter; |
91 | struct ebitmap_node *iter_node; | 87 | u32 cmap_idx; |
92 | MAPTYPE node_val; | 88 | |
93 | size_t bitmap_byte; | 89 | /* This function is a much simpler because SELinux's MAPTYPE happens |
94 | unsigned char bitmask; | 90 | * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is |
95 | 91 | * changed from a u64 this function will most likely need to be changed | |
96 | if (src->highbit == 0) { | 92 | * as well. It's not ideal but I think the tradeoff in terms of |
97 | *dst = NULL; | 93 | * neatness and speed is worth it. */ |
98 | *dst_len = 0; | 94 | |
95 | if (e_iter == NULL) { | ||
96 | *catmap = NULL; | ||
99 | return 0; | 97 | return 0; |
100 | } | 98 | } |
101 | 99 | ||
102 | bitmap_len = src->highbit / 8; | 100 | c_iter = netlbl_secattr_catmap_alloc(GFP_ATOMIC); |
103 | if (src->highbit % 7) | 101 | if (c_iter == NULL) |
104 | bitmap_len += 1; | ||
105 | |||
106 | bitmap = kzalloc((bitmap_len & ~(sizeof(MAPTYPE) - 1)) + | ||
107 | sizeof(MAPTYPE), | ||
108 | GFP_ATOMIC); | ||
109 | if (bitmap == NULL) | ||
110 | return -ENOMEM; | 102 | return -ENOMEM; |
103 | *catmap = c_iter; | ||
104 | c_iter->startbit = e_iter->startbit & ~(NETLBL_CATMAP_SIZE - 1); | ||
105 | |||
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 | } | ||
111 | 121 | ||
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); | ||
129 | |||
130 | *dst = bitmap; | ||
131 | *dst_len = bitmap_len; | ||
132 | return 0; | 122 | return 0; |
123 | |||
124 | netlbl_export_failure: | ||
125 | netlbl_secattr_catmap_free(*catmap); | ||
126 | return -ENOMEM; | ||
133 | } | 127 | } |
134 | 128 | ||
135 | /** | 129 | /** |
136 | * ebitmap_import - Import an unsigned char bitmap string into an ebitmap | 130 | * ebitmap_netlbl_import - Import a NetLabel category bitmap into an ebitmap |
137 | * @src: the bitmap string | 131 | * @ebmap: the ebitmap to export |
138 | * @src_len: the bitmap length in bytes | 132 | * @catmap: the NetLabel category bitmap |
139 | * @dst: the empty ebitmap | ||
140 | * | 133 | * |
141 | * Description: | 134 | * Description: |
142 | * This function takes a little endian bitmap string in src and imports it into | 135 | * Import a NetLabel category bitmap into a SELinux extensibile bitmap. |
143 | * the ebitmap pointed to by dst. Returns zero on success, negative values on | 136 | * Returns zero on success, negative values on error. |
144 | * failure. | ||
145 | * | 137 | * |
146 | */ | 138 | */ |
147 | int ebitmap_import(const unsigned char *src, | 139 | int ebitmap_netlbl_import(struct ebitmap *ebmap, |
148 | size_t src_len, | 140 | struct netlbl_lsm_secattr_catmap *catmap) |
149 | struct ebitmap *dst) | ||
150 | { | 141 | { |
151 | size_t src_off = 0; | 142 | struct ebitmap_node *e_iter = NULL; |
152 | size_t node_limit; | 143 | struct ebitmap_node *emap_prev = NULL; |
153 | struct ebitmap_node *node_new; | 144 | struct netlbl_lsm_secattr_catmap *c_iter = catmap; |
154 | struct ebitmap_node *node_last = NULL; | 145 | u32 c_idx; |
155 | u32 i_byte; | ||
156 | u32 i_bit; | ||
157 | unsigned char src_byte; | ||
158 | |||
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); | ||
163 | 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 | 146 | ||
176 | node_new = kzalloc(sizeof(*node_new), GFP_ATOMIC); | 147 | /* This function is a much simpler because SELinux's MAPTYPE happens |
177 | if (unlikely(node_new == NULL)) { | 148 | * to be the same as NetLabel's NETLBL_CATMAP_MAPTYPE, if MAPTYPE is |
178 | ebitmap_destroy(dst); | 149 | * changed from a u64 this function will most likely need to be changed |
179 | return -ENOMEM; | 150 | * as well. It's not ideal but I think the tradeoff in terms of |
180 | } | 151 | * neatness and speed is worth it. */ |
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 | } | ||
190 | 152 | ||
191 | if (node_last != NULL) | 153 | do { |
192 | node_last->next = node_new; | 154 | for (c_idx = 0; c_idx < NETLBL_CATMAP_MAPCNT; c_idx++) { |
193 | else | 155 | if (c_iter->bitmap[c_idx] == 0) |
194 | dst->node = node_new; | 156 | continue; |
195 | node_last = node_new; | 157 | |
196 | } | 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; | ||
197 | 166 | ||
198 | if (likely(node_last != NULL)) | 167 | e_iter->startbit = c_iter->startbit + |
199 | dst->highbit = node_last->startbit + MAPSIZE; | 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 | 177 | ||
203 | return 0; | 178 | return 0; |
179 | |||
180 | netlbl_import_failure: | ||
181 | ebitmap_destroy(ebmap); | ||
182 | return -ENOMEM; | ||
204 | } | 183 | } |
184 | #endif /* CONFIG_NETLABEL */ | ||
205 | 185 | ||
206 | int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2) | 186 | int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2) |
207 | { | 187 | { |