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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3167 - (hide annotations) (download) (as text)
Tue Nov 10 11:55:04 2009 UTC (14 years, 6 months ago) by kumaneko
Original Path: trunk/1.7.x/ccs-patch/security/ccsecurity/network.c
File MIME type: text/x-csrc
File size: 24356 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 3167 * Version: 1.7.1 2009/11/11
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 kumaneko 2958 == CCS_CONFIG_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 kumaneko 2958 if (r.mode != CCS_CONFIG_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 3046 const int error = ccs_network_entry2(is_ipv6, operation, address,
248     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 3046 static inline int ccs_network_listen_acl(const bool is_ipv6, const u8 *address,
398 kumaneko 2943 const u16 port)
399 kumaneko 111 {
400 kumaneko 2922 return ccs_network_entry(is_ipv6, CCS_NETWORK_TCP_LISTEN,
401 kumaneko 2943 (const u32 *) address, ntohs(port));
402 kumaneko 111 }
403    
404 kumaneko 1052 /**
405 kumaneko 2922 * ccs_network_connect_acl - Check permission for connect() operation.
406 kumaneko 1052 *
407     * @is_ipv6: True if @address is an IPv6 address.
408     * @sock_type: Type of socket. (TCP or UDP or RAW)
409     * @address: An IPv4 or IPv6 address.
410     * @port: Port number.
411     *
412     * Returns 0 on success, negative value otherwise.
413     */
414 kumaneko 2922 static inline int ccs_network_connect_acl(const bool is_ipv6,
415 kumaneko 2943 const int sock_type,
416 kumaneko 3046 const u8 *address, const u16 port)
417 kumaneko 111 {
418 kumaneko 1052 u8 operation;
419     switch (sock_type) {
420     case SOCK_STREAM:
421 kumaneko 2915 operation = CCS_NETWORK_TCP_CONNECT;
422 kumaneko 1052 break;
423     case SOCK_DGRAM:
424 kumaneko 2915 operation = CCS_NETWORK_UDP_CONNECT;
425 kumaneko 1052 break;
426     default:
427 kumaneko 2915 operation = CCS_NETWORK_RAW_CONNECT;
428 kumaneko 1052 }
429 kumaneko 2922 return ccs_network_entry(is_ipv6, operation,
430 kumaneko 2943 (const u32 *) address, ntohs(port));
431 kumaneko 111 }
432    
433 kumaneko 1052 /**
434 kumaneko 2922 * ccs_network_bind_acl - Check permission for bind() operation.
435 kumaneko 1052 *
436     * @is_ipv6: True if @address is an IPv6 address.
437     * @sock_type: Type of socket. (TCP or UDP or RAW)
438     * @address: An IPv4 or IPv6 address.
439     * @port: Port number.
440     *
441     * Returns 0 on success, negative value otherwise.
442     */
443 kumaneko 2922 static int ccs_network_bind_acl(const bool is_ipv6, const int sock_type,
444 kumaneko 2943 const u8 *address, const u16 port)
445 kumaneko 111 {
446 kumaneko 1052 u8 operation;
447     switch (sock_type) {
448     case SOCK_STREAM:
449 kumaneko 2915 operation = CCS_NETWORK_TCP_BIND;
450 kumaneko 1052 break;
451     case SOCK_DGRAM:
452 kumaneko 2915 operation = CCS_NETWORK_UDP_BIND;
453 kumaneko 1052 break;
454     default:
455 kumaneko 2915 operation = CCS_NETWORK_RAW_BIND;
456 kumaneko 1052 }
457 kumaneko 2922 return ccs_network_entry(is_ipv6, operation,
458 kumaneko 2943 (const u32 *) address, ntohs(port));
459 kumaneko 111 }
460    
461 kumaneko 1052 /**
462 kumaneko 2922 * ccs_network_accept_acl - Check permission for accept() operation.
463 kumaneko 1052 *
464     * @is_ipv6: True if @address is an IPv6 address.
465     * @address: An IPv4 or IPv6 address.
466     * @port: Port number.
467     *
468     * Returns 0 on success, negative value otherwise.
469     */
470 kumaneko 3046 static inline int ccs_network_accept_acl(const bool is_ipv6, const u8 *address,
471 kumaneko 2943 const u16 port)
472 kumaneko 111 {
473 kumaneko 708 int retval;
474 kumaneko 2282 current->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
475 kumaneko 2922 retval = ccs_network_entry(is_ipv6, CCS_NETWORK_TCP_ACCEPT,
476 kumaneko 2943 (const u32 *) address, ntohs(port));
477 kumaneko 2282 current->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
478 kumaneko 708 return retval;
479 kumaneko 111 }
480    
481 kumaneko 1052 /**
482 kumaneko 2922 * ccs_network_sendmsg_acl - Check permission for sendmsg() operation.
483 kumaneko 1052 *
484     * @is_ipv6: True if @address is an IPv6 address.
485     * @sock_type: Type of socket. (UDP or RAW)
486     * @address: An IPv4 or IPv6 address.
487     * @port: Port number.
488     *
489     * Returns 0 on success, negative value otherwise.
490     */
491 kumaneko 2922 static inline int ccs_network_sendmsg_acl(const bool is_ipv6,
492 kumaneko 2943 const int sock_type,
493 kumaneko 3046 const u8 *address, const u16 port)
494 kumaneko 111 {
495 kumaneko 1052 u8 operation;
496     if (sock_type == SOCK_DGRAM)
497 kumaneko 2915 operation = CCS_NETWORK_UDP_CONNECT;
498 kumaneko 1052 else
499 kumaneko 2915 operation = CCS_NETWORK_RAW_CONNECT;
500 kumaneko 2922 return ccs_network_entry(is_ipv6, operation,
501 kumaneko 2943 (const u32 *) address, ntohs(port));
502 kumaneko 111 }
503    
504 kumaneko 1052 /**
505 kumaneko 2922 * ccs_network_recvmsg_acl - Check permission for recvmsg() operation.
506 kumaneko 1052 *
507     * @is_ipv6: True if @address is an IPv6 address.
508     * @sock_type: Type of socket. (UDP or RAW)
509     * @address: An IPv4 or IPv6 address.
510     * @port: Port number.
511     *
512     * Returns 0 on success, negative value otherwise.
513     */
514 kumaneko 2922 static inline int ccs_network_recvmsg_acl(const bool is_ipv6,
515 kumaneko 2943 const int sock_type,
516 kumaneko 3046 const u8 *address, const u16 port)
517 kumaneko 111 {
518 kumaneko 708 int retval;
519 kumaneko 1052 const u8 operation
520 kumaneko 1064 = (sock_type == SOCK_DGRAM) ?
521 kumaneko 2915 CCS_NETWORK_UDP_CONNECT : CCS_NETWORK_RAW_CONNECT;
522 kumaneko 2282 current->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
523 kumaneko 2922 retval = ccs_network_entry(is_ipv6, operation,
524 kumaneko 2943 (const u32 *) address, ntohs(port));
525 kumaneko 2282 current->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
526 kumaneko 708 return retval;
527 kumaneko 111 }
528 kumaneko 2037
529     #define MAX_SOCK_ADDR 128 /* net/socket.c */
530    
531     /* Check permission for creating a socket. */
532     int ccs_socket_create_permission(int family, int type, int protocol)
533     {
534     int error = 0;
535     /* Nothing to do if I am a kernel service. */
536     if (segment_eq(get_fs(), KERNEL_DS))
537     return 0;
538 kumaneko 2282 if (family == PF_PACKET && !ccs_capable(CCS_USE_PACKET_SOCKET))
539 kumaneko 2037 return -EPERM;
540 kumaneko 2282 if (family == PF_ROUTE && !ccs_capable(CCS_USE_ROUTE_SOCKET))
541 kumaneko 2037 return -EPERM;
542     if (family != PF_INET && family != PF_INET6)
543     return 0;
544     switch (type) {
545     case SOCK_STREAM:
546 kumaneko 2282 if (!ccs_capable(CCS_INET_STREAM_SOCKET_CREATE))
547 kumaneko 2037 error = -EPERM;
548     break;
549     case SOCK_DGRAM:
550 kumaneko 2282 if (!ccs_capable(CCS_USE_INET_DGRAM_SOCKET))
551 kumaneko 2037 error = -EPERM;
552     break;
553     case SOCK_RAW:
554 kumaneko 2282 if (!ccs_capable(CCS_USE_INET_RAW_SOCKET))
555 kumaneko 2037 error = -EPERM;
556     break;
557     }
558     return error;
559     }
560    
561     /* Check permission for listening a TCP socket. */
562     int ccs_socket_listen_permission(struct socket *sock)
563     {
564     int error = 0;
565     char addr[MAX_SOCK_ADDR];
566     int addr_len;
567     /* Nothing to do if I am a kernel service. */
568     if (segment_eq(get_fs(), KERNEL_DS))
569     return 0;
570     if (sock->type != SOCK_STREAM)
571     return 0;
572     switch (sock->sk->sk_family) {
573     case PF_INET:
574     case PF_INET6:
575     break;
576     default:
577     return 0;
578     }
579 kumaneko 2282 if (!ccs_capable(CCS_INET_STREAM_SOCKET_LISTEN))
580 kumaneko 2037 return -EPERM;
581     if (sock->ops->getname(sock, (struct sockaddr *) addr, &addr_len, 0))
582     return -EPERM;
583     switch (((struct sockaddr *) addr)->sa_family) {
584     struct sockaddr_in6 *addr6;
585     struct sockaddr_in *addr4;
586     case AF_INET6:
587     addr6 = (struct sockaddr_in6 *) addr;
588 kumaneko 2922 error = ccs_network_listen_acl(true,
589 kumaneko 2943 addr6->sin6_addr.s6_addr,
590     addr6->sin6_port);
591 kumaneko 2037 break;
592     case AF_INET:
593     addr4 = (struct sockaddr_in *) addr;
594 kumaneko 2922 error = ccs_network_listen_acl(false,
595 kumaneko 2943 (u8 *) &addr4->sin_addr,
596     addr4->sin_port);
597 kumaneko 2037 break;
598     }
599     return error;
600     }
601    
602     /* Check permission for setting the remote IP address/port pair of a socket. */
603     int ccs_socket_connect_permission(struct socket *sock, struct sockaddr *addr,
604     int addr_len)
605     {
606     int error = 0;
607     const unsigned int type = sock->type;
608     /* Nothing to do if I am a kernel service. */
609     if (segment_eq(get_fs(), KERNEL_DS))
610     return 0;
611     switch (type) {
612     case SOCK_STREAM:
613     case SOCK_DGRAM:
614     case SOCK_RAW:
615     break;
616     default:
617     return 0;
618     }
619     switch (addr->sa_family) {
620     struct sockaddr_in6 *addr6;
621     struct sockaddr_in *addr4;
622     u16 port;
623     case AF_INET6:
624     if (addr_len < SIN6_LEN_RFC2133)
625     break;
626     addr6 = (struct sockaddr_in6 *) addr;
627     if (type != SOCK_RAW)
628     port = addr6->sin6_port;
629     else
630     port = htons(sock->sk->sk_protocol);
631 kumaneko 2922 error = ccs_network_connect_acl(true, type,
632 kumaneko 2943 addr6->sin6_addr.s6_addr,
633     port);
634 kumaneko 2037 break;
635     case AF_INET:
636     if (addr_len < sizeof(struct sockaddr_in))
637     break;
638     addr4 = (struct sockaddr_in *) addr;
639     if (type != SOCK_RAW)
640     port = addr4->sin_port;
641     else
642     port = htons(sock->sk->sk_protocol);
643 kumaneko 2922 error = ccs_network_connect_acl(false, type,
644 kumaneko 2943 (u8 *) &addr4->sin_addr,
645     port);
646 kumaneko 2037 break;
647     }
648     if (type != SOCK_STREAM)
649     return error;
650     switch (sock->sk->sk_family) {
651     case PF_INET:
652     case PF_INET6:
653 kumaneko 2282 if (!ccs_capable(CCS_INET_STREAM_SOCKET_CONNECT))
654 kumaneko 2037 error = -EPERM;
655     break;
656     }
657     return error;
658     }
659    
660     /* Check permission for setting the local IP address/port pair of a socket. */
661     int ccs_socket_bind_permission(struct socket *sock, struct sockaddr *addr,
662     int addr_len)
663     {
664     int error = 0;
665     const unsigned int type = sock->type;
666     /* Nothing to do if I am a kernel service. */
667     if (segment_eq(get_fs(), KERNEL_DS))
668     return 0;
669     switch (type) {
670     case SOCK_STREAM:
671     case SOCK_DGRAM:
672     case SOCK_RAW:
673     break;
674     default:
675     return 0;
676     }
677     switch (addr->sa_family) {
678     struct sockaddr_in6 *addr6;
679     struct sockaddr_in *addr4;
680     u16 port;
681     case AF_INET6:
682     if (addr_len < SIN6_LEN_RFC2133)
683     break;
684     addr6 = (struct sockaddr_in6 *) addr;
685     if (type != SOCK_RAW)
686     port = addr6->sin6_port;
687     else
688     port = htons(sock->sk->sk_protocol);
689 kumaneko 2922 error = ccs_network_bind_acl(true, type,
690 kumaneko 2943 addr6->sin6_addr.s6_addr,
691     port);
692 kumaneko 2037 break;
693     case AF_INET:
694     if (addr_len < sizeof(struct sockaddr_in))
695     break;
696     addr4 = (struct sockaddr_in *) addr;
697     if (type != SOCK_RAW)
698     port = addr4->sin_port;
699     else
700     port = htons(sock->sk->sk_protocol);
701 kumaneko 2922 error = ccs_network_bind_acl(false, type,
702 kumaneko 2943 (u8 *) &addr4->sin_addr,
703     port);
704 kumaneko 2037 break;
705     }
706     return error;
707     }
708    
709     /*
710     * Check permission for accepting a TCP socket.
711     *
712     * Currently, the LSM hook for this purpose is not provided.
713     */
714     int ccs_socket_accept_permission(struct socket *sock, struct sockaddr *addr)
715     {
716     int error = 0;
717     int addr_len;
718     /* Nothing to do if I am a kernel service. */
719     if (segment_eq(get_fs(), KERNEL_DS))
720     return 0;
721     switch (sock->sk->sk_family) {
722     case PF_INET:
723     case PF_INET6:
724     break;
725     default:
726     return 0;
727     }
728     error = sock->ops->getname(sock, addr, &addr_len, 2);
729     if (error)
730     return error;
731     switch (addr->sa_family) {
732     struct sockaddr_in6 *addr6;
733     struct sockaddr_in *addr4;
734     case AF_INET6:
735     addr6 = (struct sockaddr_in6 *) addr;
736 kumaneko 2922 error = ccs_network_accept_acl(true,
737 kumaneko 2943 addr6->sin6_addr.s6_addr,
738     addr6->sin6_port);
739 kumaneko 2037 break;
740     case AF_INET:
741     addr4 = (struct sockaddr_in *) addr;
742 kumaneko 2922 error = ccs_network_accept_acl(false,
743 kumaneko 2943 (u8 *) &addr4->sin_addr,
744     addr4->sin_port);
745 kumaneko 2037 break;
746     }
747     return error;
748     }
749    
750     /* Check permission for sending a datagram via a UDP or RAW socket. */
751 kumaneko 3075 int ccs_socket_sendmsg_permission(struct socket *sock, struct msghdr *msg,
752     int size)
753 kumaneko 2037 {
754 kumaneko 3075 struct sockaddr *addr = (struct sockaddr *) msg->msg_name;
755     const int addr_len = msg->msg_namelen;
756 kumaneko 2037 int error = 0;
757     const int type = sock->type;
758     /* Nothing to do if I am a kernel service. */
759     if (segment_eq(get_fs(), KERNEL_DS))
760     return 0;
761     if (!addr || (type != SOCK_DGRAM && type != SOCK_RAW))
762     return 0;
763     switch (addr->sa_family) {
764     struct sockaddr_in6 *addr6;
765     struct sockaddr_in *addr4;
766     u16 port;
767     case AF_INET6:
768     if (addr_len < SIN6_LEN_RFC2133)
769     break;
770     addr6 = (struct sockaddr_in6 *) addr;
771     if (type == SOCK_DGRAM)
772     port = addr6->sin6_port;
773     else
774     port = htons(sock->sk->sk_protocol);
775 kumaneko 2922 error = ccs_network_sendmsg_acl(true, type,
776 kumaneko 2943 addr6->sin6_addr.s6_addr,
777     port);
778 kumaneko 2037 break;
779     case AF_INET:
780     if (addr_len < sizeof(struct sockaddr_in))
781     break;
782     addr4 = (struct sockaddr_in *) addr;
783     if (type == SOCK_DGRAM)
784     port = addr4->sin_port;
785     else
786     port = htons(sock->sk->sk_protocol);
787 kumaneko 2922 error = ccs_network_sendmsg_acl(false, type,
788 kumaneko 3046 (u8 *) &addr4->sin_addr, port);
789 kumaneko 2037 break;
790     }
791     return error;
792     }
793    
794     #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
795     #if !defined(RHEL_MAJOR) || RHEL_MAJOR != 5
796 kumaneko 3018 #if !defined(AX_MAJOR) || AX_MAJOR != 3 || !defined(AX_MINOR) || AX_MINOR < 2
797 kumaneko 2037
798     static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
799     {
800     return skb->nh.iph;
801     }
802    
803     static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
804     {
805     return skb->h.uh;
806     }
807    
808     static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
809     {
810     return skb->nh.ipv6h;
811     }
812    
813     #endif
814     #endif
815 kumaneko 3018 #endif
816 kumaneko 2037
817 kumaneko 2459 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 12)
818     static void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
819     unsigned int flags)
820     {
821     /* Clear queue. */
822     if (flags & MSG_PEEK) {
823     int clear = 0;
824     spin_lock_irq(&sk->sk_receive_queue.lock);
825     if (skb == skb_peek(&sk->sk_receive_queue)) {
826     __skb_unlink(skb, &sk->sk_receive_queue);
827     clear = 1;
828     }
829     spin_unlock_irq(&sk->sk_receive_queue.lock);
830     if (clear)
831     kfree_skb(skb);
832     }
833 kumaneko 2570 skb_free_datagram(sk, skb);
834 kumaneko 2459 }
835     #elif LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 16)
836     static void skb_kill_datagram(struct sock *sk, struct sk_buff *skb,
837     unsigned int flags)
838     {
839     /* Clear queue. */
840     if (flags & MSG_PEEK) {
841     int clear = 0;
842     spin_lock_bh(&sk->sk_receive_queue.lock);
843     if (skb == skb_peek(&sk->sk_receive_queue)) {
844     __skb_unlink(skb, &sk->sk_receive_queue);
845     clear = 1;
846     }
847     spin_unlock_bh(&sk->sk_receive_queue.lock);
848     if (clear)
849     kfree_skb(skb);
850     }
851 kumaneko 2570 skb_free_datagram(sk, skb);
852 kumaneko 2459 }
853     #endif
854    
855 kumaneko 2037 /*
856     * Check permission for receiving a datagram via a UDP or RAW socket.
857     *
858     * Currently, the LSM hook for this purpose is not provided.
859     */
860 kumaneko 2459 int ccs_socket_recvmsg_permission(struct sock *sk, struct sk_buff *skb,
861     const unsigned int flags)
862 kumaneko 2037 {
863     int error = 0;
864     const unsigned int type = sk->sk_type;
865 kumaneko 2459 if (type != SOCK_DGRAM && type != SOCK_RAW)
866 kumaneko 2037 return 0;
867     /* Nothing to do if I am a kernel service. */
868     if (segment_eq(get_fs(), KERNEL_DS))
869     return 0;
870    
871     switch (sk->sk_family) {
872     struct in6_addr sin6;
873     struct in_addr sin4;
874     u16 port;
875     case PF_INET6:
876     if (type == SOCK_DGRAM) { /* UDP IPv6 */
877     if (skb->protocol == htons(ETH_P_IP)) {
878     ipv6_addr_set(&sin6, 0, 0, htonl(0xffff),
879     ip_hdr(skb)->saddr);
880     } else {
881     ipv6_addr_copy(&sin6, &ipv6_hdr(skb)->saddr);
882     }
883     port = udp_hdr(skb)->source;
884     } else { /* RAW IPv6 */
885     ipv6_addr_copy(&sin6, &ipv6_hdr(skb)->saddr);
886     port = htons(sk->sk_protocol);
887     }
888 kumaneko 2922 error = ccs_network_recvmsg_acl(true, type,
889 kumaneko 2943 (u8 *) &sin6, port);
890 kumaneko 2037 break;
891     case PF_INET:
892     if (type == SOCK_DGRAM) { /* UDP IPv4 */
893     sin4.s_addr = ip_hdr(skb)->saddr;
894     port = udp_hdr(skb)->source;
895     } else { /* RAW IPv4 */
896     sin4.s_addr = ip_hdr(skb)->saddr;
897     port = htons(sk->sk_protocol);
898     }
899 kumaneko 2922 error = ccs_network_recvmsg_acl(false, type,
900 kumaneko 2943 (u8 *) &sin4, port);
901 kumaneko 2037 break;
902     }
903     if (!error)
904     return 0;
905     /*
906     * Remove from queue if MSG_PEEK is used so that
907     * the head message from unwanted source in receive queue will not
908     * prevent the caller from picking up next message from wanted source
909     * when the caller is using MSG_PEEK flag for picking up.
910     */
911     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
912 kumaneko 2459 if (type == SOCK_DGRAM)
913     lock_sock(sk);
914 kumaneko 2037 #endif
915 kumaneko 2459 skb_kill_datagram(sk, skb, flags);
916     #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)
917     if (type == SOCK_DGRAM)
918     release_sock(sk);
919     #endif
920 kumaneko 2037 /* Hope less harmful than -EPERM. */
921 kumaneko 2519 return -ENOMEM;
922 kumaneko 2037 }
923 kumaneko 2459 EXPORT_SYMBOL(ccs_socket_recvmsg_permission);

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