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

Subversion リポジトリの参照

Contents of /branches/ccs-patch/fs/tomoyo_network.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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