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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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