オープンソース・ソフトウェアの開発とダウンロード

Subversion リポジトリの参照

Contents of /trunk/1.8.x/ccs-patch/security/ccsecurity/network.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2219 - (show annotations) (download) (as text)
Tue Mar 3 06:30:38 2009 UTC (15 years, 2 months ago) by kumaneko
Original Path: trunk/1.6.x/ccs-patch/fs/tomoyo_network.c
File MIME type: text/x-csrc
File size: 35507 byte(s)


1 /*
2 * fs/tomoyo_network.c
3 *
4 * Implementation of the Domain-Based Mandatory Access Control.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
8 * Version: 1.6.7-rc 2009/03/03
9 *
10 * This file is applicable to both 2.4.30 and 2.6.11 and later.
11 * See README.ccs for ChangeLog.
12 *
13 */
14
15 #include <linux/ccs_common.h>
16 #include <linux/tomoyo.h>
17 #include <linux/tomoyo_socket.h>
18 #include <linux/realpath.h>
19 #include <linux/net.h>
20 #include <linux/inet.h>
21 #include <linux/in.h>
22 #include <linux/in6.h>
23 #include <net/ip.h>
24 #include <net/ipv6.h>
25 #include <net/udp.h>
26
27 /* Index numbers for Network Controls. */
28 enum ccs_network_acl_index {
29 NETWORK_ACL_UDP_BIND,
30 NETWORK_ACL_UDP_CONNECT,
31 NETWORK_ACL_TCP_BIND,
32 NETWORK_ACL_TCP_LISTEN,
33 NETWORK_ACL_TCP_CONNECT,
34 NETWORK_ACL_TCP_ACCEPT,
35 NETWORK_ACL_RAW_BIND,
36 NETWORK_ACL_RAW_CONNECT
37 };
38
39 /**
40 * ccs_audit_network_log - Audit network log.
41 *
42 * @r: Pointer to "struct ccs_request_info".
43 * @operation: The name of operation.
44 * @address: An IPv4 or IPv6 address.
45 * @port: Port number.
46 * @is_granted: True if this is a granted log.
47 *
48 * Returns 0 on success, negative value otherwise.
49 */
50 static int ccs_audit_network_log(struct ccs_request_info *r,
51 const char *operation, const char *address,
52 const u16 port, const bool is_granted)
53 {
54 return ccs_write_audit_log(is_granted, r, KEYWORD_ALLOW_NETWORK
55 "%s %s %u\n", operation, address, port);
56 }
57
58 /**
59 * ccs_save_ipv6_address - Keep the given IPv6 address on the RAM.
60 *
61 * @addr: Pointer to "struct in6_addr".
62 *
63 * Returns pointer to "struct in6_addr" on success, NULL otherwise.
64 *
65 * The RAM is shared, so NEVER try to modify or kfree() the returned address.
66 */
67 static const struct in6_addr *ccs_save_ipv6_address(const struct in6_addr *addr)
68 {
69 static const u8 ccs_block_size = 16;
70 struct ccs_addr_list {
71 /* Workaround for gcc 4.3's bug. */
72 struct in6_addr addr[16]; /* = ccs_block_size */
73 struct list1_head list;
74 u32 in_use_count;
75 };
76 static LIST1_HEAD(ccs_address_list);
77 struct ccs_addr_list *ptr;
78 static DEFINE_MUTEX(lock);
79 u8 i = ccs_block_size;
80 if (!addr)
81 return NULL;
82 mutex_lock(&lock);
83 list1_for_each_entry(ptr, &ccs_address_list, list) {
84 for (i = 0; i < ptr->in_use_count; i++) {
85 if (!memcmp(&ptr->addr[i], addr, sizeof(*addr)))
86 goto ok;
87 }
88 if (i < ccs_block_size)
89 break;
90 }
91 if (i == ccs_block_size) {
92 ptr = ccs_alloc_element(sizeof(*ptr));
93 if (!ptr)
94 goto ok;
95 list1_add_tail_mb(&ptr->list, &ccs_address_list);
96 i = 0;
97 }
98 ptr->addr[ptr->in_use_count++] = *addr;
99 ok:
100 mutex_unlock(&lock);
101 return ptr ? &ptr->addr[i] : NULL;
102 }
103
104 /* The list for "struct ccs_address_group_entry". */
105 static LIST1_HEAD(ccs_address_group_list);
106
107 /**
108 * ccs_update_address_group_entry - Update "struct ccs_address_group_entry" list.
109 *
110 * @group_name: The name of address group.
111 * @is_ipv6: True if @min_address and @max_address are IPv6 addresses.
112 * @min_address: Start of IPv4 or IPv6 address range.
113 * @max_address: End of IPv4 or IPv6 address range.
114 * @is_delete: True if it is a delete request.
115 *
116 * Returns 0 on success, negative value otherwise.
117 */
118 static int ccs_update_address_group_entry(const char *group_name,
119 const bool is_ipv6,
120 const u16 *min_address,
121 const u16 *max_address,
122 const bool is_delete)
123 {
124 static DEFINE_MUTEX(lock);
125 struct ccs_address_group_entry *new_group;
126 struct ccs_address_group_entry *group;
127 struct ccs_address_group_member *new_member;
128 struct ccs_address_group_member *member;
129 const struct ccs_path_info *saved_group_name;
130 const struct in6_addr *saved_min_address = NULL;
131 const struct in6_addr *saved_max_address = NULL;
132 int error = -ENOMEM;
133 bool found = false;
134 if (!ccs_is_correct_path(group_name, 0, 0, 0, __func__) ||
135 !group_name[0])
136 return -EINVAL;
137 saved_group_name = ccs_save_name(group_name);
138 if (!saved_group_name)
139 return -ENOMEM;
140 if (!is_ipv6)
141 goto not_ipv6;
142 saved_min_address
143 = ccs_save_ipv6_address((struct in6_addr *) min_address);
144 saved_max_address
145 = ccs_save_ipv6_address((struct in6_addr *) max_address);
146 if (!saved_min_address || !saved_max_address)
147 return -ENOMEM;
148 not_ipv6:
149 mutex_lock(&lock);
150 list1_for_each_entry(group, &ccs_address_group_list, list) {
151 if (saved_group_name != group->group_name)
152 continue;
153 list1_for_each_entry(member, &group->address_group_member_list,
154 list) {
155 if (member->is_ipv6 != is_ipv6)
156 continue;
157 if (is_ipv6) {
158 if (member->min.ipv6 != saved_min_address ||
159 member->max.ipv6 != saved_max_address)
160 continue;
161 } else {
162 if (member->min.ipv4 != *(u32 *) min_address ||
163 member->max.ipv4 != *(u32 *) max_address)
164 continue;
165 }
166 member->is_deleted = is_delete;
167 error = 0;
168 goto out;
169 }
170 found = true;
171 break;
172 }
173 if (is_delete) {
174 error = -ENOENT;
175 goto out;
176 }
177 if (!found) {
178 new_group = ccs_alloc_element(sizeof(*new_group));
179 if (!new_group)
180 goto out;
181 INIT_LIST1_HEAD(&new_group->address_group_member_list);
182 new_group->group_name = saved_group_name;
183 list1_add_tail_mb(&new_group->list, &ccs_address_group_list);
184 group = new_group;
185 }
186 new_member = ccs_alloc_element(sizeof(*new_member));
187 if (!new_member)
188 goto out;
189 new_member->is_ipv6 = is_ipv6;
190 if (is_ipv6) {
191 new_member->min.ipv6 = saved_min_address;
192 new_member->max.ipv6 = saved_max_address;
193 } else {
194 new_member->min.ipv4 = *(u32 *) min_address;
195 new_member->max.ipv4 = *(u32 *) max_address;
196 }
197 list1_add_tail_mb(&new_member->list, &group->address_group_member_list);
198 error = 0;
199 out:
200 mutex_unlock(&lock);
201 ccs_update_counter(CCS_UPDATES_COUNTER_EXCEPTION_POLICY);
202 return error;
203 }
204
205 /**
206 * ccs_parse_ip_address - Parse an IP address.
207 *
208 * @address: String to parse.
209 * @min: Pointer to store min address.
210 * @max: Pointer to store max address.
211 *
212 * Returns 2 if @address is an IPv6, 1 if @address is an IPv4, 0 otherwise.
213 */
214 static int ccs_parse_ip_address(char *address, u16 *min, u16 *max)
215 {
216 int count = sscanf(address, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"
217 "-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
218 &min[0], &min[1], &min[2], &min[3],
219 &min[4], &min[5], &min[6], &min[7],
220 &max[0], &max[1], &max[2], &max[3],
221 &max[4], &max[5], &max[6], &max[7]);
222 if (count == 8 || count == 16) {
223 u8 i;
224 if (count == 8)
225 memmove(max, min, sizeof(u16) * 8);
226 for (i = 0; i < 8; i++) {
227 min[i] = htons(min[i]);
228 max[i] = htons(max[i]);
229 }
230 return 2;
231 }
232 count = sscanf(address, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",
233 &min[0], &min[1], &min[2], &min[3],
234 &max[0], &max[1], &max[2], &max[3]);
235 if (count == 4 || count == 8) {
236 u32 ip = htonl((((u8) min[0]) << 24) + (((u8) min[1]) << 16)
237 + (((u8) min[2]) << 8) + (u8) min[3]);
238 memmove(min, &ip, sizeof(ip));
239 if (count == 8)
240 ip = htonl((((u8) max[0]) << 24) + (((u8) max[1]) << 16)
241 + (((u8) max[2]) << 8) + (u8) max[3]);
242 memmove(max, &ip, sizeof(ip));
243 return 1;
244 }
245 return 0;
246 }
247
248 /**
249 * ccs_write_address_group_policy - Write "struct ccs_address_group_entry" list.
250 *
251 * @data: String to parse.
252 * @is_delete: True if it is a delete request.
253 *
254 * Returns 0 on success, negative value otherwise.
255 */
256 int ccs_write_address_group_policy(char *data, const bool is_delete)
257 {
258 bool is_ipv6;
259 u16 min_address[8];
260 u16 max_address[8];
261 char *cp = strchr(data, ' ');
262 if (!cp)
263 return -EINVAL;
264 *cp++ = '\0';
265 switch (ccs_parse_ip_address(cp, min_address, max_address)) {
266 case 2:
267 is_ipv6 = true;
268 break;
269 case 1:
270 is_ipv6 = false;
271 break;
272 default:
273 return -EINVAL;
274 }
275 return ccs_update_address_group_entry(data, is_ipv6, min_address,
276 max_address, is_delete);
277 }
278
279 /**
280 * ccs_find_or_assign_new_address_group - Create address group.
281 *
282 * @group_name: The name of address group.
283 *
284 * Returns pointer to "struct ccs_address_group_entry" on success,
285 * NULL otherwise.
286 */
287 static struct ccs_address_group_entry *
288 ccs_find_or_assign_new_address_group(const char *group_name)
289 {
290 u8 i;
291 struct ccs_address_group_entry *group;
292 for (i = 0; i <= 1; i++) {
293 list1_for_each_entry(group, &ccs_address_group_list, list) {
294 if (!strcmp(group_name, group->group_name->name))
295 return group;
296 }
297 if (!i) {
298 const u16 dummy[2] = { 0, 0 };
299 ccs_update_address_group_entry(group_name, false,
300 dummy, dummy, false);
301 ccs_update_address_group_entry(group_name, false,
302 dummy, dummy, true);
303 }
304 }
305 return NULL;
306 }
307
308 /**
309 * ccs_address_matches_group - Check whether the given address matches members of the given address group.
310 *
311 * @is_ipv6: True if @address is an IPv6 address.
312 * @address: An IPv4 or IPv6 address.
313 * @group: Pointer to "struct ccs_address_group_entry".
314 *
315 * Returns true if @address matches addresses in @group group, false otherwise.
316 */
317 static bool ccs_address_matches_group(const bool is_ipv6, const u32 *address,
318 const struct ccs_address_group_entry *
319 group)
320 {
321 struct ccs_address_group_member *member;
322 const u32 ip = ntohl(*address);
323 list1_for_each_entry(member, &group->address_group_member_list, list) {
324 if (member->is_deleted)
325 continue;
326 if (member->is_ipv6) {
327 if (is_ipv6 &&
328 memcmp(member->min.ipv6, address, 16) <= 0 &&
329 memcmp(address, member->max.ipv6, 16) <= 0)
330 return true;
331 } else {
332 if (!is_ipv6 &&
333 member->min.ipv4 <= ip && ip <= member->max.ipv4)
334 return true;
335 }
336 }
337 return false;
338 }
339
340 /**
341 * ccs_read_address_group_policy - Read "struct ccs_address_group_entry" list.
342 *
343 * @head: Pointer to "struct ccs_io_buffer".
344 *
345 * Returns true on success, false otherwise.
346 */
347 bool ccs_read_address_group_policy(struct ccs_io_buffer *head)
348 {
349 struct list1_head *gpos;
350 struct list1_head *mpos;
351 list1_for_each_cookie(gpos, head->read_var1, &ccs_address_group_list) {
352 struct ccs_address_group_entry *group;
353 group = list1_entry(gpos, struct ccs_address_group_entry, list);
354 list1_for_each_cookie(mpos, head->read_var2,
355 &group->address_group_member_list) {
356 char buf[128];
357 struct ccs_address_group_member *member;
358 member = list1_entry(mpos,
359 struct ccs_address_group_member,
360 list);
361 if (member->is_deleted)
362 continue;
363 if (member->is_ipv6) {
364 const struct in6_addr *min_address
365 = member->min.ipv6;
366 const struct in6_addr *max_address
367 = member->max.ipv6;
368 ccs_print_ipv6(buf, sizeof(buf), min_address);
369 if (min_address != max_address) {
370 int len;
371 char *cp = buf + strlen(buf);
372 *cp++ = '-';
373 len = strlen(buf);
374 ccs_print_ipv6(cp, sizeof(buf) - len,
375 max_address);
376 }
377 } else {
378 const u32 min_address = member->min.ipv4;
379 const u32 max_address = member->max.ipv4;
380 memset(buf, 0, sizeof(buf));
381 snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u",
382 HIPQUAD(min_address));
383 if (min_address != max_address) {
384 const int len = strlen(buf);
385 snprintf(buf + len,
386 sizeof(buf) - 1 - len,
387 "-%u.%u.%u.%u",
388 HIPQUAD(max_address));
389 }
390 }
391 if (!ccs_io_printf(head, KEYWORD_ADDRESS_GROUP
392 "%s %s\n", group->group_name->name,
393 buf))
394 goto out;
395 }
396 }
397 return true;
398 out:
399 return false;
400 }
401
402 #if !defined(NIP6)
403 #define NIP6(addr) \
404 ntohs((addr).s6_addr16[0]), ntohs((addr).s6_addr16[1]), \
405 ntohs((addr).s6_addr16[2]), ntohs((addr).s6_addr16[3]), \
406 ntohs((addr).s6_addr16[4]), ntohs((addr).s6_addr16[5]), \
407 ntohs((addr).s6_addr16[6]), ntohs((addr).s6_addr16[7])
408 #endif
409
410 /**
411 * ccs_print_ipv6 - Print an IPv6 address.
412 *
413 * @buffer: Buffer to write to.
414 * @buffer_len: Size of @buffer.
415 * @ip: Pointer to "struct in6_addr".
416 *
417 * Returns nothing.
418 */
419 void ccs_print_ipv6(char *buffer, const int buffer_len,
420 const struct in6_addr *ip)
421 {
422 memset(buffer, 0, buffer_len);
423 snprintf(buffer, buffer_len - 1, "%x:%x:%x:%x:%x:%x:%x:%x", NIP6(*ip));
424 }
425
426 /**
427 * ccs_net2keyword - Convert network operation index to network operation name.
428 *
429 * @operation: Type of operation.
430 *
431 * Returns the name of operation.
432 */
433 const char *ccs_net2keyword(const u8 operation)
434 {
435 const char *keyword = "unknown";
436 switch (operation) {
437 case NETWORK_ACL_UDP_BIND:
438 keyword = "UDP bind";
439 break;
440 case NETWORK_ACL_UDP_CONNECT:
441 keyword = "UDP connect";
442 break;
443 case NETWORK_ACL_TCP_BIND:
444 keyword = "TCP bind";
445 break;
446 case NETWORK_ACL_TCP_LISTEN:
447 keyword = "TCP listen";
448 break;
449 case NETWORK_ACL_TCP_CONNECT:
450 keyword = "TCP connect";
451 break;
452 case NETWORK_ACL_TCP_ACCEPT:
453 keyword = "TCP accept";
454 break;
455 case NETWORK_ACL_RAW_BIND:
456 keyword = "RAW bind";
457 break;
458 case NETWORK_ACL_RAW_CONNECT:
459 keyword = "RAW connect";
460 break;
461 }
462 return keyword;
463 }
464
465 /**
466 * ccs_update_network_entry - Update "struct ccs_ip_network_acl_record" list.
467 *
468 * @operation: Type of operation.
469 * @record_type: Type of address.
470 * @group: Pointer to "struct ccs_address_group_entry". May be NULL.
471 * @min_address: Start of IPv4 or IPv6 address range.
472 * @max_address: End of IPv4 or IPv6 address range.
473 * @min_port: Start of port number range.
474 * @max_port: End of port number range.
475 * @domain: Pointer to "struct domain_info".
476 * @condition: Pointer to "struct ccs_condition_list". May be NULL.
477 * @is_delete: True if it is a delete request.
478 *
479 * Returns 0 on success, negative value otherwise.
480 */
481 static int ccs_update_network_entry(const u8 operation, const u8 record_type,
482 const struct ccs_address_group_entry *group,
483 const u32 *min_address,
484 const u32 *max_address,
485 const u16 min_port, const u16 max_port,
486 struct domain_info *domain,
487 const struct ccs_condition_list *condition,
488 const bool is_delete)
489 {
490 static DEFINE_MUTEX(lock);
491 struct ccs_acl_info *ptr;
492 struct ccs_ip_network_acl_record *acl;
493 int error = -ENOMEM;
494 /* using host byte order to allow u32 comparison than memcmp().*/
495 const u32 min_ip = ntohl(*min_address);
496 const u32 max_ip = ntohl(*max_address);
497 const struct in6_addr *saved_min_address = NULL;
498 const struct in6_addr *saved_max_address = NULL;
499 if (!domain)
500 return -EINVAL;
501 if (record_type != IP_RECORD_TYPE_IPv6)
502 goto not_ipv6;
503 saved_min_address = ccs_save_ipv6_address((struct in6_addr *)
504 min_address);
505 saved_max_address = ccs_save_ipv6_address((struct in6_addr *)
506 max_address);
507 if (!saved_min_address || !saved_max_address)
508 return -ENOMEM;
509 not_ipv6:
510 mutex_lock(&lock);
511 if (is_delete)
512 goto delete;
513 list1_for_each_entry(ptr, &domain->acl_info_list, list) {
514 if (ccs_acl_type1(ptr) != TYPE_IP_NETWORK_ACL)
515 continue;
516 if (ccs_get_condition_part(ptr) != condition)
517 continue;
518 acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
519 if (acl->operation_type != operation ||
520 acl->record_type != record_type ||
521 acl->min_port != min_port || max_port != acl->max_port)
522 continue;
523 if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
524 if (acl->u.group != group)
525 continue;
526 } else if (record_type == IP_RECORD_TYPE_IPv4) {
527 if (acl->u.ipv4.min != min_ip ||
528 max_ip != acl->u.ipv4.max)
529 continue;
530 } else if (record_type == IP_RECORD_TYPE_IPv6) {
531 if (acl->u.ipv6.min != saved_min_address ||
532 saved_max_address != acl->u.ipv6.max)
533 continue;
534 }
535 error = ccs_add_domain_acl(NULL, ptr);
536 goto out;
537 }
538 /* Not found. Append it to the tail. */
539 acl = ccs_alloc_acl_element(TYPE_IP_NETWORK_ACL, condition);
540 if (!acl)
541 goto out;
542 acl->operation_type = operation;
543 acl->record_type = record_type;
544 if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
545 acl->u.group = group;
546 } else if (record_type == IP_RECORD_TYPE_IPv4) {
547 acl->u.ipv4.min = min_ip;
548 acl->u.ipv4.max = max_ip;
549 } else {
550 acl->u.ipv6.min = saved_min_address;
551 acl->u.ipv6.max = saved_max_address;
552 }
553 acl->min_port = min_port;
554 acl->max_port = max_port;
555 error = ccs_add_domain_acl(domain, &acl->head);
556 goto out;
557 delete:
558 error = -ENOENT;
559 list1_for_each_entry(ptr, &domain->acl_info_list, list) {
560 if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL)
561 continue;
562 if (ccs_get_condition_part(ptr) != condition)
563 continue;
564 acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
565 if (acl->operation_type != operation ||
566 acl->record_type != record_type ||
567 acl->min_port != min_port || max_port != acl->max_port)
568 continue;
569 if (record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
570 if (acl->u.group != group)
571 continue;
572 } else if (record_type == IP_RECORD_TYPE_IPv4) {
573 if (acl->u.ipv4.min != min_ip ||
574 max_ip != acl->u.ipv4.max)
575 continue;
576 } else if (record_type == IP_RECORD_TYPE_IPv6) {
577 if (acl->u.ipv6.min != saved_min_address ||
578 saved_max_address != acl->u.ipv6.max)
579 continue;
580 }
581 error = ccs_del_domain_acl(ptr);
582 break;
583 }
584 out:
585 mutex_unlock(&lock);
586 return error;
587 }
588
589 /**
590 * ccs_check_network_entry - Check permission for network operation.
591 *
592 * @is_ipv6: True if @address is an IPv6 address.
593 * @operation: Type of operation.
594 * @address: An IPv4 or IPv6 address.
595 * @port: Port number.
596 *
597 * Returns 0 on success, negative value otherwise.
598 */
599 static int ccs_check_network_entry(const bool is_ipv6, const u8 operation,
600 const u32 *address, const u16 port)
601 {
602 struct ccs_request_info r;
603 struct ccs_acl_info *ptr;
604 const char *keyword = ccs_net2keyword(operation);
605 bool is_enforce;
606 /* using host byte order to allow u32 comparison than memcmp().*/
607 const u32 ip = ntohl(*address);
608 bool found = false;
609 char buf[64];
610 if (!ccs_can_sleep())
611 return 0;
612 ccs_init_request_info(&r, NULL, CCS_TOMOYO_MAC_FOR_NETWORK);
613 is_enforce = (r.mode == 3);
614 if (!r.mode)
615 return 0;
616 retry:
617 list1_for_each_entry(ptr, &r.domain->acl_info_list, list) {
618 struct ccs_ip_network_acl_record *acl;
619 if (ccs_acl_type2(ptr) != TYPE_IP_NETWORK_ACL)
620 continue;
621 acl = container_of(ptr, struct ccs_ip_network_acl_record, head);
622 if (acl->operation_type != operation || port < acl->min_port ||
623 acl->max_port < port || !ccs_check_condition(&r, ptr))
624 continue;
625 if (acl->record_type == IP_RECORD_TYPE_ADDRESS_GROUP) {
626 if (!ccs_address_matches_group(is_ipv6, address,
627 acl->u.group))
628 continue;
629 } else if (acl->record_type == IP_RECORD_TYPE_IPv4) {
630 if (is_ipv6 ||
631 ip < acl->u.ipv4.min || acl->u.ipv4.max < ip)
632 continue;
633 } else {
634 if (!is_ipv6 ||
635 memcmp(acl->u.ipv6.min, address, 16) > 0 ||
636 memcmp(address, acl->u.ipv6.max, 16) > 0)
637 continue;
638 }
639 r.cond = ccs_get_condition_part(ptr);
640 found = true;
641 break;
642 }
643 memset(buf, 0, sizeof(buf));
644 if (is_ipv6)
645 ccs_print_ipv6(buf, sizeof(buf),
646 (const struct in6_addr *) address);
647 else
648 snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", HIPQUAD(ip));
649 ccs_audit_network_log(&r, keyword, buf, port, found);
650 if (found)
651 return 0;
652 if (ccs_verbose_mode(r.domain))
653 printk(KERN_WARNING "TOMOYO-%s: %s to %s %u denied for %s\n",
654 ccs_get_msg(is_enforce), keyword, buf, port,
655 ccs_get_last_name(r.domain));
656 if (is_enforce) {
657 int error = ccs_check_supervisor(&r, KEYWORD_ALLOW_NETWORK
658 "%s %s %u\n", keyword, buf,
659 port);
660 if (error == 1)
661 goto retry;
662 return error;
663 }
664 if (r.mode == 1 && ccs_domain_quota_ok(r.domain))
665 ccs_update_network_entry(operation, is_ipv6 ?
666 IP_RECORD_TYPE_IPv6 :
667 IP_RECORD_TYPE_IPv4,
668 NULL, address, address, port, port,
669 r.domain, ccs_handler_cond(), 0);
670 return 0;
671 }
672
673 /**
674 * ccs_write_network_policy - Write "struct ccs_ip_network_acl_record" list.
675 *
676 * @data: String to parse.
677 * @domain: Pointer to "struct domain_info".
678 * @condition: Pointer to "struct ccs_condition_list". May be NULL.
679 * @is_delete: True if it is a delete request.
680 *
681 * Returns 0 on success, negative value otherwise.
682 */
683 int ccs_write_network_policy(char *data, struct domain_info *domain,
684 const struct ccs_condition_list *condition,
685 const bool is_delete)
686 {
687 u8 sock_type;
688 u8 operation;
689 u8 record_type;
690 u16 min_address[8];
691 u16 max_address[8];
692 struct ccs_address_group_entry *group = NULL;
693 u16 min_port;
694 u16 max_port;
695 u8 count;
696 char *cp1 = strchr(data, ' ');
697 char *cp2;
698 if (!cp1)
699 goto out;
700 cp1++;
701 if (!strncmp(data, "TCP ", 4))
702 sock_type = SOCK_STREAM;
703 else if (!strncmp(data, "UDP ", 4))
704 sock_type = SOCK_DGRAM;
705 else if (!strncmp(data, "RAW ", 4))
706 sock_type = SOCK_RAW;
707 else
708 goto out;
709 cp2 = strchr(cp1, ' ');
710 if (!cp2)
711 goto out;
712 cp2++;
713 if (!strncmp(cp1, "bind ", 5))
714 switch (sock_type) {
715 case SOCK_STREAM:
716 operation = NETWORK_ACL_TCP_BIND;
717 break;
718 case SOCK_DGRAM:
719 operation = NETWORK_ACL_UDP_BIND;
720 break;
721 default:
722 operation = NETWORK_ACL_RAW_BIND;
723 }
724 else if (!strncmp(cp1, "connect ", 8))
725 switch (sock_type) {
726 case SOCK_STREAM:
727 operation = NETWORK_ACL_TCP_CONNECT;
728 break;
729 case SOCK_DGRAM:
730 operation = NETWORK_ACL_UDP_CONNECT;
731 break;
732 default:
733 operation = NETWORK_ACL_RAW_CONNECT;
734 }
735 else if (sock_type == SOCK_STREAM && !strncmp(cp1, "listen ", 7))
736 operation = NETWORK_ACL_TCP_LISTEN;
737 else if (sock_type == SOCK_STREAM && !strncmp(cp1, "accept ", 7))
738 operation = NETWORK_ACL_TCP_ACCEPT;
739 else
740 goto out;
741 cp1 = strchr(cp2, ' ');
742 if (!cp1)
743 goto out;
744 *cp1++ = '\0';
745 switch (ccs_parse_ip_address(cp2, min_address, max_address)) {
746 case 2:
747 record_type = IP_RECORD_TYPE_IPv6;
748 break;
749 case 1:
750 record_type = IP_RECORD_TYPE_IPv4;
751 break;
752 default:
753 if (*cp2 != '@')
754 goto out;
755 group = ccs_find_or_assign_new_address_group(cp2 + 1);
756 if (!group)
757 return -ENOMEM;
758 record_type = IP_RECORD_TYPE_ADDRESS_GROUP;
759 break;
760 }
761 if (strchr(cp1, ' '))
762 goto out;
763 count = sscanf(cp1, "%hu-%hu", &min_port, &max_port);
764 if (count != 1 && count != 2)
765 goto out;
766 if (count == 1)
767 max_port = min_port;
768 return ccs_update_network_entry(operation, record_type, group,
769 (u32 *) min_address,
770 (u32 *) max_address,
771 min_port, max_port, domain, condition,
772 is_delete);
773 out:
774 return -EINVAL;
775 }
776
777 /**
778 * ccs_check_network_listen_acl - Check permission for listen() operation.
779 *
780 * @is_ipv6: True if @address is an IPv6 address.
781 * @address: An IPv4 or IPv6 address.
782 * @port: Port number.
783 *
784 * Returns 0 on success, negative value otherwise.
785 */
786 static inline int ccs_check_network_listen_acl(const bool is_ipv6,
787 const u8 *address,
788 const u16 port)
789 {
790 return ccs_check_network_entry(is_ipv6, NETWORK_ACL_TCP_LISTEN,
791 (const u32 *) address, ntohs(port));
792 }
793
794 /**
795 * ccs_check_network_connect_acl - Check permission for connect() operation.
796 *
797 * @is_ipv6: True if @address is an IPv6 address.
798 * @sock_type: Type of socket. (TCP or UDP or RAW)
799 * @address: An IPv4 or IPv6 address.
800 * @port: Port number.
801 *
802 * Returns 0 on success, negative value otherwise.
803 */
804 static inline int ccs_check_network_connect_acl(const bool is_ipv6,
805 const int sock_type,
806 const u8 *address,
807 const u16 port)
808 {
809 u8 operation;
810 switch (sock_type) {
811 case SOCK_STREAM:
812 operation = NETWORK_ACL_TCP_CONNECT;
813 break;
814 case SOCK_DGRAM:
815 operation = NETWORK_ACL_UDP_CONNECT;
816 break;
817 default:
818 operation = NETWORK_ACL_RAW_CONNECT;
819 }
820 return ccs_check_network_entry(is_ipv6, operation,
821 (const u32 *) address, ntohs(port));
822 }
823
824 /**
825 * ccs_check_network_bind_acl - Check permission for bind() operation.
826 *
827 * @is_ipv6: True if @address is an IPv6 address.
828 * @sock_type: Type of socket. (TCP or UDP or RAW)
829 * @address: An IPv4 or IPv6 address.
830 * @port: Port number.
831 *
832 * Returns 0 on success, negative value otherwise.
833 */
834 static int ccs_check_network_bind_acl(const bool is_ipv6, const int sock_type,
835 const u8 *address, const u16 port)
836 {
837 u8 operation;
838 switch (sock_type) {
839 case SOCK_STREAM:
840 operation = NETWORK_ACL_TCP_BIND;
841 break;
842 case SOCK_DGRAM:
843 operation = NETWORK_ACL_UDP_BIND;
844 break;
845 default:
846 operation = NETWORK_ACL_RAW_BIND;
847 }
848 return ccs_check_network_entry(is_ipv6, operation,
849 (const u32 *) address, ntohs(port));
850 }
851
852 /**
853 * ccs_check_network_accept_acl - Check permission for accept() operation.
854 *
855 * @is_ipv6: True if @address is an IPv6 address.
856 * @address: An IPv4 or IPv6 address.
857 * @port: Port number.
858 *
859 * Returns 0 on success, negative value otherwise.
860 */
861 static inline int ccs_check_network_accept_acl(const bool is_ipv6,
862 const u8 *address,
863 const u16 port)
864 {
865 int retval;
866 current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
867 retval = ccs_check_network_entry(is_ipv6, NETWORK_ACL_TCP_ACCEPT,
868 (const u32 *) address, ntohs(port));
869 current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
870 return retval;
871 }
872
873 /**
874 * ccs_check_network_sendmsg_acl - Check permission for sendmsg() operation.
875 *
876 * @is_ipv6: True if @address is an IPv6 address.
877 * @sock_type: Type of socket. (UDP or RAW)
878 * @address: An IPv4 or IPv6 address.
879 * @port: Port number.
880 *
881 * Returns 0 on success, negative value otherwise.
882 */
883 static inline int ccs_check_network_sendmsg_acl(const bool is_ipv6,
884 const int sock_type,
885 const u8 *address,
886 const u16 port)
887 {
888 u8 operation;
889 if (sock_type == SOCK_DGRAM)
890 operation = NETWORK_ACL_UDP_CONNECT;
891 else
892 operation = NETWORK_ACL_RAW_CONNECT;
893 return ccs_check_network_entry(is_ipv6, operation,
894 (const u32 *) address, ntohs(port));
895 }
896
897 /**
898 * ccs_check_network_recvmsg_acl - Check permission for recvmsg() operation.
899 *
900 * @is_ipv6: True if @address is an IPv6 address.
901 * @sock_type: Type of socket. (UDP or RAW)
902 * @address: An IPv4 or IPv6 address.
903 * @port: Port number.
904 *
905 * Returns 0 on success, negative value otherwise.
906 */
907 static inline int ccs_check_network_recvmsg_acl(const bool is_ipv6,
908 const int sock_type,
909 const u8 *address,
910 const u16 port)
911 {
912 int retval;
913 const u8 operation
914 = (sock_type == SOCK_DGRAM) ?
915 NETWORK_ACL_UDP_CONNECT : NETWORK_ACL_RAW_CONNECT;
916 current->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
917 retval = ccs_check_network_entry(is_ipv6, operation,
918 (const u32 *) address, ntohs(port));
919 current->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
920 return retval;
921 }
922
923 #define MAX_SOCK_ADDR 128 /* net/socket.c */
924
925 /* Check permission for creating a socket. */
926 int ccs_socket_create_permission(int family, int type, int protocol)
927 {
928 int error = 0;
929 /* Nothing to do if I am a kernel service. */
930 if (segment_eq(get_fs(), KERNEL_DS))
931 return 0;
932 if (family == PF_PACKET && !ccs_capable(TOMOYO_USE_PACKET_SOCKET))
933 return -EPERM;
934 if (family == PF_ROUTE && !ccs_capable(TOMOYO_USE_ROUTE_SOCKET))
935 return -EPERM;
936 if (family != PF_INET && family != PF_INET6)
937 return 0;
938 switch (type) {
939 case SOCK_STREAM:
940 if (!ccs_capable(TOMOYO_INET_STREAM_SOCKET_CREATE))
941 error = -EPERM;
942 break;
943 case SOCK_DGRAM:
944 if (!ccs_capable(TOMOYO_USE_INET_DGRAM_SOCKET))
945 error = -EPERM;
946 break;
947 case SOCK_RAW:
948 if (!ccs_capable(TOMOYO_USE_INET_RAW_SOCKET))
949 error = -EPERM;
950 break;
951 }
952 return error;
953 }
954
955 /* Check permission for listening a TCP socket. */
956 int ccs_socket_listen_permission(struct socket *sock)
957 {
958 int error = 0;
959 char addr[MAX_SOCK_ADDR];
960 int addr_len;
961 /* Nothing to do if I am a kernel service. */
962 if (segment_eq(get_fs(), KERNEL_DS))
963 return 0;
964 if (sock->type != SOCK_STREAM)
965 return 0;
966 switch (sock->sk->sk_family) {
967 case PF_INET:
968 case PF_INET6:
969 break;
970 default:
971 return 0;
972 }
973 if (!ccs_capable(TOMOYO_INET_STREAM_SOCKET_LISTEN))
974 return -EPERM;
975 if (sock->ops->getname(sock, (struct sockaddr *) addr, &addr_len, 0))
976 return -EPERM;
977 switch (((struct sockaddr *) addr)->sa_family) {
978 struct sockaddr_in6 *addr6;
979 struct sockaddr_in *addr4;
980 case AF_INET6:
981 addr6 = (struct sockaddr_in6 *) addr;
982 error = ccs_check_network_listen_acl(true,
983 addr6->sin6_addr.s6_addr,
984 addr6->sin6_port);
985 break;
986 case AF_INET:
987 addr4 = (struct sockaddr_in *) addr;
988 error = ccs_check_network_listen_acl(false,
989 (u8 *) &addr4->sin_addr,
990 addr4->sin_port);
991 break;
992 }
993 return error;
994 }
995
996 /* Check permission for setting the remote IP address/port pair of a socket. */
997 int ccs_socket_connect_permission(struct socket *sock, struct sockaddr *addr,
998 int addr_len)
999 {
1000 int error = 0;
1001 const unsigned int type = sock->type;
1002 /* Nothing to do if I am a kernel service. */
1003 if (segment_eq(get_fs(), KERNEL_DS))
1004 return 0;
1005 switch (type) {
1006 case SOCK_STREAM:
1007 case SOCK_DGRAM:
1008 case SOCK_RAW:
1009 break;
1010 default:
1011 return 0;
1012 }
1013 switch (addr->sa_family) {
1014 struct sockaddr_in6 *addr6;
1015 struct sockaddr_in *addr4;
1016 u16 port;
1017 case AF_INET6:
1018 if (addr_len < SIN6_LEN_RFC2133)
1019 break;
1020 addr6 = (struct sockaddr_in6 *) addr;
1021 if (type != SOCK_RAW)
1022 port = addr6->sin6_port;
1023 else
1024 port = htons(sock->sk->sk_protocol);
1025 error = ccs_check_network_connect_acl(true, type,
1026 addr6->sin6_addr.s6_addr,
1027 port);
1028 break;
1029 case AF_INET:
1030 if (addr_len < sizeof(struct sockaddr_in))
1031 break;
1032 addr4 = (struct sockaddr_in *) addr;
1033 if (type != SOCK_RAW)
1034 port = addr4->sin_port;
1035 else
1036 port = htons(sock->sk->sk_protocol);
1037 error = ccs_check_network_connect_acl(false, type,
1038 (u8 *) &addr4->sin_addr,
1039 port);
1040 break;
1041 }
1042 if (type != SOCK_STREAM)
1043 return error;
1044 switch (sock->sk->sk_family) {
1045 case PF_INET:
1046 case PF_INET6:
1047 if (!ccs_capable(TOMOYO_INET_STREAM_SOCKET_CONNECT))
1048 error = -EPERM;
1049 break;
1050 }
1051 return error;
1052 }
1053
1054 /* Check permission for setting the local IP address/port pair of a socket. */
1055 int ccs_socket_bind_permission(struct socket *sock, struct sockaddr *addr,
1056 int addr_len)
1057 {
1058 int error = 0;
1059 const unsigned int type = sock->type;
1060 /* Nothing to do if I am a kernel service. */
1061 if (segment_eq(get_fs(), KERNEL_DS))
1062 return 0;
1063 switch (type) {
1064 case SOCK_STREAM:
1065 case SOCK_DGRAM:
1066 case SOCK_RAW:
1067 break;
1068 default:
1069 return 0;
1070 }
1071 switch (addr->sa_family) {
1072 struct sockaddr_in6 *addr6;
1073 struct sockaddr_in *addr4;
1074 u16 port;
1075 case AF_INET6:
1076 if (addr_len < SIN6_LEN_RFC2133)
1077 break;
1078 addr6 = (struct sockaddr_in6 *) addr;
1079 if (type != SOCK_RAW)
1080 port = addr6->sin6_port;
1081 else
1082 port = htons(sock->sk->sk_protocol);
1083 error = ccs_check_network_bind_acl(true, type,
1084 addr6->sin6_addr.s6_addr,
1085 port);
1086 break;
1087 case AF_INET:
1088 if (addr_len < sizeof(struct sockaddr_in))
1089 break;
1090 addr4 = (struct sockaddr_in *) addr;
1091 if (type != SOCK_RAW)
1092 port = addr4->sin_port;
1093 else
1094 port = htons(sock->sk->sk_protocol);
1095 error = ccs_check_network_bind_acl(false, type,
1096 (u8 *) &addr4->sin_addr,
1097 port);
1098 break;
1099 }
1100 return error;
1101 }
1102
1103 /*
1104 * Check permission for accepting a TCP socket.
1105 *
1106 * Currently, the LSM hook for this purpose is not provided.
1107 */
1108 int ccs_socket_accept_permission(struct socket *sock, struct sockaddr *addr)
1109 {
1110 int error = 0;
1111 int addr_len;
1112 /* Nothing to do if I am a kernel service. */
1113 if (segment_eq(get_fs(), KERNEL_DS))
1114 return 0;
1115 switch (sock->sk->sk_family) {
1116 case PF_INET:
1117 case PF_INET6:
1118 break;
1119 default:
1120 return 0;
1121 }
1122 error = sock->ops->getname(sock, addr, &addr_len, 2);
1123 if (error)
1124 return error;
1125 switch (addr->sa_family) {
1126 struct sockaddr_in6 *addr6;
1127 struct sockaddr_in *addr4;
1128 case AF_INET6:
1129 addr6 = (struct sockaddr_in6 *) addr;
1130 error = ccs_check_network_accept_acl(true,
1131 addr6->sin6_addr.s6_addr,
1132 addr6->sin6_port);
1133 break;
1134 case AF_INET:
1135 addr4 = (struct sockaddr_in *) addr;
1136 error = ccs_check_network_accept_acl(false,
1137 (u8 *) &addr4->sin_addr,
1138 addr4->sin_port);
1139 break;
1140 }
1141 return error;
1142 }
1143
1144 /* Check permission for sending a datagram via a UDP or RAW socket. */
1145 int ccs_socket_sendmsg_permission(struct socket *sock, struct sockaddr *addr,
1146 int addr_len)
1147 {
1148 int error = 0;
1149 const int type = sock->type;
1150 /* Nothing to do if I am a kernel service. */
1151 if (segment_eq(get_fs(), KERNEL_DS))
1152 return 0;
1153 if (!addr || (type != SOCK_DGRAM && type != SOCK_RAW))
1154 return 0;
1155 switch (addr->sa_family) {
1156 struct sockaddr_in6 *addr6;
1157 struct sockaddr_in *addr4;
1158 u16 port;
1159 case AF_INET6:
1160 if (addr_len < SIN6_LEN_RFC2133)
1161 break;
1162 addr6 = (struct sockaddr_in6 *) addr;
1163 if (type == SOCK_DGRAM)
1164 port = addr6->sin6_port;
1165 else
1166 port = htons(sock->sk->sk_protocol);
1167 error = ccs_check_network_sendmsg_acl(true, type,
1168 addr6->sin6_addr.s6_addr,
1169 port);
1170 break;
1171 case AF_INET:
1172 if (addr_len < sizeof(struct sockaddr_in))
1173 break;
1174 addr4 = (struct sockaddr_in *) addr;
1175 if (type == SOCK_DGRAM)
1176 port = addr4->sin_port;
1177 else
1178 port = htons(sock->sk->sk_protocol);
1179 error = ccs_check_network_sendmsg_acl(false, type,
1180 (u8 *) &addr4->sin_addr,
1181 port);
1182 break;
1183 }
1184 return error;
1185 }
1186
1187 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
1188 #if !defined(RHEL_MAJOR) || RHEL_MAJOR != 5
1189
1190 static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
1191 {
1192 return skb->nh.iph;
1193 }
1194
1195 static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
1196 {
1197 return skb->h.uh;
1198 }
1199
1200 static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
1201 {
1202 return skb->nh.ipv6h;
1203 }
1204
1205 #endif
1206 #endif
1207
1208 /*
1209 * Check permission for receiving a datagram via a UDP or RAW socket.
1210 *
1211 * Currently, the LSM hook for this purpose is not provided.
1212 */
1213 int ccs_socket_recv_datagram_permission(struct sock *sk, struct sk_buff *skb,
1214 const unsigned int flags)
1215 {
1216 int error = 0;
1217 const unsigned int type = sk->sk_type;
1218 /* Nothing to do if I didn't receive a datagram. */
1219 if (!skb)
1220 return 0;
1221 /* Nothing to do if I can't sleep. */
1222 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
1223 if (in_interrupt())
1224 return 0;
1225 #else
1226 if (in_atomic())
1227 return 0;
1228 #endif
1229 /* Nothing to do if I am a kernel service. */
1230 if (segment_eq(get_fs(), KERNEL_DS))
1231 return 0;
1232 if (type != SOCK_DGRAM && type != SOCK_RAW)
1233 return 0;
1234
1235 switch (sk->sk_family) {
1236 struct in6_addr sin6;
1237 struct in_addr sin4;
1238 u16 port;
1239 case PF_INET6:
1240 if (type == SOCK_DGRAM) { /* UDP IPv6 */
1241 if (skb->protocol == htons(ETH_P_IP)) {
1242 ipv6_addr_set(&sin6, 0, 0, htonl(0xffff),
1243 ip_hdr(skb)->saddr);
1244 } else {
1245 ipv6_addr_copy(&sin6, &ipv6_hdr(skb)->saddr);
1246 }
1247 port = udp_hdr(skb)->source;
1248 } else { /* RAW IPv6 */
1249 ipv6_addr_copy(&sin6, &ipv6_hdr(skb)->saddr);
1250 port = htons(sk->sk_protocol);
1251 }
1252 error = ccs_check_network_recvmsg_acl(true, type,
1253 (u8 *) &sin6, port);
1254 break;
1255 case PF_INET:
1256 if (type == SOCK_DGRAM) { /* UDP IPv4 */
1257 sin4.s_addr = ip_hdr(skb)->saddr;
1258 port = udp_hdr(skb)->source;
1259 } else { /* RAW IPv4 */
1260 sin4.s_addr = ip_hdr(skb)->saddr;
1261 port = htons(sk->sk_protocol);
1262 }
1263 error = ccs_check_network_recvmsg_acl(false, type,
1264 (u8 *) &sin4, port);
1265 break;
1266 }
1267 if (!error)
1268 return 0;
1269 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1270 lock_sock(sk);
1271 #endif
1272 /*
1273 * Remove from queue if MSG_PEEK is used so that
1274 * the head message from unwanted source in receive queue will not
1275 * prevent the caller from picking up next message from wanted source
1276 * when the caller is using MSG_PEEK flag for picking up.
1277 */
1278 if (flags & MSG_PEEK) {
1279 unsigned long cpu_flags;
1280 /***** CRITICAL SECTION START *****/
1281 spin_lock_irqsave(&sk->sk_receive_queue.lock, cpu_flags);
1282 if (skb == skb_peek(&sk->sk_receive_queue)) {
1283 __skb_unlink(skb, &sk->sk_receive_queue);
1284 atomic_dec(&skb->users);
1285 }
1286 spin_unlock_irqrestore(&sk->sk_receive_queue.lock, cpu_flags);
1287 /***** CRITICAL SECTION END *****/
1288 }
1289 /* Drop reference count. */
1290 skb_free_datagram(sk, skb);
1291 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
1292 release_sock(sk);
1293 #endif
1294 /* Hope less harmful than -EPERM. */
1295 return -EAGAIN;
1296 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26