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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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