diff options
Diffstat (limited to 'net/netlabel')
-rw-r--r-- | net/netlabel/netlabel_addrlist.c | 130 | ||||
-rw-r--r-- | net/netlabel/netlabel_addrlist.h | 15 | ||||
-rw-r--r-- | net/netlabel/netlabel_domainhash.c | 290 | ||||
-rw-r--r-- | net/netlabel/netlabel_domainhash.h | 38 | ||||
-rw-r--r-- | net/netlabel/netlabel_kapi.c | 7 | ||||
-rw-r--r-- | net/netlabel/netlabel_mgmt.c | 398 | ||||
-rw-r--r-- | net/netlabel/netlabel_mgmt.h | 59 | ||||
-rw-r--r-- | net/netlabel/netlabel_unlabeled.c | 96 |
8 files changed, 811 insertions, 222 deletions
diff --git a/net/netlabel/netlabel_addrlist.c b/net/netlabel/netlabel_addrlist.c index dd928aa52db1..b0925a303353 100644 --- a/net/netlabel/netlabel_addrlist.c +++ b/net/netlabel/netlabel_addrlist.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <linux/ipv6.h> | 39 | #include <linux/ipv6.h> |
40 | #include <net/ip.h> | 40 | #include <net/ip.h> |
41 | #include <net/ipv6.h> | 41 | #include <net/ipv6.h> |
42 | #include <linux/audit.h> | ||
42 | 43 | ||
43 | #include "netlabel_addrlist.h" | 44 | #include "netlabel_addrlist.h" |
44 | 45 | ||
@@ -69,6 +70,32 @@ struct netlbl_af4list *netlbl_af4list_search(__be32 addr, | |||
69 | return NULL; | 70 | return NULL; |
70 | } | 71 | } |
71 | 72 | ||
73 | /** | ||
74 | * netlbl_af4list_search_exact - Search for an exact IPv4 address entry | ||
75 | * @addr: IPv4 address | ||
76 | * @mask: IPv4 address mask | ||
77 | * @head: the list head | ||
78 | * | ||
79 | * Description: | ||
80 | * Searches the IPv4 address list given by @head. If an exact match if found | ||
81 | * it is returned, otherwise NULL is returned. The caller is responsible for | ||
82 | * calling the rcu_read_[un]lock() functions. | ||
83 | * | ||
84 | */ | ||
85 | struct netlbl_af4list *netlbl_af4list_search_exact(__be32 addr, | ||
86 | __be32 mask, | ||
87 | struct list_head *head) | ||
88 | { | ||
89 | struct netlbl_af4list *iter; | ||
90 | |||
91 | list_for_each_entry_rcu(iter, head, list) | ||
92 | if (iter->valid && iter->addr == addr && iter->mask == mask) | ||
93 | return iter; | ||
94 | |||
95 | return NULL; | ||
96 | } | ||
97 | |||
98 | |||
72 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 99 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
73 | /** | 100 | /** |
74 | * netlbl_af6list_search - Search for a matching IPv6 address entry | 101 | * netlbl_af6list_search - Search for a matching IPv6 address entry |
@@ -93,6 +120,33 @@ struct netlbl_af6list *netlbl_af6list_search(const struct in6_addr *addr, | |||
93 | 120 | ||
94 | return NULL; | 121 | return NULL; |
95 | } | 122 | } |
123 | |||
124 | /** | ||
125 | * netlbl_af6list_search_exact - Search for an exact IPv6 address entry | ||
126 | * @addr: IPv6 address | ||
127 | * @mask: IPv6 address mask | ||
128 | * @head: the list head | ||
129 | * | ||
130 | * Description: | ||
131 | * Searches the IPv6 address list given by @head. If an exact match if found | ||
132 | * it is returned, otherwise NULL is returned. The caller is responsible for | ||
133 | * calling the rcu_read_[un]lock() functions. | ||
134 | * | ||
135 | */ | ||
136 | struct netlbl_af6list *netlbl_af6list_search_exact(const struct in6_addr *addr, | ||
137 | const struct in6_addr *mask, | ||
138 | struct list_head *head) | ||
139 | { | ||
140 | struct netlbl_af6list *iter; | ||
141 | |||
142 | list_for_each_entry_rcu(iter, head, list) | ||
143 | if (iter->valid && | ||
144 | ipv6_addr_equal(&iter->addr, addr) && | ||
145 | ipv6_addr_equal(&iter->mask, mask)) | ||
146 | return iter; | ||
147 | |||
148 | return NULL; | ||
149 | } | ||
96 | #endif /* IPv6 */ | 150 | #endif /* IPv6 */ |
97 | 151 | ||
98 | /** | 152 | /** |
@@ -256,3 +310,79 @@ struct netlbl_af6list *netlbl_af6list_remove(const struct in6_addr *addr, | |||
256 | return NULL; | 310 | return NULL; |
257 | } | 311 | } |
258 | #endif /* IPv6 */ | 312 | #endif /* IPv6 */ |
313 | |||
314 | /* | ||
315 | * Audit Helper Functions | ||
316 | */ | ||
317 | |||
318 | /** | ||
319 | * netlbl_af4list_audit_addr - Audit an IPv4 address | ||
320 | * @audit_buf: audit buffer | ||
321 | * @src: true if source address, false if destination | ||
322 | * @dev: network interface | ||
323 | * @addr: IP address | ||
324 | * @mask: IP address mask | ||
325 | * | ||
326 | * Description: | ||
327 | * Write the IPv4 address and address mask, if necessary, to @audit_buf. | ||
328 | * | ||
329 | */ | ||
330 | void netlbl_af4list_audit_addr(struct audit_buffer *audit_buf, | ||
331 | int src, const char *dev, | ||
332 | __be32 addr, __be32 mask) | ||
333 | { | ||
334 | u32 mask_val = ntohl(mask); | ||
335 | char *dir = (src ? "src" : "dst"); | ||
336 | |||
337 | if (dev != NULL) | ||
338 | audit_log_format(audit_buf, " netif=%s", dev); | ||
339 | audit_log_format(audit_buf, " %s=" NIPQUAD_FMT, dir, NIPQUAD(addr)); | ||
340 | if (mask_val != 0xffffffff) { | ||
341 | u32 mask_len = 0; | ||
342 | while (mask_val > 0) { | ||
343 | mask_val <<= 1; | ||
344 | mask_len++; | ||
345 | } | ||
346 | audit_log_format(audit_buf, " %s_prefixlen=%d", dir, mask_len); | ||
347 | } | ||
348 | } | ||
349 | |||
350 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
351 | /** | ||
352 | * netlbl_af6list_audit_addr - Audit an IPv6 address | ||
353 | * @audit_buf: audit buffer | ||
354 | * @src: true if source address, false if destination | ||
355 | * @dev: network interface | ||
356 | * @addr: IP address | ||
357 | * @mask: IP address mask | ||
358 | * | ||
359 | * Description: | ||
360 | * Write the IPv6 address and address mask, if necessary, to @audit_buf. | ||
361 | * | ||
362 | */ | ||
363 | void netlbl_af6list_audit_addr(struct audit_buffer *audit_buf, | ||
364 | int src, | ||
365 | const char *dev, | ||
366 | const struct in6_addr *addr, | ||
367 | const struct in6_addr *mask) | ||
368 | { | ||
369 | char *dir = (src ? "src" : "dst"); | ||
370 | |||
371 | if (dev != NULL) | ||
372 | audit_log_format(audit_buf, " netif=%s", dev); | ||
373 | audit_log_format(audit_buf, " %s=" NIP6_FMT, dir, NIP6(*addr)); | ||
374 | if (ntohl(mask->s6_addr32[3]) != 0xffffffff) { | ||
375 | u32 mask_len = 0; | ||
376 | u32 mask_val; | ||
377 | int iter = -1; | ||
378 | while (ntohl(mask->s6_addr32[++iter]) == 0xffffffff) | ||
379 | mask_len += 32; | ||
380 | mask_val = ntohl(mask->s6_addr32[iter]); | ||
381 | while (mask_val > 0) { | ||
382 | mask_val <<= 1; | ||
383 | mask_len++; | ||
384 | } | ||
385 | audit_log_format(audit_buf, " %s_prefixlen=%d", dir, mask_len); | ||
386 | } | ||
387 | } | ||
388 | #endif /* IPv6 */ | ||
diff --git a/net/netlabel/netlabel_addrlist.h b/net/netlabel/netlabel_addrlist.h index 0c41df057fa8..0242bead405f 100644 --- a/net/netlabel/netlabel_addrlist.h +++ b/net/netlabel/netlabel_addrlist.h | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/rcupdate.h> | 36 | #include <linux/rcupdate.h> |
37 | #include <linux/list.h> | 37 | #include <linux/list.h> |
38 | #include <linux/in6.h> | 38 | #include <linux/in6.h> |
39 | #include <linux/audit.h> | ||
39 | 40 | ||
40 | /** | 41 | /** |
41 | * struct netlbl_af4list - NetLabel IPv4 address list | 42 | * struct netlbl_af4list - NetLabel IPv4 address list |
@@ -116,6 +117,12 @@ struct netlbl_af4list *netlbl_af4list_remove(__be32 addr, __be32 mask, | |||
116 | void netlbl_af4list_remove_entry(struct netlbl_af4list *entry); | 117 | void netlbl_af4list_remove_entry(struct netlbl_af4list *entry); |
117 | struct netlbl_af4list *netlbl_af4list_search(__be32 addr, | 118 | struct netlbl_af4list *netlbl_af4list_search(__be32 addr, |
118 | struct list_head *head); | 119 | struct list_head *head); |
120 | struct netlbl_af4list *netlbl_af4list_search_exact(__be32 addr, | ||
121 | __be32 mask, | ||
122 | struct list_head *head); | ||
123 | void netlbl_af4list_audit_addr(struct audit_buffer *audit_buf, | ||
124 | int src, const char *dev, | ||
125 | __be32 addr, __be32 mask); | ||
119 | 126 | ||
120 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 127 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
121 | 128 | ||
@@ -169,6 +176,14 @@ struct netlbl_af6list *netlbl_af6list_remove(const struct in6_addr *addr, | |||
169 | void netlbl_af6list_remove_entry(struct netlbl_af6list *entry); | 176 | void netlbl_af6list_remove_entry(struct netlbl_af6list *entry); |
170 | struct netlbl_af6list *netlbl_af6list_search(const struct in6_addr *addr, | 177 | struct netlbl_af6list *netlbl_af6list_search(const struct in6_addr *addr, |
171 | struct list_head *head); | 178 | struct list_head *head); |
179 | struct netlbl_af6list *netlbl_af6list_search_exact(const struct in6_addr *addr, | ||
180 | const struct in6_addr *mask, | ||
181 | struct list_head *head); | ||
182 | void netlbl_af6list_audit_addr(struct audit_buffer *audit_buf, | ||
183 | int src, | ||
184 | const char *dev, | ||
185 | const struct in6_addr *addr, | ||
186 | const struct in6_addr *mask); | ||
172 | #endif /* IPV6 */ | 187 | #endif /* IPV6 */ |
173 | 188 | ||
174 | #endif | 189 | #endif |
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index 0243f0c57b41..5fadf10e5ddf 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c | |||
@@ -11,7 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 | 14 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008 |
15 | * | 15 | * |
16 | * This program is free software; you can redistribute it and/or modify | 16 | * This program is free software; you can redistribute it and/or modify |
17 | * it under the terms of the GNU General Public License as published by | 17 | * it under the terms of the GNU General Public License as published by |
@@ -40,6 +40,7 @@ | |||
40 | #include <asm/bug.h> | 40 | #include <asm/bug.h> |
41 | 41 | ||
42 | #include "netlabel_mgmt.h" | 42 | #include "netlabel_mgmt.h" |
43 | #include "netlabel_addrlist.h" | ||
43 | #include "netlabel_domainhash.h" | 44 | #include "netlabel_domainhash.h" |
44 | #include "netlabel_user.h" | 45 | #include "netlabel_user.h" |
45 | 46 | ||
@@ -72,8 +73,28 @@ static struct netlbl_dom_map *netlbl_domhsh_def = NULL; | |||
72 | static void netlbl_domhsh_free_entry(struct rcu_head *entry) | 73 | static void netlbl_domhsh_free_entry(struct rcu_head *entry) |
73 | { | 74 | { |
74 | struct netlbl_dom_map *ptr; | 75 | struct netlbl_dom_map *ptr; |
76 | struct netlbl_af4list *iter4; | ||
77 | struct netlbl_af4list *tmp4; | ||
78 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
79 | struct netlbl_af6list *iter6; | ||
80 | struct netlbl_af6list *tmp6; | ||
81 | #endif /* IPv6 */ | ||
75 | 82 | ||
76 | ptr = container_of(entry, struct netlbl_dom_map, rcu); | 83 | ptr = container_of(entry, struct netlbl_dom_map, rcu); |
84 | if (ptr->type == NETLBL_NLTYPE_ADDRSELECT) { | ||
85 | netlbl_af4list_foreach_safe(iter4, tmp4, | ||
86 | &ptr->type_def.addrsel->list4) { | ||
87 | netlbl_af4list_remove_entry(iter4); | ||
88 | kfree(netlbl_domhsh_addr4_entry(iter4)); | ||
89 | } | ||
90 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
91 | netlbl_af6list_foreach_safe(iter6, tmp6, | ||
92 | &ptr->type_def.addrsel->list6) { | ||
93 | netlbl_af6list_remove_entry(iter6); | ||
94 | kfree(netlbl_domhsh_addr6_entry(iter6)); | ||
95 | } | ||
96 | #endif /* IPv6 */ | ||
97 | } | ||
77 | kfree(ptr->domain); | 98 | kfree(ptr->domain); |
78 | kfree(ptr); | 99 | kfree(ptr); |
79 | } | 100 | } |
@@ -156,6 +177,69 @@ static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) | |||
156 | return entry; | 177 | return entry; |
157 | } | 178 | } |
158 | 179 | ||
180 | /** | ||
181 | * netlbl_domhsh_audit_add - Generate an audit entry for an add event | ||
182 | * @entry: the entry being added | ||
183 | * @addr4: the IPv4 address information | ||
184 | * @addr6: the IPv6 address information | ||
185 | * @result: the result code | ||
186 | * @audit_info: NetLabel audit information | ||
187 | * | ||
188 | * Description: | ||
189 | * Generate an audit record for adding a new NetLabel/LSM mapping entry with | ||
190 | * the given information. Caller is responsibile for holding the necessary | ||
191 | * locks. | ||
192 | * | ||
193 | */ | ||
194 | static void netlbl_domhsh_audit_add(struct netlbl_dom_map *entry, | ||
195 | struct netlbl_af4list *addr4, | ||
196 | struct netlbl_af6list *addr6, | ||
197 | int result, | ||
198 | struct netlbl_audit *audit_info) | ||
199 | { | ||
200 | struct audit_buffer *audit_buf; | ||
201 | struct cipso_v4_doi *cipsov4 = NULL; | ||
202 | u32 type; | ||
203 | |||
204 | audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info); | ||
205 | if (audit_buf != NULL) { | ||
206 | audit_log_format(audit_buf, " nlbl_domain=%s", | ||
207 | entry->domain ? entry->domain : "(default)"); | ||
208 | if (addr4 != NULL) { | ||
209 | struct netlbl_domaddr4_map *map4; | ||
210 | map4 = netlbl_domhsh_addr4_entry(addr4); | ||
211 | type = map4->type; | ||
212 | cipsov4 = map4->type_def.cipsov4; | ||
213 | netlbl_af4list_audit_addr(audit_buf, 0, NULL, | ||
214 | addr4->addr, addr4->mask); | ||
215 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
216 | } else if (addr6 != NULL) { | ||
217 | struct netlbl_domaddr6_map *map6; | ||
218 | map6 = netlbl_domhsh_addr6_entry(addr6); | ||
219 | type = map6->type; | ||
220 | netlbl_af6list_audit_addr(audit_buf, 0, NULL, | ||
221 | &addr6->addr, &addr6->mask); | ||
222 | #endif /* IPv6 */ | ||
223 | } else { | ||
224 | type = entry->type; | ||
225 | cipsov4 = entry->type_def.cipsov4; | ||
226 | } | ||
227 | switch (type) { | ||
228 | case NETLBL_NLTYPE_UNLABELED: | ||
229 | audit_log_format(audit_buf, " nlbl_protocol=unlbl"); | ||
230 | break; | ||
231 | case NETLBL_NLTYPE_CIPSOV4: | ||
232 | BUG_ON(cipsov4 == NULL); | ||
233 | audit_log_format(audit_buf, | ||
234 | " nlbl_protocol=cipsov4 cipso_doi=%u", | ||
235 | cipsov4->doi); | ||
236 | break; | ||
237 | } | ||
238 | audit_log_format(audit_buf, " res=%u", result == 0 ? 1 : 0); | ||
239 | audit_log_end(audit_buf); | ||
240 | } | ||
241 | } | ||
242 | |||
159 | /* | 243 | /* |
160 | * Domain Hash Table Functions | 244 | * Domain Hash Table Functions |
161 | */ | 245 | */ |
@@ -213,50 +297,106 @@ int __init netlbl_domhsh_init(u32 size) | |||
213 | int netlbl_domhsh_add(struct netlbl_dom_map *entry, | 297 | int netlbl_domhsh_add(struct netlbl_dom_map *entry, |
214 | struct netlbl_audit *audit_info) | 298 | struct netlbl_audit *audit_info) |
215 | { | 299 | { |
216 | int ret_val; | 300 | int ret_val = 0; |
217 | u32 bkt; | 301 | struct netlbl_dom_map *entry_old; |
218 | struct audit_buffer *audit_buf; | 302 | struct netlbl_af4list *iter4; |
219 | 303 | struct netlbl_af4list *tmp4; | |
220 | entry->valid = 1; | 304 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
221 | INIT_RCU_HEAD(&entry->rcu); | 305 | struct netlbl_af6list *iter6; |
306 | struct netlbl_af6list *tmp6; | ||
307 | #endif /* IPv6 */ | ||
222 | 308 | ||
223 | rcu_read_lock(); | 309 | rcu_read_lock(); |
310 | |||
224 | spin_lock(&netlbl_domhsh_lock); | 311 | spin_lock(&netlbl_domhsh_lock); |
225 | if (entry->domain != NULL) { | 312 | if (entry->domain != NULL) |
226 | bkt = netlbl_domhsh_hash(entry->domain); | 313 | entry_old = netlbl_domhsh_search(entry->domain); |
227 | if (netlbl_domhsh_search(entry->domain) == NULL) | 314 | else |
315 | entry_old = netlbl_domhsh_search_def(entry->domain); | ||
316 | if (entry_old == NULL) { | ||
317 | entry->valid = 1; | ||
318 | INIT_RCU_HEAD(&entry->rcu); | ||
319 | |||
320 | if (entry->domain != NULL) { | ||
321 | u32 bkt = netlbl_domhsh_hash(entry->domain); | ||
228 | list_add_tail_rcu(&entry->list, | 322 | list_add_tail_rcu(&entry->list, |
229 | &rcu_dereference(netlbl_domhsh)->tbl[bkt]); | 323 | &rcu_dereference(netlbl_domhsh)->tbl[bkt]); |
230 | else | 324 | } else { |
231 | ret_val = -EEXIST; | 325 | INIT_LIST_HEAD(&entry->list); |
232 | } else { | ||
233 | INIT_LIST_HEAD(&entry->list); | ||
234 | if (rcu_dereference(netlbl_domhsh_def) == NULL) | ||
235 | rcu_assign_pointer(netlbl_domhsh_def, entry); | 326 | rcu_assign_pointer(netlbl_domhsh_def, entry); |
236 | else | ||
237 | ret_val = -EEXIST; | ||
238 | } | ||
239 | spin_unlock(&netlbl_domhsh_lock); | ||
240 | audit_buf = netlbl_audit_start_common(AUDIT_MAC_MAP_ADD, audit_info); | ||
241 | if (audit_buf != NULL) { | ||
242 | audit_log_format(audit_buf, | ||
243 | " nlbl_domain=%s", | ||
244 | entry->domain ? entry->domain : "(default)"); | ||
245 | switch (entry->type) { | ||
246 | case NETLBL_NLTYPE_UNLABELED: | ||
247 | audit_log_format(audit_buf, " nlbl_protocol=unlbl"); | ||
248 | break; | ||
249 | case NETLBL_NLTYPE_CIPSOV4: | ||
250 | audit_log_format(audit_buf, | ||
251 | " nlbl_protocol=cipsov4 cipso_doi=%u", | ||
252 | entry->type_def.cipsov4->doi); | ||
253 | break; | ||
254 | } | 327 | } |
255 | audit_log_format(audit_buf, " res=%u", ret_val == 0 ? 1 : 0); | ||
256 | audit_log_end(audit_buf); | ||
257 | } | ||
258 | rcu_read_unlock(); | ||
259 | 328 | ||
329 | if (entry->type == NETLBL_NLTYPE_ADDRSELECT) { | ||
330 | netlbl_af4list_foreach_rcu(iter4, | ||
331 | &entry->type_def.addrsel->list4) | ||
332 | netlbl_domhsh_audit_add(entry, iter4, NULL, | ||
333 | ret_val, audit_info); | ||
334 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
335 | netlbl_af6list_foreach_rcu(iter6, | ||
336 | &entry->type_def.addrsel->list6) | ||
337 | netlbl_domhsh_audit_add(entry, NULL, iter6, | ||
338 | ret_val, audit_info); | ||
339 | #endif /* IPv6 */ | ||
340 | } else | ||
341 | netlbl_domhsh_audit_add(entry, NULL, NULL, | ||
342 | ret_val, audit_info); | ||
343 | } else if (entry_old->type == NETLBL_NLTYPE_ADDRSELECT && | ||
344 | entry->type == NETLBL_NLTYPE_ADDRSELECT) { | ||
345 | struct list_head *old_list4; | ||
346 | struct list_head *old_list6; | ||
347 | |||
348 | old_list4 = &entry_old->type_def.addrsel->list4; | ||
349 | old_list6 = &entry_old->type_def.addrsel->list6; | ||
350 | |||
351 | /* we only allow the addition of address selectors if all of | ||
352 | * the selectors do not exist in the existing domain map */ | ||
353 | netlbl_af4list_foreach_rcu(iter4, | ||
354 | &entry->type_def.addrsel->list4) | ||
355 | if (netlbl_af4list_search_exact(iter4->addr, | ||
356 | iter4->mask, | ||
357 | old_list4)) { | ||
358 | ret_val = -EEXIST; | ||
359 | goto add_return; | ||
360 | } | ||
361 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
362 | netlbl_af6list_foreach_rcu(iter6, | ||
363 | &entry->type_def.addrsel->list6) | ||
364 | if (netlbl_af6list_search_exact(&iter6->addr, | ||
365 | &iter6->mask, | ||
366 | old_list6)) { | ||
367 | ret_val = -EEXIST; | ||
368 | goto add_return; | ||
369 | } | ||
370 | #endif /* IPv6 */ | ||
371 | |||
372 | netlbl_af4list_foreach_safe(iter4, tmp4, | ||
373 | &entry->type_def.addrsel->list4) { | ||
374 | netlbl_af4list_remove_entry(iter4); | ||
375 | iter4->valid = 1; | ||
376 | ret_val = netlbl_af4list_add(iter4, old_list4); | ||
377 | netlbl_domhsh_audit_add(entry_old, iter4, NULL, | ||
378 | ret_val, audit_info); | ||
379 | if (ret_val != 0) | ||
380 | goto add_return; | ||
381 | } | ||
382 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
383 | netlbl_af6list_foreach_safe(iter6, tmp6, | ||
384 | &entry->type_def.addrsel->list6) { | ||
385 | netlbl_af6list_remove_entry(iter6); | ||
386 | iter6->valid = 1; | ||
387 | ret_val = netlbl_af6list_add(iter6, old_list6); | ||
388 | netlbl_domhsh_audit_add(entry_old, NULL, iter6, | ||
389 | ret_val, audit_info); | ||
390 | if (ret_val != 0) | ||
391 | goto add_return; | ||
392 | } | ||
393 | #endif /* IPv6 */ | ||
394 | } else | ||
395 | ret_val = -EINVAL; | ||
396 | |||
397 | add_return: | ||
398 | spin_unlock(&netlbl_domhsh_lock); | ||
399 | rcu_read_unlock(); | ||
260 | return ret_val; | 400 | return ret_val; |
261 | } | 401 | } |
262 | 402 | ||
@@ -319,7 +459,19 @@ int netlbl_domhsh_remove_entry(struct netlbl_dom_map *entry, | |||
319 | } | 459 | } |
320 | 460 | ||
321 | if (ret_val == 0) { | 461 | if (ret_val == 0) { |
462 | struct netlbl_af4list *iter4; | ||
463 | struct netlbl_domaddr4_map *map4; | ||
464 | |||
322 | switch (entry->type) { | 465 | switch (entry->type) { |
466 | case NETLBL_NLTYPE_ADDRSELECT: | ||
467 | netlbl_af4list_foreach_rcu(iter4, | ||
468 | &entry->type_def.addrsel->list4) { | ||
469 | map4 = netlbl_domhsh_addr4_entry(iter4); | ||
470 | cipso_v4_doi_putdef(map4->type_def.cipsov4); | ||
471 | } | ||
472 | /* no need to check the IPv6 list since we currently | ||
473 | * support only unlabeled protocols for IPv6 */ | ||
474 | break; | ||
323 | case NETLBL_NLTYPE_CIPSOV4: | 475 | case NETLBL_NLTYPE_CIPSOV4: |
324 | cipso_v4_doi_putdef(entry->type_def.cipsov4); | 476 | cipso_v4_doi_putdef(entry->type_def.cipsov4); |
325 | break; | 477 | break; |
@@ -388,6 +540,70 @@ struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain) | |||
388 | } | 540 | } |
389 | 541 | ||
390 | /** | 542 | /** |
543 | * netlbl_domhsh_getentry_af4 - Get an entry from the domain hash table | ||
544 | * @domain: the domain name to search for | ||
545 | * @addr: the IP address to search for | ||
546 | * | ||
547 | * Description: | ||
548 | * Look through the domain hash table searching for an entry to match @domain | ||
549 | * and @addr, return a pointer to a copy of the entry or NULL. The caller is | ||
550 | * responsible for ensuring that rcu_read_[un]lock() is called. | ||
551 | * | ||
552 | */ | ||
553 | struct netlbl_domaddr4_map *netlbl_domhsh_getentry_af4(const char *domain, | ||
554 | __be32 addr) | ||
555 | { | ||
556 | struct netlbl_dom_map *dom_iter; | ||
557 | struct netlbl_af4list *addr_iter; | ||
558 | |||
559 | dom_iter = netlbl_domhsh_search_def(domain); | ||
560 | if (dom_iter == NULL) | ||
561 | return NULL; | ||
562 | if (dom_iter->type != NETLBL_NLTYPE_ADDRSELECT) | ||
563 | return NULL; | ||
564 | |||
565 | addr_iter = netlbl_af4list_search(addr, | ||
566 | &dom_iter->type_def.addrsel->list4); | ||
567 | if (addr_iter == NULL) | ||
568 | return NULL; | ||
569 | |||
570 | return netlbl_domhsh_addr4_entry(addr_iter); | ||
571 | } | ||
572 | |||
573 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
574 | /** | ||
575 | * netlbl_domhsh_getentry_af6 - Get an entry from the domain hash table | ||
576 | * @domain: the domain name to search for | ||
577 | * @addr: the IP address to search for | ||
578 | * | ||
579 | * Description: | ||
580 | * Look through the domain hash table searching for an entry to match @domain | ||
581 | * and @addr, return a pointer to a copy of the entry or NULL. The caller is | ||
582 | * responsible for ensuring that rcu_read_[un]lock() is called. | ||
583 | * | ||
584 | */ | ||
585 | struct netlbl_domaddr6_map *netlbl_domhsh_getentry_af6(const char *domain, | ||
586 | const struct in6_addr *addr) | ||
587 | { | ||
588 | struct netlbl_dom_map *dom_iter; | ||
589 | struct netlbl_af6list *addr_iter; | ||
590 | |||
591 | dom_iter = netlbl_domhsh_search_def(domain); | ||
592 | if (dom_iter == NULL) | ||
593 | return NULL; | ||
594 | if (dom_iter->type != NETLBL_NLTYPE_ADDRSELECT) | ||
595 | return NULL; | ||
596 | |||
597 | addr_iter = netlbl_af6list_search(addr, | ||
598 | &dom_iter->type_def.addrsel->list6); | ||
599 | if (addr_iter == NULL) | ||
600 | return NULL; | ||
601 | |||
602 | return netlbl_domhsh_addr6_entry(addr_iter); | ||
603 | } | ||
604 | #endif /* IPv6 */ | ||
605 | |||
606 | /** | ||
391 | * netlbl_domhsh_walk - Iterate through the domain mapping hash table | 607 | * netlbl_domhsh_walk - Iterate through the domain mapping hash table |
392 | * @skip_bkt: the number of buckets to skip at the start | 608 | * @skip_bkt: the number of buckets to skip at the start |
393 | * @skip_chain: the number of entries to skip in the first iterated bucket | 609 | * @skip_chain: the number of entries to skip in the first iterated bucket |
diff --git a/net/netlabel/netlabel_domainhash.h b/net/netlabel/netlabel_domainhash.h index afcc41a7432d..bfcb6763a1a1 100644 --- a/net/netlabel/netlabel_domainhash.h +++ b/net/netlabel/netlabel_domainhash.h | |||
@@ -11,7 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | /* | 13 | /* |
14 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 | 14 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008 |
15 | * | 15 | * |
16 | * This program is free software; you can redistribute it and/or modify | 16 | * This program is free software; you can redistribute it and/or modify |
17 | * it under the terms of the GNU General Public License as published by | 17 | * it under the terms of the GNU General Public License as published by |
@@ -36,16 +36,43 @@ | |||
36 | #include <linux/rcupdate.h> | 36 | #include <linux/rcupdate.h> |
37 | #include <linux/list.h> | 37 | #include <linux/list.h> |
38 | 38 | ||
39 | #include "netlabel_addrlist.h" | ||
40 | |||
39 | /* Domain hash table size */ | 41 | /* Domain hash table size */ |
40 | /* XXX - currently this number is an uneducated guess */ | 42 | /* XXX - currently this number is an uneducated guess */ |
41 | #define NETLBL_DOMHSH_BITSIZE 7 | 43 | #define NETLBL_DOMHSH_BITSIZE 7 |
42 | 44 | ||
43 | /* Domain mapping definition struct */ | 45 | /* Domain mapping definition structures */ |
46 | #define netlbl_domhsh_addr4_entry(iter) \ | ||
47 | container_of(iter, struct netlbl_domaddr4_map, list) | ||
48 | struct netlbl_domaddr4_map { | ||
49 | u32 type; | ||
50 | union { | ||
51 | struct cipso_v4_doi *cipsov4; | ||
52 | } type_def; | ||
53 | |||
54 | struct netlbl_af4list list; | ||
55 | }; | ||
56 | #define netlbl_domhsh_addr6_entry(iter) \ | ||
57 | container_of(iter, struct netlbl_domaddr6_map, list) | ||
58 | struct netlbl_domaddr6_map { | ||
59 | u32 type; | ||
60 | |||
61 | /* NOTE: no 'type_def' union needed at present since we don't currently | ||
62 | * support any IPv6 labeling protocols */ | ||
63 | |||
64 | struct netlbl_af6list list; | ||
65 | }; | ||
66 | struct netlbl_domaddr_map { | ||
67 | struct list_head list4; | ||
68 | struct list_head list6; | ||
69 | }; | ||
44 | struct netlbl_dom_map { | 70 | struct netlbl_dom_map { |
45 | char *domain; | 71 | char *domain; |
46 | u32 type; | 72 | u32 type; |
47 | union { | 73 | union { |
48 | struct cipso_v4_doi *cipsov4; | 74 | struct cipso_v4_doi *cipsov4; |
75 | struct netlbl_domaddr_map *addrsel; | ||
49 | } type_def; | 76 | } type_def; |
50 | 77 | ||
51 | u32 valid; | 78 | u32 valid; |
@@ -66,9 +93,16 @@ int netlbl_domhsh_remove_entry(struct netlbl_dom_map *entry, | |||
66 | int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info); | 93 | int netlbl_domhsh_remove(const char *domain, struct netlbl_audit *audit_info); |
67 | int netlbl_domhsh_remove_default(struct netlbl_audit *audit_info); | 94 | int netlbl_domhsh_remove_default(struct netlbl_audit *audit_info); |
68 | struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain); | 95 | struct netlbl_dom_map *netlbl_domhsh_getentry(const char *domain); |
96 | struct netlbl_domaddr4_map *netlbl_domhsh_getentry_af4(const char *domain, | ||
97 | __be32 addr); | ||
69 | int netlbl_domhsh_walk(u32 *skip_bkt, | 98 | int netlbl_domhsh_walk(u32 *skip_bkt, |
70 | u32 *skip_chain, | 99 | u32 *skip_chain, |
71 | int (*callback) (struct netlbl_dom_map *entry, void *arg), | 100 | int (*callback) (struct netlbl_dom_map *entry, void *arg), |
72 | void *cb_arg); | 101 | void *cb_arg); |
73 | 102 | ||
103 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
104 | struct netlbl_domaddr6_map *netlbl_domhsh_getentry_af6(const char *domain, | ||
105 | const struct in6_addr *addr); | ||
106 | #endif /* IPv6 */ | ||
107 | |||
74 | #endif | 108 | #endif |
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 7d8ecea93914..8b820dc98060 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c | |||
@@ -419,7 +419,9 @@ int netlbl_enabled(void) | |||
419 | * Attach the correct label to the given socket using the security attributes | 419 | * Attach the correct label to the given socket using the security attributes |
420 | * specified in @secattr. This function requires exclusive access to @sk, | 420 | * specified in @secattr. This function requires exclusive access to @sk, |
421 | * which means it either needs to be in the process of being created or locked. | 421 | * which means it either needs to be in the process of being created or locked. |
422 | * Returns zero on success, negative values on failure. | 422 | * Returns zero on success, -EDESTADDRREQ if the domain is configured to use |
423 | * network address selectors (can't blindly label the socket), and negative | ||
424 | * values on all other failures. | ||
423 | * | 425 | * |
424 | */ | 426 | */ |
425 | int netlbl_sock_setattr(struct sock *sk, | 427 | int netlbl_sock_setattr(struct sock *sk, |
@@ -433,6 +435,9 @@ int netlbl_sock_setattr(struct sock *sk, | |||
433 | if (dom_entry == NULL) | 435 | if (dom_entry == NULL) |
434 | goto socket_setattr_return; | 436 | goto socket_setattr_return; |
435 | switch (dom_entry->type) { | 437 | switch (dom_entry->type) { |
438 | case NETLBL_NLTYPE_ADDRSELECT: | ||
439 | ret_val = -EDESTADDRREQ; | ||
440 | break; | ||
436 | case NETLBL_NLTYPE_CIPSOV4: | 441 | case NETLBL_NLTYPE_CIPSOV4: |
437 | ret_val = cipso_v4_sock_setattr(sk, | 442 | ret_val = cipso_v4_sock_setattr(sk, |
438 | dom_entry->type_def.cipsov4, | 443 | dom_entry->type_def.cipsov4, |
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index c4e18c7bc0c1..ee769ecaa13c 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c | |||
@@ -10,7 +10,7 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | /* | 12 | /* |
13 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006 | 13 | * (c) Copyright Hewlett-Packard Development Company, L.P., 2006, 2008 |
14 | * | 14 | * |
15 | * This program is free software; you can redistribute it and/or modify | 15 | * This program is free software; you can redistribute it and/or modify |
16 | * it under the terms of the GNU General Public License as published by | 16 | * it under the terms of the GNU General Public License as published by |
@@ -32,9 +32,13 @@ | |||
32 | #include <linux/socket.h> | 32 | #include <linux/socket.h> |
33 | #include <linux/string.h> | 33 | #include <linux/string.h> |
34 | #include <linux/skbuff.h> | 34 | #include <linux/skbuff.h> |
35 | #include <linux/in.h> | ||
36 | #include <linux/in6.h> | ||
35 | #include <net/sock.h> | 37 | #include <net/sock.h> |
36 | #include <net/netlink.h> | 38 | #include <net/netlink.h> |
37 | #include <net/genetlink.h> | 39 | #include <net/genetlink.h> |
40 | #include <net/ip.h> | ||
41 | #include <net/ipv6.h> | ||
38 | #include <net/netlabel.h> | 42 | #include <net/netlabel.h> |
39 | #include <net/cipso_ipv4.h> | 43 | #include <net/cipso_ipv4.h> |
40 | #include <asm/atomic.h> | 44 | #include <asm/atomic.h> |
@@ -71,80 +75,337 @@ static const struct nla_policy netlbl_mgmt_genl_policy[NLBL_MGMT_A_MAX + 1] = { | |||
71 | }; | 75 | }; |
72 | 76 | ||
73 | /* | 77 | /* |
74 | * NetLabel Command Handlers | 78 | * Helper Functions |
75 | */ | 79 | */ |
76 | 80 | ||
77 | /** | 81 | /** |
78 | * netlbl_mgmt_add - Handle an ADD message | 82 | * netlbl_mgmt_add - Handle an ADD message |
79 | * @skb: the NETLINK buffer | ||
80 | * @info: the Generic NETLINK info block | 83 | * @info: the Generic NETLINK info block |
84 | * @audit_info: NetLabel audit information | ||
81 | * | 85 | * |
82 | * Description: | 86 | * Description: |
83 | * Process a user generated ADD message and add the domains from the message | 87 | * Helper function for the ADD and ADDDEF messages to add the domain mappings |
84 | * to the hash table. See netlabel.h for a description of the message format. | 88 | * from the message to the hash table. See netlabel.h for a description of the |
85 | * Returns zero on success, negative values on failure. | 89 | * message format. Returns zero on success, negative values on failure. |
86 | * | 90 | * |
87 | */ | 91 | */ |
88 | static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info) | 92 | static int netlbl_mgmt_add_common(struct genl_info *info, |
93 | struct netlbl_audit *audit_info) | ||
89 | { | 94 | { |
90 | int ret_val = -EINVAL; | 95 | int ret_val = -EINVAL; |
91 | struct netlbl_dom_map *entry = NULL; | 96 | struct netlbl_dom_map *entry = NULL; |
92 | size_t tmp_size; | 97 | struct netlbl_domaddr_map *addrmap = NULL; |
98 | struct cipso_v4_doi *cipsov4 = NULL; | ||
93 | u32 tmp_val; | 99 | u32 tmp_val; |
94 | struct netlbl_audit audit_info; | ||
95 | |||
96 | if (!info->attrs[NLBL_MGMT_A_DOMAIN] || | ||
97 | !info->attrs[NLBL_MGMT_A_PROTOCOL]) | ||
98 | goto add_failure; | ||
99 | |||
100 | netlbl_netlink_auditinfo(skb, &audit_info); | ||
101 | 100 | ||
102 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); | 101 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
103 | if (entry == NULL) { | 102 | if (entry == NULL) { |
104 | ret_val = -ENOMEM; | 103 | ret_val = -ENOMEM; |
105 | goto add_failure; | 104 | goto add_failure; |
106 | } | 105 | } |
107 | tmp_size = nla_len(info->attrs[NLBL_MGMT_A_DOMAIN]); | ||
108 | entry->domain = kmalloc(tmp_size, GFP_KERNEL); | ||
109 | if (entry->domain == NULL) { | ||
110 | ret_val = -ENOMEM; | ||
111 | goto add_failure; | ||
112 | } | ||
113 | entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]); | 106 | entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]); |
114 | nla_strlcpy(entry->domain, info->attrs[NLBL_MGMT_A_DOMAIN], tmp_size); | 107 | if (info->attrs[NLBL_MGMT_A_DOMAIN]) { |
108 | size_t tmp_size = nla_len(info->attrs[NLBL_MGMT_A_DOMAIN]); | ||
109 | entry->domain = kmalloc(tmp_size, GFP_KERNEL); | ||
110 | if (entry->domain == NULL) { | ||
111 | ret_val = -ENOMEM; | ||
112 | goto add_failure; | ||
113 | } | ||
114 | nla_strlcpy(entry->domain, | ||
115 | info->attrs[NLBL_MGMT_A_DOMAIN], tmp_size); | ||
116 | } | ||
117 | |||
118 | /* NOTE: internally we allow/use a entry->type value of | ||
119 | * NETLBL_NLTYPE_ADDRSELECT but we don't currently allow users | ||
120 | * to pass that as a protocol value because we need to know the | ||
121 | * "real" protocol */ | ||
115 | 122 | ||
116 | switch (entry->type) { | 123 | switch (entry->type) { |
117 | case NETLBL_NLTYPE_UNLABELED: | 124 | case NETLBL_NLTYPE_UNLABELED: |
118 | ret_val = netlbl_domhsh_add(entry, &audit_info); | ||
119 | break; | 125 | break; |
120 | case NETLBL_NLTYPE_CIPSOV4: | 126 | case NETLBL_NLTYPE_CIPSOV4: |
121 | if (!info->attrs[NLBL_MGMT_A_CV4DOI]) | 127 | if (!info->attrs[NLBL_MGMT_A_CV4DOI]) |
122 | goto add_failure; | 128 | goto add_failure; |
123 | 129 | ||
124 | tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]); | 130 | tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]); |
125 | entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val); | 131 | cipsov4 = cipso_v4_doi_getdef(tmp_val); |
126 | if (entry->type_def.cipsov4 == NULL) | 132 | if (cipsov4 == NULL) |
127 | goto add_failure; | 133 | goto add_failure; |
128 | ret_val = netlbl_domhsh_add(entry, &audit_info); | 134 | entry->type_def.cipsov4 = cipsov4; |
129 | if (ret_val != 0) | ||
130 | cipso_v4_doi_putdef(entry->type_def.cipsov4); | ||
131 | break; | 135 | break; |
132 | default: | 136 | default: |
133 | goto add_failure; | 137 | goto add_failure; |
134 | } | 138 | } |
139 | |||
140 | if (info->attrs[NLBL_MGMT_A_IPV4ADDR]) { | ||
141 | struct in_addr *addr; | ||
142 | struct in_addr *mask; | ||
143 | struct netlbl_domaddr4_map *map; | ||
144 | |||
145 | addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL); | ||
146 | if (addrmap == NULL) { | ||
147 | ret_val = -ENOMEM; | ||
148 | goto add_failure; | ||
149 | } | ||
150 | INIT_LIST_HEAD(&addrmap->list4); | ||
151 | INIT_LIST_HEAD(&addrmap->list6); | ||
152 | |||
153 | if (nla_len(info->attrs[NLBL_MGMT_A_IPV4ADDR]) != | ||
154 | sizeof(struct in_addr)) { | ||
155 | ret_val = -EINVAL; | ||
156 | goto add_failure; | ||
157 | } | ||
158 | if (nla_len(info->attrs[NLBL_MGMT_A_IPV4MASK]) != | ||
159 | sizeof(struct in_addr)) { | ||
160 | ret_val = -EINVAL; | ||
161 | goto add_failure; | ||
162 | } | ||
163 | addr = nla_data(info->attrs[NLBL_MGMT_A_IPV4ADDR]); | ||
164 | mask = nla_data(info->attrs[NLBL_MGMT_A_IPV4MASK]); | ||
165 | |||
166 | map = kzalloc(sizeof(*map), GFP_KERNEL); | ||
167 | if (map == NULL) { | ||
168 | ret_val = -ENOMEM; | ||
169 | goto add_failure; | ||
170 | } | ||
171 | map->list.addr = addr->s_addr & mask->s_addr; | ||
172 | map->list.mask = mask->s_addr; | ||
173 | map->list.valid = 1; | ||
174 | map->type = entry->type; | ||
175 | if (cipsov4) | ||
176 | map->type_def.cipsov4 = cipsov4; | ||
177 | |||
178 | ret_val = netlbl_af4list_add(&map->list, &addrmap->list4); | ||
179 | if (ret_val != 0) { | ||
180 | kfree(map); | ||
181 | goto add_failure; | ||
182 | } | ||
183 | |||
184 | entry->type = NETLBL_NLTYPE_ADDRSELECT; | ||
185 | entry->type_def.addrsel = addrmap; | ||
186 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
187 | } else if (info->attrs[NLBL_MGMT_A_IPV6ADDR]) { | ||
188 | struct in6_addr *addr; | ||
189 | struct in6_addr *mask; | ||
190 | struct netlbl_domaddr6_map *map; | ||
191 | |||
192 | addrmap = kzalloc(sizeof(*addrmap), GFP_KERNEL); | ||
193 | if (addrmap == NULL) { | ||
194 | ret_val = -ENOMEM; | ||
195 | goto add_failure; | ||
196 | } | ||
197 | INIT_LIST_HEAD(&addrmap->list4); | ||
198 | INIT_LIST_HEAD(&addrmap->list6); | ||
199 | |||
200 | if (nla_len(info->attrs[NLBL_MGMT_A_IPV6ADDR]) != | ||
201 | sizeof(struct in6_addr)) { | ||
202 | ret_val = -EINVAL; | ||
203 | goto add_failure; | ||
204 | } | ||
205 | if (nla_len(info->attrs[NLBL_MGMT_A_IPV6MASK]) != | ||
206 | sizeof(struct in6_addr)) { | ||
207 | ret_val = -EINVAL; | ||
208 | goto add_failure; | ||
209 | } | ||
210 | addr = nla_data(info->attrs[NLBL_MGMT_A_IPV6ADDR]); | ||
211 | mask = nla_data(info->attrs[NLBL_MGMT_A_IPV6MASK]); | ||
212 | |||
213 | map = kzalloc(sizeof(*map), GFP_KERNEL); | ||
214 | if (map == NULL) { | ||
215 | ret_val = -ENOMEM; | ||
216 | goto add_failure; | ||
217 | } | ||
218 | ipv6_addr_copy(&map->list.addr, addr); | ||
219 | map->list.addr.s6_addr32[0] &= mask->s6_addr32[0]; | ||
220 | map->list.addr.s6_addr32[1] &= mask->s6_addr32[1]; | ||
221 | map->list.addr.s6_addr32[2] &= mask->s6_addr32[2]; | ||
222 | map->list.addr.s6_addr32[3] &= mask->s6_addr32[3]; | ||
223 | ipv6_addr_copy(&map->list.mask, mask); | ||
224 | map->list.valid = 1; | ||
225 | map->type = entry->type; | ||
226 | |||
227 | ret_val = netlbl_af6list_add(&map->list, &addrmap->list6); | ||
228 | if (ret_val != 0) { | ||
229 | kfree(map); | ||
230 | goto add_failure; | ||
231 | } | ||
232 | |||
233 | entry->type = NETLBL_NLTYPE_ADDRSELECT; | ||
234 | entry->type_def.addrsel = addrmap; | ||
235 | #endif /* IPv6 */ | ||
236 | } | ||
237 | |||
238 | ret_val = netlbl_domhsh_add(entry, audit_info); | ||
135 | if (ret_val != 0) | 239 | if (ret_val != 0) |
136 | goto add_failure; | 240 | goto add_failure; |
137 | 241 | ||
138 | return 0; | 242 | return 0; |
139 | 243 | ||
140 | add_failure: | 244 | add_failure: |
245 | if (cipsov4) | ||
246 | cipso_v4_doi_putdef(cipsov4); | ||
141 | if (entry) | 247 | if (entry) |
142 | kfree(entry->domain); | 248 | kfree(entry->domain); |
249 | kfree(addrmap); | ||
143 | kfree(entry); | 250 | kfree(entry); |
144 | return ret_val; | 251 | return ret_val; |
145 | } | 252 | } |
146 | 253 | ||
147 | /** | 254 | /** |
255 | * netlbl_mgmt_listentry - List a NetLabel/LSM domain map entry | ||
256 | * @skb: the NETLINK buffer | ||
257 | * @entry: the map entry | ||
258 | * | ||
259 | * Description: | ||
260 | * This function is a helper function used by the LISTALL and LISTDEF command | ||
261 | * handlers. The caller is responsibile for ensuring that the RCU read lock | ||
262 | * is held. Returns zero on success, negative values on failure. | ||
263 | * | ||
264 | */ | ||
265 | static int netlbl_mgmt_listentry(struct sk_buff *skb, | ||
266 | struct netlbl_dom_map *entry) | ||
267 | { | ||
268 | int ret_val; | ||
269 | struct nlattr *nla_a; | ||
270 | struct nlattr *nla_b; | ||
271 | struct netlbl_af4list *iter4; | ||
272 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
273 | struct netlbl_af6list *iter6; | ||
274 | #endif | ||
275 | |||
276 | if (entry->domain != NULL) { | ||
277 | ret_val = nla_put_string(skb, | ||
278 | NLBL_MGMT_A_DOMAIN, entry->domain); | ||
279 | if (ret_val != 0) | ||
280 | return ret_val; | ||
281 | } | ||
282 | |||
283 | switch (entry->type) { | ||
284 | case NETLBL_NLTYPE_ADDRSELECT: | ||
285 | nla_a = nla_nest_start(skb, NLBL_MGMT_A_SELECTORLIST); | ||
286 | if (nla_a == NULL) | ||
287 | return -ENOMEM; | ||
288 | |||
289 | netlbl_af4list_foreach_rcu(iter4, | ||
290 | &entry->type_def.addrsel->list4) { | ||
291 | struct netlbl_domaddr4_map *map4; | ||
292 | struct in_addr addr_struct; | ||
293 | |||
294 | nla_b = nla_nest_start(skb, NLBL_MGMT_A_ADDRSELECTOR); | ||
295 | if (nla_b == NULL) | ||
296 | return -ENOMEM; | ||
297 | |||
298 | addr_struct.s_addr = iter4->addr; | ||
299 | ret_val = nla_put(skb, NLBL_MGMT_A_IPV4ADDR, | ||
300 | sizeof(struct in_addr), | ||
301 | &addr_struct); | ||
302 | if (ret_val != 0) | ||
303 | return ret_val; | ||
304 | addr_struct.s_addr = iter4->mask; | ||
305 | ret_val = nla_put(skb, NLBL_MGMT_A_IPV4MASK, | ||
306 | sizeof(struct in_addr), | ||
307 | &addr_struct); | ||
308 | if (ret_val != 0) | ||
309 | return ret_val; | ||
310 | map4 = netlbl_domhsh_addr4_entry(iter4); | ||
311 | ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, | ||
312 | map4->type); | ||
313 | if (ret_val != 0) | ||
314 | return ret_val; | ||
315 | switch (map4->type) { | ||
316 | case NETLBL_NLTYPE_CIPSOV4: | ||
317 | ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI, | ||
318 | map4->type_def.cipsov4->doi); | ||
319 | if (ret_val != 0) | ||
320 | return ret_val; | ||
321 | break; | ||
322 | } | ||
323 | |||
324 | nla_nest_end(skb, nla_b); | ||
325 | } | ||
326 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
327 | netlbl_af6list_foreach_rcu(iter6, | ||
328 | &entry->type_def.addrsel->list6) { | ||
329 | struct netlbl_domaddr6_map *map6; | ||
330 | |||
331 | nla_b = nla_nest_start(skb, NLBL_MGMT_A_ADDRSELECTOR); | ||
332 | if (nla_b == NULL) | ||
333 | return -ENOMEM; | ||
334 | |||
335 | ret_val = nla_put(skb, NLBL_MGMT_A_IPV6ADDR, | ||
336 | sizeof(struct in6_addr), | ||
337 | &iter6->addr); | ||
338 | if (ret_val != 0) | ||
339 | return ret_val; | ||
340 | ret_val = nla_put(skb, NLBL_MGMT_A_IPV6MASK, | ||
341 | sizeof(struct in6_addr), | ||
342 | &iter6->mask); | ||
343 | if (ret_val != 0) | ||
344 | return ret_val; | ||
345 | map6 = netlbl_domhsh_addr6_entry(iter6); | ||
346 | ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, | ||
347 | map6->type); | ||
348 | if (ret_val != 0) | ||
349 | return ret_val; | ||
350 | |||
351 | nla_nest_end(skb, nla_b); | ||
352 | } | ||
353 | #endif /* IPv6 */ | ||
354 | |||
355 | nla_nest_end(skb, nla_a); | ||
356 | break; | ||
357 | case NETLBL_NLTYPE_UNLABELED: | ||
358 | ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, entry->type); | ||
359 | break; | ||
360 | case NETLBL_NLTYPE_CIPSOV4: | ||
361 | ret_val = nla_put_u32(skb, NLBL_MGMT_A_PROTOCOL, entry->type); | ||
362 | if (ret_val != 0) | ||
363 | return ret_val; | ||
364 | ret_val = nla_put_u32(skb, NLBL_MGMT_A_CV4DOI, | ||
365 | entry->type_def.cipsov4->doi); | ||
366 | break; | ||
367 | } | ||
368 | |||
369 | return ret_val; | ||
370 | } | ||
371 | |||
372 | /* | ||
373 | * NetLabel Command Handlers | ||
374 | */ | ||
375 | |||
376 | /** | ||
377 | * netlbl_mgmt_add - Handle an ADD message | ||
378 | * @skb: the NETLINK buffer | ||
379 | * @info: the Generic NETLINK info block | ||
380 | * | ||
381 | * Description: | ||
382 | * Process a user generated ADD message and add the domains from the message | ||
383 | * to the hash table. See netlabel.h for a description of the message format. | ||
384 | * Returns zero on success, negative values on failure. | ||
385 | * | ||
386 | */ | ||
387 | static int netlbl_mgmt_add(struct sk_buff *skb, struct genl_info *info) | ||
388 | { | ||
389 | struct netlbl_audit audit_info; | ||
390 | |||
391 | if ((!info->attrs[NLBL_MGMT_A_DOMAIN]) || | ||
392 | (!info->attrs[NLBL_MGMT_A_PROTOCOL]) || | ||
393 | (info->attrs[NLBL_MGMT_A_IPV4ADDR] && | ||
394 | info->attrs[NLBL_MGMT_A_IPV6ADDR]) || | ||
395 | (info->attrs[NLBL_MGMT_A_IPV4MASK] && | ||
396 | info->attrs[NLBL_MGMT_A_IPV6MASK]) || | ||
397 | ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^ | ||
398 | (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) || | ||
399 | ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^ | ||
400 | (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL))) | ||
401 | return -EINVAL; | ||
402 | |||
403 | netlbl_netlink_auditinfo(skb, &audit_info); | ||
404 | |||
405 | return netlbl_mgmt_add_common(info, &audit_info); | ||
406 | } | ||
407 | |||
408 | /** | ||
148 | * netlbl_mgmt_remove - Handle a REMOVE message | 409 | * netlbl_mgmt_remove - Handle a REMOVE message |
149 | * @skb: the NETLINK buffer | 410 | * @skb: the NETLINK buffer |
150 | * @info: the Generic NETLINK info block | 411 | * @info: the Generic NETLINK info block |
@@ -192,23 +453,9 @@ static int netlbl_mgmt_listall_cb(struct netlbl_dom_map *entry, void *arg) | |||
192 | if (data == NULL) | 453 | if (data == NULL) |
193 | goto listall_cb_failure; | 454 | goto listall_cb_failure; |
194 | 455 | ||
195 | ret_val = nla_put_string(cb_arg->skb, | 456 | ret_val = netlbl_mgmt_listentry(cb_arg->skb, entry); |
196 | NLBL_MGMT_A_DOMAIN, | ||
197 | entry->domain); | ||
198 | if (ret_val != 0) | 457 | if (ret_val != 0) |
199 | goto listall_cb_failure; | 458 | goto listall_cb_failure; |
200 | ret_val = nla_put_u32(cb_arg->skb, NLBL_MGMT_A_PROTOCOL, entry->type); | ||
201 | if (ret_val != 0) | ||
202 | goto listall_cb_failure; | ||
203 | switch (entry->type) { | ||
204 | case NETLBL_NLTYPE_CIPSOV4: | ||
205 | ret_val = nla_put_u32(cb_arg->skb, | ||
206 | NLBL_MGMT_A_CV4DOI, | ||
207 | entry->type_def.cipsov4->doi); | ||
208 | if (ret_val != 0) | ||
209 | goto listall_cb_failure; | ||
210 | break; | ||
211 | } | ||
212 | 459 | ||
213 | cb_arg->seq++; | 460 | cb_arg->seq++; |
214 | return genlmsg_end(cb_arg->skb, data); | 461 | return genlmsg_end(cb_arg->skb, data); |
@@ -262,50 +509,22 @@ static int netlbl_mgmt_listall(struct sk_buff *skb, | |||
262 | */ | 509 | */ |
263 | static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info) | 510 | static int netlbl_mgmt_adddef(struct sk_buff *skb, struct genl_info *info) |
264 | { | 511 | { |
265 | int ret_val = -EINVAL; | ||
266 | struct netlbl_dom_map *entry = NULL; | ||
267 | u32 tmp_val; | ||
268 | struct netlbl_audit audit_info; | 512 | struct netlbl_audit audit_info; |
269 | 513 | ||
270 | if (!info->attrs[NLBL_MGMT_A_PROTOCOL]) | 514 | if ((!info->attrs[NLBL_MGMT_A_PROTOCOL]) || |
271 | goto adddef_failure; | 515 | (info->attrs[NLBL_MGMT_A_IPV4ADDR] && |
516 | info->attrs[NLBL_MGMT_A_IPV6ADDR]) || | ||
517 | (info->attrs[NLBL_MGMT_A_IPV4MASK] && | ||
518 | info->attrs[NLBL_MGMT_A_IPV6MASK]) || | ||
519 | ((info->attrs[NLBL_MGMT_A_IPV4ADDR] != NULL) ^ | ||
520 | (info->attrs[NLBL_MGMT_A_IPV4MASK] != NULL)) || | ||
521 | ((info->attrs[NLBL_MGMT_A_IPV6ADDR] != NULL) ^ | ||
522 | (info->attrs[NLBL_MGMT_A_IPV6MASK] != NULL))) | ||
523 | return -EINVAL; | ||
272 | 524 | ||
273 | netlbl_netlink_auditinfo(skb, &audit_info); | 525 | netlbl_netlink_auditinfo(skb, &audit_info); |
274 | 526 | ||
275 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); | 527 | return netlbl_mgmt_add_common(info, &audit_info); |
276 | if (entry == NULL) { | ||
277 | ret_val = -ENOMEM; | ||
278 | goto adddef_failure; | ||
279 | } | ||
280 | entry->type = nla_get_u32(info->attrs[NLBL_MGMT_A_PROTOCOL]); | ||
281 | |||
282 | switch (entry->type) { | ||
283 | case NETLBL_NLTYPE_UNLABELED: | ||
284 | ret_val = netlbl_domhsh_add_default(entry, &audit_info); | ||
285 | break; | ||
286 | case NETLBL_NLTYPE_CIPSOV4: | ||
287 | if (!info->attrs[NLBL_MGMT_A_CV4DOI]) | ||
288 | goto adddef_failure; | ||
289 | |||
290 | tmp_val = nla_get_u32(info->attrs[NLBL_MGMT_A_CV4DOI]); | ||
291 | entry->type_def.cipsov4 = cipso_v4_doi_getdef(tmp_val); | ||
292 | if (entry->type_def.cipsov4 == NULL) | ||
293 | goto adddef_failure; | ||
294 | ret_val = netlbl_domhsh_add_default(entry, &audit_info); | ||
295 | if (ret_val != 0) | ||
296 | cipso_v4_doi_putdef(entry->type_def.cipsov4); | ||
297 | break; | ||
298 | default: | ||
299 | goto adddef_failure; | ||
300 | } | ||
301 | if (ret_val != 0) | ||
302 | goto adddef_failure; | ||
303 | |||
304 | return 0; | ||
305 | |||
306 | adddef_failure: | ||
307 | kfree(entry); | ||
308 | return ret_val; | ||
309 | } | 528 | } |
310 | 529 | ||
311 | /** | 530 | /** |
@@ -359,19 +578,10 @@ static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info) | |||
359 | ret_val = -ENOENT; | 578 | ret_val = -ENOENT; |
360 | goto listdef_failure_lock; | 579 | goto listdef_failure_lock; |
361 | } | 580 | } |
362 | ret_val = nla_put_u32(ans_skb, NLBL_MGMT_A_PROTOCOL, entry->type); | 581 | ret_val = netlbl_mgmt_listentry(ans_skb, entry); |
363 | if (ret_val != 0) | ||
364 | goto listdef_failure_lock; | ||
365 | switch (entry->type) { | ||
366 | case NETLBL_NLTYPE_CIPSOV4: | ||
367 | ret_val = nla_put_u32(ans_skb, | ||
368 | NLBL_MGMT_A_CV4DOI, | ||
369 | entry->type_def.cipsov4->doi); | ||
370 | if (ret_val != 0) | ||
371 | goto listdef_failure_lock; | ||
372 | break; | ||
373 | } | ||
374 | rcu_read_unlock(); | 582 | rcu_read_unlock(); |
583 | if (ret_val != 0) | ||
584 | goto listdef_failure; | ||
375 | 585 | ||
376 | genlmsg_end(ans_skb, data); | 586 | genlmsg_end(ans_skb, data); |
377 | return genlmsg_reply(ans_skb, info); | 587 | return genlmsg_reply(ans_skb, info); |
diff --git a/net/netlabel/netlabel_mgmt.h b/net/netlabel/netlabel_mgmt.h index a43bff169d6b..05d96431f819 100644 --- a/net/netlabel/netlabel_mgmt.h +++ b/net/netlabel/netlabel_mgmt.h | |||
@@ -45,6 +45,16 @@ | |||
45 | * NLBL_MGMT_A_DOMAIN | 45 | * NLBL_MGMT_A_DOMAIN |
46 | * NLBL_MGMT_A_PROTOCOL | 46 | * NLBL_MGMT_A_PROTOCOL |
47 | * | 47 | * |
48 | * If IPv4 is specified the following attributes are required: | ||
49 | * | ||
50 | * NLBL_MGMT_A_IPV4ADDR | ||
51 | * NLBL_MGMT_A_IPV4MASK | ||
52 | * | ||
53 | * If IPv6 is specified the following attributes are required: | ||
54 | * | ||
55 | * NLBL_MGMT_A_IPV6ADDR | ||
56 | * NLBL_MGMT_A_IPV6MASK | ||
57 | * | ||
48 | * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required: | 58 | * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required: |
49 | * | 59 | * |
50 | * NLBL_MGMT_A_CV4DOI | 60 | * NLBL_MGMT_A_CV4DOI |
@@ -68,13 +78,24 @@ | |||
68 | * Required attributes: | 78 | * Required attributes: |
69 | * | 79 | * |
70 | * NLBL_MGMT_A_DOMAIN | 80 | * NLBL_MGMT_A_DOMAIN |
81 | * | ||
82 | * If the IP address selectors are not used the following attribute is | ||
83 | * required: | ||
84 | * | ||
71 | * NLBL_MGMT_A_PROTOCOL | 85 | * NLBL_MGMT_A_PROTOCOL |
72 | * | 86 | * |
73 | * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required: | 87 | * If the IP address selectors are used then the following attritbute is |
88 | * required: | ||
89 | * | ||
90 | * NLBL_MGMT_A_SELECTORLIST | ||
91 | * | ||
92 | * If the mapping is using the NETLBL_NLTYPE_CIPSOV4 type then the following | ||
93 | * attributes are required: | ||
74 | * | 94 | * |
75 | * NLBL_MGMT_A_CV4DOI | 95 | * NLBL_MGMT_A_CV4DOI |
76 | * | 96 | * |
77 | * If using NETLBL_NLTYPE_UNLABELED no other attributes are required. | 97 | * If the mapping is using the NETLBL_NLTYPE_UNLABELED type no other |
98 | * attributes are required. | ||
78 | * | 99 | * |
79 | * o ADDDEF: | 100 | * o ADDDEF: |
80 | * Sent by an application to set the default domain mapping for the NetLabel | 101 | * Sent by an application to set the default domain mapping for the NetLabel |
@@ -100,15 +121,23 @@ | |||
100 | * application there is no payload. On success the kernel should send a | 121 | * application there is no payload. On success the kernel should send a |
101 | * response using the following format. | 122 | * response using the following format. |
102 | * | 123 | * |
103 | * Required attributes: | 124 | * If the IP address selectors are not used the following attribute is |
125 | * required: | ||
104 | * | 126 | * |
105 | * NLBL_MGMT_A_PROTOCOL | 127 | * NLBL_MGMT_A_PROTOCOL |
106 | * | 128 | * |
107 | * If using NETLBL_NLTYPE_CIPSOV4 the following attributes are required: | 129 | * If the IP address selectors are used then the following attritbute is |
130 | * required: | ||
131 | * | ||
132 | * NLBL_MGMT_A_SELECTORLIST | ||
133 | * | ||
134 | * If the mapping is using the NETLBL_NLTYPE_CIPSOV4 type then the following | ||
135 | * attributes are required: | ||
108 | * | 136 | * |
109 | * NLBL_MGMT_A_CV4DOI | 137 | * NLBL_MGMT_A_CV4DOI |
110 | * | 138 | * |
111 | * If using NETLBL_NLTYPE_UNLABELED no other attributes are required. | 139 | * If the mapping is using the NETLBL_NLTYPE_UNLABELED type no other |
140 | * attributes are required. | ||
112 | * | 141 | * |
113 | * o PROTOCOLS: | 142 | * o PROTOCOLS: |
114 | * Sent by an application to request a list of configured NetLabel protocols | 143 | * Sent by an application to request a list of configured NetLabel protocols |
@@ -162,6 +191,26 @@ enum { | |||
162 | NLBL_MGMT_A_CV4DOI, | 191 | NLBL_MGMT_A_CV4DOI, |
163 | /* (NLA_U32) | 192 | /* (NLA_U32) |
164 | * the CIPSOv4 DOI value */ | 193 | * the CIPSOv4 DOI value */ |
194 | NLBL_MGMT_A_IPV6ADDR, | ||
195 | /* (NLA_BINARY, struct in6_addr) | ||
196 | * an IPv6 address */ | ||
197 | NLBL_MGMT_A_IPV6MASK, | ||
198 | /* (NLA_BINARY, struct in6_addr) | ||
199 | * an IPv6 address mask */ | ||
200 | NLBL_MGMT_A_IPV4ADDR, | ||
201 | /* (NLA_BINARY, struct in_addr) | ||
202 | * an IPv4 address */ | ||
203 | NLBL_MGMT_A_IPV4MASK, | ||
204 | /* (NLA_BINARY, struct in_addr) | ||
205 | * and IPv4 address mask */ | ||
206 | NLBL_MGMT_A_ADDRSELECTOR, | ||
207 | /* (NLA_NESTED) | ||
208 | * an IP address selector, must contain an address, mask, and protocol | ||
209 | * attribute plus any protocol specific attributes */ | ||
210 | NLBL_MGMT_A_SELECTORLIST, | ||
211 | /* (NLA_NESTED) | ||
212 | * the selector list, there must be at least one | ||
213 | * NLBL_MGMT_A_ADDRSELECTOR attribute */ | ||
165 | __NLBL_MGMT_A_MAX, | 214 | __NLBL_MGMT_A_MAX, |
166 | }; | 215 | }; |
167 | #define NLBL_MGMT_A_MAX (__NLBL_MGMT_A_MAX - 1) | 216 | #define NLBL_MGMT_A_MAX (__NLBL_MGMT_A_MAX - 1) |
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c index ab8131a8e489..e8a5c32b0f10 100644 --- a/net/netlabel/netlabel_unlabeled.c +++ b/net/netlabel/netlabel_unlabeled.c | |||
@@ -146,76 +146,6 @@ static const struct nla_policy netlbl_unlabel_genl_policy[NLBL_UNLABEL_A_MAX + 1 | |||
146 | }; | 146 | }; |
147 | 147 | ||
148 | /* | 148 | /* |
149 | * Audit Helper Functions | ||
150 | */ | ||
151 | |||
152 | /** | ||
153 | * netlbl_unlabel_audit_addr4 - Audit an IPv4 address | ||
154 | * @audit_buf: audit buffer | ||
155 | * @dev: network interface | ||
156 | * @addr: IP address | ||
157 | * @mask: IP address mask | ||
158 | * | ||
159 | * Description: | ||
160 | * Write the IPv4 address and address mask, if necessary, to @audit_buf. | ||
161 | * | ||
162 | */ | ||
163 | static void netlbl_unlabel_audit_addr4(struct audit_buffer *audit_buf, | ||
164 | const char *dev, | ||
165 | __be32 addr, __be32 mask) | ||
166 | { | ||
167 | u32 mask_val = ntohl(mask); | ||
168 | |||
169 | if (dev != NULL) | ||
170 | audit_log_format(audit_buf, " netif=%s", dev); | ||
171 | audit_log_format(audit_buf, " src=" NIPQUAD_FMT, NIPQUAD(addr)); | ||
172 | if (mask_val != 0xffffffff) { | ||
173 | u32 mask_len = 0; | ||
174 | while (mask_val > 0) { | ||
175 | mask_val <<= 1; | ||
176 | mask_len++; | ||
177 | } | ||
178 | audit_log_format(audit_buf, " src_prefixlen=%d", mask_len); | ||
179 | } | ||
180 | } | ||
181 | |||
182 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
183 | /** | ||
184 | * netlbl_unlabel_audit_addr6 - Audit an IPv6 address | ||
185 | * @audit_buf: audit buffer | ||
186 | * @dev: network interface | ||
187 | * @addr: IP address | ||
188 | * @mask: IP address mask | ||
189 | * | ||
190 | * Description: | ||
191 | * Write the IPv6 address and address mask, if necessary, to @audit_buf. | ||
192 | * | ||
193 | */ | ||
194 | static void netlbl_unlabel_audit_addr6(struct audit_buffer *audit_buf, | ||
195 | const char *dev, | ||
196 | const struct in6_addr *addr, | ||
197 | const struct in6_addr *mask) | ||
198 | { | ||
199 | if (dev != NULL) | ||
200 | audit_log_format(audit_buf, " netif=%s", dev); | ||
201 | audit_log_format(audit_buf, " src=" NIP6_FMT, NIP6(*addr)); | ||
202 | if (ntohl(mask->s6_addr32[3]) != 0xffffffff) { | ||
203 | u32 mask_len = 0; | ||
204 | u32 mask_val; | ||
205 | int iter = -1; | ||
206 | while (ntohl(mask->s6_addr32[++iter]) == 0xffffffff) | ||
207 | mask_len += 32; | ||
208 | mask_val = ntohl(mask->s6_addr32[iter]); | ||
209 | while (mask_val > 0) { | ||
210 | mask_val <<= 1; | ||
211 | mask_len++; | ||
212 | } | ||
213 | audit_log_format(audit_buf, " src_prefixlen=%d", mask_len); | ||
214 | } | ||
215 | } | ||
216 | #endif /* IPv6 */ | ||
217 | |||
218 | /* | ||
219 | * Unlabeled Connection Hash Table Functions | 149 | * Unlabeled Connection Hash Table Functions |
220 | */ | 150 | */ |
221 | 151 | ||
@@ -571,10 +501,10 @@ static int netlbl_unlhsh_add(struct net *net, | |||
571 | mask4 = (struct in_addr *)mask; | 501 | mask4 = (struct in_addr *)mask; |
572 | ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid); | 502 | ret_val = netlbl_unlhsh_add_addr4(iface, addr4, mask4, secid); |
573 | if (audit_buf != NULL) | 503 | if (audit_buf != NULL) |
574 | netlbl_unlabel_audit_addr4(audit_buf, | 504 | netlbl_af4list_audit_addr(audit_buf, 1, |
575 | dev_name, | 505 | dev_name, |
576 | addr4->s_addr, | 506 | addr4->s_addr, |
577 | mask4->s_addr); | 507 | mask4->s_addr); |
578 | break; | 508 | break; |
579 | } | 509 | } |
580 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 510 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
@@ -585,9 +515,9 @@ static int netlbl_unlhsh_add(struct net *net, | |||
585 | mask6 = (struct in6_addr *)mask; | 515 | mask6 = (struct in6_addr *)mask; |
586 | ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid); | 516 | ret_val = netlbl_unlhsh_add_addr6(iface, addr6, mask6, secid); |
587 | if (audit_buf != NULL) | 517 | if (audit_buf != NULL) |
588 | netlbl_unlabel_audit_addr6(audit_buf, | 518 | netlbl_af6list_audit_addr(audit_buf, 1, |
589 | dev_name, | 519 | dev_name, |
590 | addr6, mask6); | 520 | addr6, mask6); |
591 | break; | 521 | break; |
592 | } | 522 | } |
593 | #endif /* IPv6 */ | 523 | #endif /* IPv6 */ |
@@ -652,9 +582,9 @@ static int netlbl_unlhsh_remove_addr4(struct net *net, | |||
652 | audit_info); | 582 | audit_info); |
653 | if (audit_buf != NULL) { | 583 | if (audit_buf != NULL) { |
654 | dev = dev_get_by_index(net, iface->ifindex); | 584 | dev = dev_get_by_index(net, iface->ifindex); |
655 | netlbl_unlabel_audit_addr4(audit_buf, | 585 | netlbl_af4list_audit_addr(audit_buf, 1, |
656 | (dev != NULL ? dev->name : NULL), | 586 | (dev != NULL ? dev->name : NULL), |
657 | addr->s_addr, mask->s_addr); | 587 | addr->s_addr, mask->s_addr); |
658 | if (dev != NULL) | 588 | if (dev != NULL) |
659 | dev_put(dev); | 589 | dev_put(dev); |
660 | if (entry && security_secid_to_secctx(entry->secid, | 590 | if (entry && security_secid_to_secctx(entry->secid, |
@@ -712,9 +642,9 @@ static int netlbl_unlhsh_remove_addr6(struct net *net, | |||
712 | audit_info); | 642 | audit_info); |
713 | if (audit_buf != NULL) { | 643 | if (audit_buf != NULL) { |
714 | dev = dev_get_by_index(net, iface->ifindex); | 644 | dev = dev_get_by_index(net, iface->ifindex); |
715 | netlbl_unlabel_audit_addr6(audit_buf, | 645 | netlbl_af6list_audit_addr(audit_buf, 1, |
716 | (dev != NULL ? dev->name : NULL), | 646 | (dev != NULL ? dev->name : NULL), |
717 | addr, mask); | 647 | addr, mask); |
718 | if (dev != NULL) | 648 | if (dev != NULL) |
719 | dev_put(dev); | 649 | dev_put(dev); |
720 | if (entry && security_secid_to_secctx(entry->secid, | 650 | if (entry && security_secid_to_secctx(entry->secid, |