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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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