aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux/ss/ebitmap.c
diff options
context:
space:
mode:
authorPaul Moore <paul.moore@hp.com>2006-11-29 13:18:18 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:31:36 -0500
commit02752760359db6b00a3ffb1acfc13ef8d9eb1e3f (patch)
tree796cd65fd4cd732b295e61dac194efbf36b78842 /security/selinux/ss/ebitmap.c
parentef91fd522ba3c88d9c68261c243567bc4c5a8f55 (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.c198
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 */
85int ebitmap_export(const struct ebitmap *src, 82int 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
124netlbl_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 */
147int ebitmap_import(const unsigned char *src, 139int 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
180netlbl_import_failure:
181 ebitmap_destroy(ebmap);
182 return -ENOMEM;
204} 183}
184#endif /* CONFIG_NETLABEL */
205 185
206int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2) 186int ebitmap_contains(struct ebitmap *e1, struct ebitmap *e2)
207{ 187{