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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2344 - (hide annotations) (download) (as text)
Wed Apr 1 02:23:18 2009 UTC (15 years, 1 month ago) by kumaneko
Original Path: trunk/1.6.x/ccs-patch/fs/tomoyo_network.c
File MIME type: text/x-csrc
File size: 35480 byte(s)


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

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