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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2951 - (hide annotations) (download) (as text)
Tue Aug 25 04:26:20 2009 UTC (14 years, 9 months ago) by kumaneko
Original Path: trunk/1.7.x/ccs-patch/security/ccsecurity/network.c
File MIME type: text/x-csrc
File size: 24225 byte(s)


1 kumaneko 111 /*
2 kumaneko 2864 * security/ccsecurity/network.c
3 kumaneko 111 *
4 kumaneko 2030 * Copyright (C) 2005-2009 NTT DATA CORPORATION
5 kumaneko 111 *
6 kumaneko 2943 * Version: 1.7.0-pre 2009/08/24
7 kumaneko 111 *
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 kumaneko 1084 #include <linux/net.h>
14     #include <linux/inet.h>
15     #include <linux/in.h>
16     #include <linux/in6.h>
17 kumaneko 2037 #include <net/ip.h>
18     #include <net/ipv6.h>
19     #include <net/udp.h>
20 kumaneko 2854 #include "internal.h"
21 kumaneko 111
22 kumaneko 1052 /**
23 kumaneko 2002 * ccs_audit_network_log - Audit network log.
24 kumaneko 1052 *
25 kumaneko 1657 * @r: Pointer to "struct ccs_request_info".
26 kumaneko 1052 * @operation: The name of operation.
27     * @address: An IPv4 or IPv6 address.
28     * @port: Port number.
29     * @is_granted: True if this is a granted log.
30     *
31     * Returns 0 on success, negative value otherwise.
32     */
33 kumaneko 2002 static int ccs_audit_network_log(struct ccs_request_info *r,
34     const char *operation, const char *address,
35     const u16 port, const bool is_granted)
36 kumaneko 111 {
37 kumaneko 2943 if (!is_granted)
38     ccs_warn_log(r, "%s %s %u", operation, address, port);
39 kumaneko 2892 return ccs_write_audit_log(is_granted, r, CCS_KEYWORD_ALLOW_NETWORK
40 kumaneko 1657 "%s %s %u\n", operation, address, port);
41 kumaneko 111 }
42    
43 kumaneko 1052 /**
44 kumaneko 2890 * ccs_parse_ip_address - Parse an IP address.
45     *
46     * @address: String to parse.
47     * @min: Pointer to store min address.
48     * @max: Pointer to store max address.
49     *
50     * Returns 2 if @address is an IPv6, 1 if @address is an IPv4, 0 otherwise.
51     */
52 kumaneko 2900 int ccs_parse_ip_address(char *address, u16 *min, u16 *max)
53 kumaneko 2890 {
54     int count = sscanf(address, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"
55     "-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
56     &min[0], &min[1], &min[2], &min[3],
57     &min[4], &min[5], &min[6], &min[7],
58     &max[0], &max[1], &max[2], &max[3],
59     &max[4], &max[5], &max[6], &max[7]);
60     if (count == 8 || count == 16) {
61     u8 i;
62     if (count == 8)
63     memmove(max, min, sizeof(u16) * 8);
64     for (i = 0; i < 8; i++) {
65     min[i] = htons(min[i]);
66     max[i] = htons(max[i]);
67     }
68     return 2;
69     }
70     count = sscanf(address, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",
71     &min[0], &min[1], &min[2], &min[3],
72     &max[0], &max[1], &max[2], &max[3]);
73     if (count == 4 || count == 8) {
74     u32 ip = htonl((((u8) min[0]) << 24) + (((u8) min[1]) << 16)
75     + (((u8) min[2]) << 8) + (u8) min[3]);
76     memmove(min, &ip, sizeof(ip));
77     if (count == 8)
78     ip = htonl((((u8) max[0]) << 24) + (((u8) max[1]) << 16)
79     + (((u8) max[2]) << 8) + (u8) max[3]);
80     memmove(max, &ip, sizeof(ip));
81     return 1;
82     }
83     return 0;
84     }
85    
86 kumaneko 719 #if !defined(NIP6)
87 kumaneko 2943 #define NIP6(addr) \
88     ntohs((addr).s6_addr16[0]), ntohs((addr).s6_addr16[1]), \
89     ntohs((addr).s6_addr16[2]), ntohs((addr).s6_addr16[3]), \
90     ntohs((addr).s6_addr16[4]), ntohs((addr).s6_addr16[5]), \
91     ntohs((addr).s6_addr16[6]), ntohs((addr).s6_addr16[7])
92 kumaneko 719 #endif
93    
94 kumaneko 1052 /**
95 kumaneko 1054 * ccs_print_ipv6 - Print an IPv6 address.
96 kumaneko 1052 *
97     * @buffer: Buffer to write to.
98 kumaneko 1064 * @buffer_len: Size of @buffer.
99 kumaneko 1052 * @ip: Pointer to "struct in6_addr".
100     *
101 kumaneko 1064 * Returns nothing.
102 kumaneko 1052 */
103 kumaneko 1064 void ccs_print_ipv6(char *buffer, const int buffer_len,
104     const struct in6_addr *ip)
105 kumaneko 111 {
106     memset(buffer, 0, buffer_len);
107 kumaneko 719 snprintf(buffer, buffer_len - 1, "%x:%x:%x:%x:%x:%x:%x:%x", NIP6(*ip));
108 kumaneko 111 }
109    
110 kumaneko 1052 /**
111     * ccs_net2keyword - Convert network operation index to network operation name.
112     *
113     * @operation: Type of operation.
114     *
115     * Returns the name of operation.
116     */
117     const char *ccs_net2keyword(const u8 operation)
118 kumaneko 111 {
119     const char *keyword = "unknown";
120     switch (operation) {
121 kumaneko 2915 case CCS_NETWORK_UDP_BIND:
122 kumaneko 111 keyword = "UDP bind";
123     break;
124 kumaneko 2915 case CCS_NETWORK_UDP_CONNECT:
125 kumaneko 111 keyword = "UDP connect";
126     break;
127 kumaneko 2915 case CCS_NETWORK_TCP_BIND:
128 kumaneko 111 keyword = "TCP bind";
129     break;
130 kumaneko 2915 case CCS_NETWORK_TCP_LISTEN:
131 kumaneko 111 keyword = "TCP listen";
132     break;
133 kumaneko 2915 case CCS_NETWORK_TCP_CONNECT:
134 kumaneko 111 keyword = "TCP connect";
135     break;
136 kumaneko 2915 case CCS_NETWORK_TCP_ACCEPT:
137 kumaneko 111 keyword = "TCP accept";
138     break;
139 kumaneko 2915 case CCS_NETWORK_RAW_BIND:
140 kumaneko 111 keyword = "RAW bind";
141     break;
142 kumaneko 2915 case CCS_NETWORK_RAW_CONNECT:
143 kumaneko 111 keyword = "RAW connect";
144     break;
145     }
146     return keyword;
147     }
148    
149 kumaneko 1052 /**
150 kumaneko 2922 * ccs_network_entry2 - Check permission for network operation.
151 kumaneko 1052 *
152     * @is_ipv6: True if @address is an IPv6 address.
153     * @operation: Type of operation.
154     * @address: An IPv4 or IPv6 address.
155     * @port: Port number.
156     *
157     * Returns 0 on success, negative value otherwise.
158 kumaneko 2690 *
159 kumaneko 2828 * Caller holds ccs_read_lock().
160 kumaneko 1052 */
161 kumaneko 2922 static int ccs_network_entry2(const bool is_ipv6, const u8 operation,
162 kumaneko 2943 const u32 *address, const u16 port)
163 kumaneko 111 {
164 kumaneko 1657 struct ccs_request_info r;
165 kumaneko 2002 struct ccs_acl_info *ptr;
166 kumaneko 1052 const char *keyword = ccs_net2keyword(operation);
167 kumaneko 2916 const u16 perm = 1 << operation;
168 kumaneko 1052 /* using host byte order to allow u32 comparison than memcmp().*/
169     const u32 ip = ntohl(*address);
170 kumaneko 2897 int error;
171 kumaneko 1064 char buf[64];
172 kumaneko 2943 if (ccs_init_request_info(&r, NULL,
173     CCS_MAC_NETWORK_UDP_BIND + operation)
174     == CCS_MAC_MODE_DISABLED)
175 kumaneko 1052 return 0;
176 kumaneko 2943 memset(buf, 0, sizeof(buf));
177     if (is_ipv6)
178     ccs_print_ipv6(buf, sizeof(buf), (const struct in6_addr *)
179     address);
180     else
181     snprintf(buf, sizeof(buf) - 1, "%u.%u.%u.%u", HIPQUAD(ip));
182     do {
183     error = -EPERM;
184     list_for_each_entry_rcu(ptr, &r.domain->acl_info_list, list) {
185     struct ccs_ip_network_acl *acl;
186     if (ptr->is_deleted ||
187     ptr->type != CCS_TYPE_IP_NETWORK_ACL)
188 kumaneko 1052 continue;
189 kumaneko 2943 acl = container_of(ptr, struct ccs_ip_network_acl,
190     head);
191     if (!(acl->perm & perm))
192 kumaneko 1052 continue;
193 kumaneko 2943 if (!ccs_compare_number_union(port, &acl->port) ||
194     !ccs_condition(&r, ptr))
195 kumaneko 1052 continue;
196 kumaneko 2943 switch (acl->address_type) {
197     case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP:
198     if (!ccs_address_matches_group(is_ipv6,
199     address,
200     acl->address.
201     group))
202     continue;
203     break;
204     case CCS_IP_ADDRESS_TYPE_IPv4:
205     if (is_ipv6 || ip < acl->address.ipv4.min ||
206     acl->address.ipv4.max < ip)
207     continue;
208     break;
209     default:
210     if (!is_ipv6 ||
211     memcmp(acl->address.ipv6.min, address, 16)
212     > 0 ||
213     memcmp(address, acl->address.ipv6.max, 16)
214     > 0)
215     continue;
216     break;
217     }
218     r.cond = ptr->cond;
219     error = 0;
220     break;
221 kumaneko 111 }
222 kumaneko 2943 ccs_audit_network_log(&r, keyword, buf, port, !error);
223     if (!error)
224     break;
225 kumaneko 2922 error = ccs_supervisor(&r, CCS_KEYWORD_ALLOW_NETWORK
226 kumaneko 2943 "%s %s %u\n", keyword, buf, port);
227     } while (error == 1);
228     if (r.mode != CCS_MAC_MODE_ENFORCING)
229 kumaneko 2897 error = 0;
230     return error;
231 kumaneko 111 }
232    
233 kumaneko 1052 /**
234 kumaneko 2922 * ccs_network_entry - Check permission for network operation.
235 kumaneko 2702 *
236     * @is_ipv6: True if @address is an IPv6 address.
237     * @operation: Type of operation.
238     * @address: An IPv4 or IPv6 address.
239     * @port: Port number.
240     *
241     * Returns 0 on success, negative value otherwise.
242     */
243 kumaneko 2922 static int ccs_network_entry(const bool is_ipv6, const u8 operation,
244 kumaneko 2943 const u32 *address, const u16 port)
245 kumaneko 2702 {
246 kumaneko 2828 const int idx = ccs_read_lock();
247 kumaneko 2922 const int error = ccs_network_entry2(is_ipv6, operation,
248 kumaneko 2943 address, port);
249 kumaneko 2828 ccs_read_unlock(idx);
250 kumaneko 2702 return error;
251     }
252    
253     /**
254 kumaneko 2915 * ccs_write_network_policy - Write "struct ccs_ip_network_acl" list.
255 kumaneko 1052 *
256     * @data: String to parse.
257 kumaneko 2282 * @domain: Pointer to "struct ccs_domain_info".
258 kumaneko 2576 * @condition: Pointer to "struct ccs_condition". May be NULL.
259 kumaneko 1052 * @is_delete: True if it is a delete request.
260     *
261     * Returns 0 on success, negative value otherwise.
262     */
263 kumaneko 2282 int ccs_write_network_policy(char *data, struct ccs_domain_info *domain,
264 kumaneko 2576 struct ccs_condition *condition,
265 kumaneko 1052 const bool is_delete)
266 kumaneko 111 {
267 kumaneko 2915 struct ccs_ip_network_acl *entry = NULL;
268 kumaneko 2900 struct ccs_acl_info *ptr;
269 kumaneko 2915 struct ccs_ip_network_acl e = {
270 kumaneko 2900 .head.type = CCS_TYPE_IP_NETWORK_ACL,
271     .head.cond = condition,
272     };
273     u16 min_address[8];
274     u16 max_address[8];
275     int error = is_delete ? -ENOENT : -ENOMEM;
276     u8 sock_type;
277 kumaneko 2779 char *w[4];
278     if (!ccs_tokenize(data, w, sizeof(w)) || !w[3][0])
279 kumaneko 2870 return -EINVAL;
280 kumaneko 2900 if (!strcmp(w[0], "TCP"))
281     sock_type = SOCK_STREAM;
282     else if (!strcmp(w[0], "UDP"))
283     sock_type = SOCK_DGRAM;
284     else if (!strcmp(w[0], "RAW"))
285     sock_type = SOCK_RAW;
286     else
287     return -EINVAL;
288     if (!strcmp(w[1], "bind"))
289     switch (sock_type) {
290     case SOCK_STREAM:
291 kumaneko 2916 e.perm = 1 << CCS_NETWORK_TCP_BIND;
292 kumaneko 2900 break;
293     case SOCK_DGRAM:
294 kumaneko 2916 e.perm = 1 << CCS_NETWORK_UDP_BIND;
295 kumaneko 2900 break;
296     default:
297 kumaneko 2916 e.perm = 1 << CCS_NETWORK_RAW_BIND;
298 kumaneko 2900 break;
299     }
300     else if (!strcmp(w[1], "connect"))
301     switch (sock_type) {
302     case SOCK_STREAM:
303 kumaneko 2916 e.perm = 1 << CCS_NETWORK_TCP_CONNECT;
304 kumaneko 2900 break;
305     case SOCK_DGRAM:
306 kumaneko 2916 e.perm = 1 << CCS_NETWORK_UDP_CONNECT;
307 kumaneko 2900 break;
308     default:
309 kumaneko 2916 e.perm = 1 << CCS_NETWORK_RAW_CONNECT;
310 kumaneko 2900 break;
311     }
312     else if (sock_type == SOCK_STREAM && !strcmp(w[1], "listen"))
313 kumaneko 2916 e.perm = 1 << CCS_NETWORK_TCP_LISTEN;
314 kumaneko 2900 else if (sock_type == SOCK_STREAM && !strcmp(w[1], "accept"))
315 kumaneko 2916 e.perm = 1 << CCS_NETWORK_TCP_ACCEPT;
316 kumaneko 2900 else
317     return -EINVAL;
318     switch (ccs_parse_ip_address(w[2], min_address, max_address)) {
319     case 2:
320 kumaneko 2916 e.address_type = CCS_IP_ADDRESS_TYPE_IPv6;
321 kumaneko 2900 e.address.ipv6.min = ccs_get_ipv6_address((struct in6_addr *)
322     min_address);
323     e.address.ipv6.max = ccs_get_ipv6_address((struct in6_addr *)
324     max_address);
325     if (!e.address.ipv6.min || !e.address.ipv6.max)
326     goto out;
327     break;
328     case 1:
329 kumaneko 2916 e.address_type = CCS_IP_ADDRESS_TYPE_IPv4;
330 kumaneko 2900 /* use host byte order to allow u32 comparison.*/
331 kumaneko 2943 e.address.ipv4.min = ntohl(*(u32 *) min_address);
332     e.address.ipv4.max = ntohl(*(u32 *) max_address);
333 kumaneko 2900 break;
334     default:
335     if (w[2][0] != '@')
336     return -EINVAL;
337 kumaneko 2916 e.address_type = CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP;
338 kumaneko 2900 e.address.group = ccs_get_address_group(w[2] + 1);
339     if (!e.address.group)
340     return -ENOMEM;
341     break;
342     }
343     if (!ccs_parse_number_union(w[3], &e.port))
344     goto out;
345     if (!is_delete)
346     entry = kmalloc(sizeof(e), GFP_KERNEL);
347     mutex_lock(&ccs_policy_lock);
348     list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
349 kumaneko 2915 struct ccs_ip_network_acl *acl =
350     container_of(ptr, struct ccs_ip_network_acl,
351 kumaneko 2900 head);
352     if (ptr->type != CCS_TYPE_IP_NETWORK_ACL ||
353     ptr->cond != condition ||
354 kumaneko 2916 ccs_memcmp(acl, &e, offsetof(typeof(e), address_type),
355 kumaneko 2900 sizeof(e)))
356     continue;
357 kumaneko 2916 if (is_delete) {
358     acl->perm &= ~e.perm;
359     if (!acl->perm)
360     ptr->is_deleted = true;
361     } else {
362     if (ptr->is_deleted)
363     acl->perm = 0;
364     acl->perm |= e.perm;
365     ptr->is_deleted = false;
366     }
367 kumaneko 2900 error = 0;
368     break;
369     }
370     if (!is_delete && error && ccs_commit_ok(entry, &e, sizeof(e))) {
371     ccs_add_domain_acl(domain, &entry->head);
372     entry = NULL;
373     error = 0;
374     }
375     mutex_unlock(&ccs_policy_lock);
376     out:
377     if (w[2][0] == '@')
378     ccs_put_address_group(e.address.group);
379 kumaneko 2916 else if (e.address_type == CCS_IP_ADDRESS_TYPE_IPv6) {
380 kumaneko 2900 ccs_put_ipv6_address(e.address.ipv6.min);
381     ccs_put_ipv6_address(e.address.ipv6.max);
382     }
383     ccs_put_number_union(&e.port);
384     kfree(entry);
385     return error;
386 kumaneko 111 }
387    
388 kumaneko 1052 /**
389 kumaneko 2922 * ccs_network_listen_acl - Check permission for listen() operation.
390 kumaneko 1052 *
391     * @is_ipv6: True if @address is an IPv6 address.
392     * @address: An IPv4 or IPv6 address.
393     * @port: Port number.
394     *
395     * Returns 0 on success, negative value otherwise.
396     */
397 kumaneko 2922 static inline int ccs_network_listen_acl(const bool is_ipv6,
398 kumaneko 2943 const u8 *address,
399     const u16 port)
400 kumaneko 111 {
401 kumaneko 2922 return ccs_network_entry(is_ipv6, CCS_NETWORK_TCP_LISTEN,
402 kumaneko 2943 (const u32 *) address, ntohs(port));
403 kumaneko 111 }
404    
405 kumaneko 1052 /**
406 kumaneko 2922 * ccs_network_connect_acl - Check permission for connect() operation.
407 kumaneko 1052 *
408     * @is_ipv6: True if @address is an IPv6 address.
409     * @sock_type: Type of socket. (TCP or UDP or RAW)
410     * @address: An IPv4 or IPv6 address.
411     * @port: Port number.
412     *
413     * Returns 0 on success, negative value otherwise.
414     */
415 kumaneko 2922 static inline int ccs_network_connect_acl(const bool is_ipv6,
416 kumaneko 2943 const int sock_type,
417     const u8 *address,
418     const u16 port)
419 kumaneko 111 {
420 kumaneko 1052 u8 operation;
421     switch (sock_type) {
422     case SOCK_STREAM:
423 kumaneko 2915 operation = CCS_NETWORK_TCP_CONNECT;
424 kumaneko 1052 break;
425     case SOCK_DGRAM:
426 kumaneko 2915 operation = CCS_NETWORK_UDP_CONNECT;
427 kumaneko 1052 break;
428     default:
429 kumaneko 2915 operation = CCS_NETWORK_RAW_CONNECT;
430 kumaneko 1052 }
431 kumaneko 2922 return ccs_network_entry(is_ipv6, operation,
432 kumaneko 2943 (const u32 *) address, ntohs(port));
433 kumaneko 111 }
434    
435 kumaneko 1052 /**
436 kumaneko 2922 * ccs_network_bind_acl - Check permission for bind() operation.
437 kumaneko 1052 *
438     * @is_ipv6: True if @address is an IPv6 address.
439     * @sock_type: Type of socket. (TCP or UDP or RAW)
440     * @address: An IPv4 or IPv6 address.
441     * @port: Port number.
442     *
443     * Returns 0 on success, negative value otherwise.
444     */
445 kumaneko 2922 static int ccs_network_bind_acl(const bool is_ipv6, const int sock_type,
446 kumaneko 2943 const u8 *address, const u16 port)
447 kumaneko 111 {
448 kumaneko 1052 u8 operation;
449     switch (sock_type) {
450     case SOCK_STREAM:
451 kumaneko 2915 operation = CCS_NETWORK_TCP_BIND;
452 kumaneko 1052 break;
453     case SOCK_DGRAM:
454 kumaneko 2915 operation = CCS_NETWORK_UDP_BIND;
455 kumaneko 1052 break;
456     default:
457 kumaneko 2915 operation = CCS_NETWORK_RAW_BIND;
458 kumaneko 1052 }
459 kumaneko 2922 return ccs_network_entry(is_ipv6, operation,
460 kumaneko 2943 (const u32 *) address, ntohs(port));
461 kumaneko 111 }
462    
463 kumaneko 1052 /**
464 kumaneko 2922 * ccs_network_accept_acl - Check permission for accept() operation.
465 kumaneko 1052 *
466     * @is_ipv6: True if @address is an IPv6 address.
467     * @address: An IPv4 or IPv6 address.
468     * @port: Port number.
469     *
470     * Returns 0 on success, negative value otherwise.
471     */
472 kumaneko 2922 static inline int ccs_network_accept_acl(const bool is_ipv6,
473 kumaneko 2943 const u8 *address,
474     const u16 port)
475 kumaneko 111 {
476 kumaneko 708 int retval;
477 kumaneko 2282 current->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
478 kumaneko 2922 retval = ccs_network_entry(is_ipv6, CCS_NETWORK_TCP_ACCEPT,
479 kumaneko 2943 (const u32 *) address, ntohs(port));
480 kumaneko 2282 current->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
481 kumaneko 708 return retval;
482 kumaneko 111 }
483    
484 kumaneko 1052 /**
485 kumaneko 2922 * ccs_network_sendmsg_acl - Check permission for sendmsg() operation.
486 kumaneko 1052 *
487     * @is_ipv6: True if @address is an IPv6 address.
488     * @sock_type: Type of socket. (UDP or RAW)
489     * @address: An IPv4 or IPv6 address.
490     * @port: Port number.
491     *
492     * Returns 0 on success, negative value otherwise.
493     */
494 kumaneko 2922 static inline int ccs_network_sendmsg_acl(const bool is_ipv6,
495 kumaneko 2943 const int sock_type,
496     const u8 *address,
497     const u16 port)
498 kumaneko 111 {
499 kumaneko 1052 u8 operation;
500     if (sock_type == SOCK_DGRAM)
501 kumaneko 2915 operation = CCS_NETWORK_UDP_CONNECT;
502 kumaneko 1052 else
503 kumaneko 2915 operation = CCS_NETWORK_RAW_CONNECT;
504 kumaneko 2922 return ccs_network_entry(is_ipv6, operation,
505 kumaneko 2943 (const u32 *) address, ntohs(port));
506 kumaneko 111 }
507    
508 kumaneko 1052 /**
509 kumaneko 2922 * ccs_network_recvmsg_acl - Check permission for recvmsg() operation.
510 kumaneko 1052 *
511     * @is_ipv6: True if @address is an IPv6 address.
512     * @sock_type: Type of socket. (UDP or RAW)
513     * @address: An IPv4 or IPv6 address.
514     * @port: Port number.
515     *
516     * Returns 0 on success, negative value otherwise.
517     */
518 kumaneko 2922 static inline int ccs_network_recvmsg_acl(const bool is_ipv6,
519 kumaneko 2943 const int sock_type,
520     const u8 *address,
521     const u16 port)
522 kumaneko 111 {
523 kumaneko 708 int retval;
524 kumaneko 1052 const u8 operation
525 kumaneko 1064 = (sock_type == SOCK_DGRAM) ?
526 kumaneko 2915 CCS_NETWORK_UDP_CONNECT : CCS_NETWORK_RAW_CONNECT;
527 kumaneko 2282 current->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
528 kumaneko 2922 retval = ccs_network_entry(is_ipv6, operation,
529 kumaneko 2943 (const u32 *) address, ntohs(port));
530 kumaneko 2282 current->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
531 kumaneko 708 return retval;
532 kumaneko 111 }
533 kumaneko 2037
534     #define MAX_SOCK_ADDR 128 /* net/socket.c */
535    
536     /* Check permission for creating a socket. */
537     int ccs_socket_create_permission(int family, int type, int protocol)
538     {
539     int error = 0;
540     /* Nothing to do if I am a kernel service. */
541     if (segment_eq(get_fs(), KERNEL_DS))
542     return 0;
543 kumaneko 2282 if (family == PF_PACKET && !ccs_capable(CCS_USE_PACKET_SOCKET))
544 kumaneko 2037 return -EPERM;
545 kumaneko 2282 if (family == PF_ROUTE && !ccs_capable(CCS_USE_ROUTE_SOCKET))
546 kumaneko 2037 return -EPERM;
547     if (family != PF_INET && family != PF_INET6)
548     return 0;
549     switch (type) {
550     case SOCK_STREAM:
551 kumaneko 2282 if (!ccs_capable(CCS_INET_STREAM_SOCKET_CREATE))
552 kumaneko 2037 error = -EPERM;
553     break;
554     case SOCK_DGRAM:
555 kumaneko 2282 if (!ccs_capable(CCS_USE_INET_DGRAM_SOCKET))
556 kumaneko 2037 error = -EPERM;
557     break;
558     case SOCK_RAW:
559 kumaneko 2282 if (!ccs_capable(CCS_USE_INET_RAW_SOCKET))
560 kumaneko 2037 error = -EPERM;
561     break;
562     }
563     return error;
564     }
565    
566     /* Check permission for listening a TCP socket. */
567     int ccs_socket_listen_permission(struct socket *sock)
568     {
569     int error = 0;
570     char addr[MAX_SOCK_ADDR];
571     int addr_len;
572     /* Nothing to do if I am a kernel service. */
573     if (segment_eq(get_fs(), KERNEL_DS))
574     return 0;
575     if (sock->type != SOCK_STREAM)
576     return 0;
577     switch (sock->sk->sk_family) {
578     case PF_INET:
579     case PF_INET6:
580     break;
581     default:
582     return 0;
583     }
584 kumaneko 2282 if (!ccs_capable(CCS_INET_STREAM_SOCKET_LISTEN))
585 kumaneko 2037 return -EPERM;
586     if (sock->ops->getname(sock, (struct sockaddr *) addr, &addr_len, 0))
587     return -EPERM;
588     switch (((struct sockaddr *) addr)->sa_family) {
589     struct sockaddr_in6 *addr6;
590     struct sockaddr_in *addr4;
591     case AF_INET6:
592     addr6 = (struct sockaddr_in6 *) addr;
593 kumaneko 2922 error = ccs_network_listen_acl(true,
594 kumaneko 2943 addr6->sin6_addr.s6_addr,
595     addr6->sin6_port);
596 kumaneko 2037 break;
597     case AF_INET:
598     addr4 = (struct sockaddr_in *) addr;
599 kumaneko 2922 error = ccs_network_listen_acl(false,
600 kumaneko 2943 (u8 *) &addr4->sin_addr,
601     addr4->sin_port);
602 kumaneko 2037 break;
603     }
604     return error;
605     }
606    
607     /* Check permission for setting the remote IP address/port pair of a socket. */
608     int ccs_socket_connect_permission(struct socket *sock, struct sockaddr *addr,
609     int addr_len)
610     {
611     int error = 0;
612     const unsigned int type = sock->type;
613     /* Nothing to do if I am a kernel service. */
614     if (segment_eq(get_fs(), KERNEL_DS))
615     return 0;
616     switch (type) {
617     case SOCK_STREAM:
618     case SOCK_DGRAM:
619     case SOCK_RAW:
620     break;
621     default:
622     return 0;
623     }
624     switch (addr->sa_family) {
625     struct sockaddr_in6 *addr6;
626     struct sockaddr_in *addr4;
627     u16 port;
628     case AF_INET6:
629     if (addr_len < SIN6_LEN_RFC2133)
630     break;
631     addr6 = (struct sockaddr_in6 *) addr;
632     if (type != SOCK_RAW)
633     port = addr6->sin6_port;
634     else
635     port = htons(sock->sk->sk_protocol);
636 kumaneko 2922 error = ccs_network_connect_acl(true, type,
637 kumaneko 2943 addr6->sin6_addr.s6_addr,
638     port);
639 kumaneko 2037 break;
640     case AF_INET:
641     if (addr_len < sizeof(struct sockaddr_in))
642     break;
643     addr4 = (struct sockaddr_in *) addr;
644     if (type != SOCK_RAW)
645     port = addr4->sin_port;
646     else
647     port = htons(sock->sk->sk_protocol);
648 kumaneko 2922 error = ccs_network_connect_acl(false, type,
649 kumaneko 2943 (u8 *) &addr4->sin_addr,
650     port);
651 kumaneko 2037 break;
652     }
653     if (type != SOCK_STREAM)
654     return error;
655     switch (sock->sk->sk_family) {
656     case PF_INET:
657     case PF_INET6:
658 kumaneko 2282 if (!ccs_capable(CCS_INET_STREAM_SOCKET_CONNECT))
659 kumaneko 2037 error = -EPERM;
660     break;
661     }
662     return error;
663     }
664    
665     /* Check permission for setting the local IP address/port pair of a socket. */
666     int ccs_socket_bind_permission(struct socket *sock, struct sockaddr *addr,
667     int addr_len)
668     {
669     int error = 0;
670     const unsigned int type = sock->type;
671     /* Nothing to do if I am a kernel service. */
672     if (segment_eq(get_fs(), KERNEL_DS))
673     return 0;
674     switch (type) {
675     case SOCK_STREAM:
676     case SOCK_DGRAM:
677     case SOCK_RAW:
678     break;
679     default:
680     return 0;
681     }
682     switch (addr->sa_family) {
683     struct sockaddr_in6 *addr6;
684     struct sockaddr_in *addr4;
685     u16 port;
686     case AF_INET6:
687     if (addr_len < SIN6_LEN_RFC2133)
688     break;
689     addr6 = (struct sockaddr_in6 *) addr;
690     if (type != SOCK_RAW)
691     port = addr6->sin6_port;
692     else
693     port = htons(sock->sk->sk_protocol);
694 kumaneko 2922 error = ccs_network_bind_acl(true, type,
695 kumaneko 2943 addr6->sin6_addr.s6_addr,
696     port);
697 kumaneko 2037 break;
698     case AF_INET:
699     if (addr_len < sizeof(struct sockaddr_in))
700     break;
701     addr4 = (struct sockaddr_in *) addr;
702     if (type != SOCK_RAW)
703     port = addr4->sin_port;
704     else
705     port = htons(sock->sk->sk_protocol);
706 kumaneko 2922 error = ccs_network_bind_acl(false, type,
707 kumaneko 2943 (u8 *) &addr4->sin_addr,
708     port);
709 kumaneko 2037 break;
710     }
711     return error;
712     }
713    
714     /*
715     * Check permission for accepting a TCP socket.
716     *
717     * Currently, the LSM hook for this purpose is not provided.
718     */
719     int ccs_socket_accept_permission(struct socket *sock, struct sockaddr *addr)
720     {
721     int error = 0;
722     int addr_len;
723     /* Nothing to do if I am a kernel service. */
724     if (segment_eq(get_fs(), KERNEL_DS))
725     return 0;
726     switch (sock->sk->sk_family) {
727     case PF_INET:
728     case PF_INET6:
729     break;
730     default:
731     return 0;
732     }
733     error = sock->ops->getname(sock, addr, &addr_len, 2);
734     if (error)
735     return error;
736     switch (addr->sa_family) {
737     struct sockaddr_in6 *addr6;
738     struct sockaddr_in *addr4;
739     case AF_INET6:
740     addr6 = (struct sockaddr_in6 *) addr;
741 kumaneko 2922 error = ccs_network_accept_acl(true,
742 kumaneko 2943 addr6->sin6_addr.s6_addr,
743     addr6->sin6_port);
744 kumaneko 2037 break;
745     case AF_INET:
746     addr4 = (struct sockaddr_in *) addr;
747 kumaneko 2922 error = ccs_network_accept_acl(false,
748 kumaneko 2943 (u8 *) &addr4->sin_addr,
749     addr4->sin_port);
750 kumaneko 2037 break;
751     }
752     return error;
753     }
754    
755     /* Check permission for sending a datagram via a UDP or RAW socket. */
756     int ccs_socket_sendmsg_permission(struct socket *sock, struct sockaddr *addr,
757     int addr_len)
758     {
759     int error = 0;
760     const int type = sock->type;
761     /* Nothing to do if I am a kernel service. */
762     if (segment_eq(get_fs(), KERNEL_DS))
763     return 0;
764     if (!addr || (type != SOCK_DGRAM && type != SOCK_RAW))
765     return 0;
766     switch (addr->sa_family) {
767     struct sockaddr_in6 *addr6;
768     struct sockaddr_in *addr4;
769     u16 port;
770     case AF_INET6:
771     if (addr_len < SIN6_LEN_RFC2133)
772     break;
773     addr6 = (struct sockaddr_in6 *) addr;
774     if (type == SOCK_DGRAM)
775     port = addr6->sin6_port;
776     else
777     port = htons(sock->sk->sk_protocol);
778 kumaneko 2922 error = ccs_network_sendmsg_acl(true, type,
779 kumaneko 2943 addr6->sin6_addr.s6_addr,
780     port);
781 kumaneko 2037 break;
782     case AF_INET:
783     if (addr_len < sizeof(struct sockaddr_in))
784     break;
785     addr4 = (struct sockaddr_in *) addr;
786     if (type == SOCK_DGRAM)
787     port = addr4->sin_port;
788     else
789     port = htons(sock->sk->sk_protocol);
790 kumaneko 2922 error = ccs_network_sendmsg_acl(false, type,
791 kumaneko 2943 (u8 *) &addr4->sin_addr,
792     port);
793 kumaneko 2037 break;
794     }
795     return error;
796     }
797    
798     #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
799     #if !defined(RHEL_MAJOR) || RHEL_MAJOR != 5
800    
801     static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
802     {
803     return skb->nh.iph;
804     }
805    
806     static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
807     {
808     return skb->h.uh;
809     }
810    
811     static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
812     {
813     return skb->nh.ipv6h;
814     }
815    
816     #endif
817     #endif
818    
819 kumaneko 2459 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12)
820     static void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
821     unsigned int flags)
822     {
823     /* Clear queue. */
824     if (flags & MSG_PEEK) {
825     int clear = 0;
826     spin_lock_irq(&sk->sk_receive_queue.lock);
827     if (skb == skb_peek(&sk->sk_receive_queue)) {
828     __skb_unlink(skb, &sk->sk_receive_queue);
829     clear = 1;
830     }
831     spin_unlock_irq(&sk->sk_receive_queue.lock);
832     if (clear)
833     kfree_skb(skb);
834     }
835 kumaneko 2570 skb_free_datagram(sk, skb);
836 kumaneko 2459 }
837     #elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
838     static void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
839     unsigned int flags)
840     {
841     /* Clear queue. */
842     if (flags & MSG_PEEK) {
843     int clear = 0;
844     spin_lock_bh(&sk->sk_receive_queue.lock);
845     if (skb == skb_peek(&sk->sk_receive_queue)) {
846     __skb_unlink(skb, &sk->sk_receive_queue);
847     clear = 1;
848     }
849     spin_unlock_bh(&sk->sk_receive_queue.lock);
850     if (clear)
851     kfree_skb(skb);
852     }
853 kumaneko 2570 skb_free_datagram(sk, skb);
854 kumaneko 2459 }
855     #endif
856    
857 kumaneko 2037 /*
858     * Check permission for receiving a datagram via a UDP or RAW socket.
859     *
860     * Currently, the LSM hook for this purpose is not provided.
861     */
862 kumaneko 2459 int ccs_socket_recvmsg_permission(struct sock *sk, struct sk_buff *skb,
863     const unsigned int flags)
864 kumaneko 2037 {
865     int error = 0;
866     const unsigned int type = sk->sk_type;
867 kumaneko 2459 if (type != SOCK_DGRAM && type != SOCK_RAW)
868 kumaneko 2037 return 0;
869     /* Nothing to do if I am a kernel service. */
870     if (segment_eq(get_fs(), KERNEL_DS))
871     return 0;
872    
873     switch (sk->sk_family) {
874     struct in6_addr sin6;
875     struct in_addr sin4;
876     u16 port;
877     case PF_INET6:
878     if (type == SOCK_DGRAM) { /* UDP IPv6 */
879     if (skb->protocol == htons(ETH_P_IP)) {
880     ipv6_addr_set(&sin6, 0, 0, htonl(0xffff),
881     ip_hdr(skb)->saddr);
882     } else {
883     ipv6_addr_copy(&sin6, &ipv6_hdr(skb)->saddr);
884     }
885     port = udp_hdr(skb)->source;
886     } else { /* RAW IPv6 */
887     ipv6_addr_copy(&sin6, &ipv6_hdr(skb)->saddr);
888     port = htons(sk->sk_protocol);
889     }
890 kumaneko 2922 error = ccs_network_recvmsg_acl(true, type,
891 kumaneko 2943 (u8 *) &sin6, port);
892 kumaneko 2037 break;
893     case PF_INET:
894     if (type == SOCK_DGRAM) { /* UDP IPv4 */
895     sin4.s_addr = ip_hdr(skb)->saddr;
896     port = udp_hdr(skb)->source;
897     } else { /* RAW IPv4 */
898     sin4.s_addr = ip_hdr(skb)->saddr;
899     port = htons(sk->sk_protocol);
900     }
901 kumaneko 2922 error = ccs_network_recvmsg_acl(false, type,
902 kumaneko 2943 (u8 *) &sin4, port);
903 kumaneko 2037 break;
904     }
905     if (!error)
906     return 0;
907     /*
908     * Remove from queue if MSG_PEEK is used so that
909     * the head message from unwanted source in receive queue will not
910     * prevent the caller from picking up next message from wanted source
911     * when the caller is using MSG_PEEK flag for picking up.
912     */
913     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
914 kumaneko 2459 if (type == SOCK_DGRAM)
915     lock_sock(sk);
916 kumaneko 2037 #endif
917 kumaneko 2459 skb_kill_datagram(sk, skb, flags);
918     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
919     if (type == SOCK_DGRAM)
920     release_sock(sk);
921     #endif
922 kumaneko 2037 /* Hope less harmful than -EPERM. */
923 kumaneko 2519 return -ENOMEM;
924 kumaneko 2037 }
925 kumaneko 2459 EXPORT_SYMBOL(ccs_socket_recvmsg_permission);

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