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

Subversion リポジトリの参照

Contents of /branches/ccs-patch/security/ccsecurity/network.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2865 - (show annotations) (download) (as text)
Fri Aug 7 07:23:13 2009 UTC (14 years, 10 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 35396 byte(s)


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

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