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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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