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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3832 - (hide annotations) (download) (as text)
Wed Jul 21 06:01:31 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: 20308 byte(s)
Fix post accept()/recvmsg() hooks.
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 3832 * Version: 1.7.2+ 2010/07/21
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 kumaneko 3823 ccs_warn_log(r, "network %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 /* Check permission for creating a socket. */
366 kumaneko 3502 static int __ccs_socket_create_permission(int family, int type, int protocol)
367 kumaneko 2037 {
368     int error = 0;
369     /* Nothing to do if I am a kernel service. */
370     if (segment_eq(get_fs(), KERNEL_DS))
371     return 0;
372 kumaneko 2282 if (family == PF_PACKET && !ccs_capable(CCS_USE_PACKET_SOCKET))
373 kumaneko 2037 return -EPERM;
374 kumaneko 2282 if (family == PF_ROUTE && !ccs_capable(CCS_USE_ROUTE_SOCKET))
375 kumaneko 2037 return -EPERM;
376     if (family != PF_INET && family != PF_INET6)
377     return 0;
378     switch (type) {
379     case SOCK_STREAM:
380 kumaneko 2282 if (!ccs_capable(CCS_INET_STREAM_SOCKET_CREATE))
381 kumaneko 2037 error = -EPERM;
382     break;
383     case SOCK_DGRAM:
384 kumaneko 2282 if (!ccs_capable(CCS_USE_INET_DGRAM_SOCKET))
385 kumaneko 2037 error = -EPERM;
386     break;
387     case SOCK_RAW:
388 kumaneko 2282 if (!ccs_capable(CCS_USE_INET_RAW_SOCKET))
389 kumaneko 2037 error = -EPERM;
390     break;
391     }
392     return error;
393     }
394    
395     /* Check permission for listening a TCP socket. */
396 kumaneko 3502 static int __ccs_socket_listen_permission(struct socket *sock)
397 kumaneko 2037 {
398 kumaneko 3829 struct sockaddr_storage addr;
399 kumaneko 2037 int error = 0;
400     int addr_len;
401 kumaneko 3702 u32 *address;
402     u16 port;
403     bool is_ipv6;
404 kumaneko 2037 /* Nothing to do if I am a kernel service. */
405     if (segment_eq(get_fs(), KERNEL_DS))
406     return 0;
407     if (sock->type != SOCK_STREAM)
408     return 0;
409     switch (sock->sk->sk_family) {
410     case PF_INET:
411     case PF_INET6:
412     break;
413     default:
414     return 0;
415     }
416 kumaneko 2282 if (!ccs_capable(CCS_INET_STREAM_SOCKET_LISTEN))
417 kumaneko 2037 return -EPERM;
418 kumaneko 3829 if (sock->ops->getname(sock, (struct sockaddr *) &addr, &addr_len, 0))
419 kumaneko 2037 return -EPERM;
420 kumaneko 3829 switch (((struct sockaddr *) &addr)->sa_family) {
421 kumaneko 2037 case AF_INET6:
422 kumaneko 3702 is_ipv6 = true;
423 kumaneko 3829 address = (u32 *) ((struct sockaddr_in6 *) &addr)->sin6_addr
424 kumaneko 3702 .s6_addr;
425 kumaneko 3829 port = ((struct sockaddr_in6 *) &addr)->sin6_port;
426 kumaneko 2037 break;
427     case AF_INET:
428 kumaneko 3702 is_ipv6 = false;
429 kumaneko 3829 address = (u32 *) &((struct sockaddr_in *) &addr)->sin_addr;
430     port = ((struct sockaddr_in *) &addr)->sin_port;
431 kumaneko 2037 break;
432 kumaneko 3702 default:
433     goto skip;
434 kumaneko 2037 }
435 kumaneko 3702 error = ccs_network_entry(is_ipv6, CCS_NETWORK_TCP_LISTEN, address,
436     port);
437     skip:
438 kumaneko 2037 return error;
439     }
440    
441     /* Check permission for setting the remote IP address/port pair of a socket. */
442 kumaneko 3502 static int __ccs_socket_connect_permission(struct socket *sock,
443     struct sockaddr *addr, int addr_len)
444 kumaneko 2037 {
445     int error = 0;
446     const unsigned int type = sock->type;
447 kumaneko 3702 u32 *address;
448     u16 port;
449     u8 operation;
450     bool is_ipv6;
451 kumaneko 2037 /* Nothing to do if I am a kernel service. */
452     if (segment_eq(get_fs(), KERNEL_DS))
453     return 0;
454     switch (type) {
455     case SOCK_STREAM:
456 kumaneko 3702 operation = CCS_NETWORK_TCP_CONNECT;
457     break;
458 kumaneko 2037 case SOCK_DGRAM:
459 kumaneko 3702 operation = CCS_NETWORK_UDP_CONNECT;
460     break;
461 kumaneko 2037 case SOCK_RAW:
462 kumaneko 3702 operation = CCS_NETWORK_RAW_CONNECT;
463 kumaneko 2037 break;
464     default:
465     return 0;
466     }
467     switch (addr->sa_family) {
468     case AF_INET6:
469     if (addr_len < SIN6_LEN_RFC2133)
470 kumaneko 3702 goto skip;
471     is_ipv6 = true;
472     address = (u32 *) ((struct sockaddr_in6 *) addr)->sin6_addr
473     .s6_addr;
474     port = ((struct sockaddr_in6 *) addr)->sin6_port;
475 kumaneko 2037 break;
476     case AF_INET:
477     if (addr_len < sizeof(struct sockaddr_in))
478 kumaneko 3702 goto skip;
479     is_ipv6 = false;
480     address = (u32 *) &((struct sockaddr_in *) addr)->sin_addr;
481     port = ((struct sockaddr_in *) addr)->sin_port;
482 kumaneko 2037 break;
483 kumaneko 3702 default:
484     goto skip;
485 kumaneko 2037 }
486 kumaneko 3702 if (type == SOCK_RAW)
487     port = htons(sock->sk->sk_protocol);
488     error = ccs_network_entry(is_ipv6, operation, address, port);
489     skip:
490 kumaneko 2037 if (type != SOCK_STREAM)
491     return error;
492     switch (sock->sk->sk_family) {
493     case PF_INET:
494     case PF_INET6:
495 kumaneko 2282 if (!ccs_capable(CCS_INET_STREAM_SOCKET_CONNECT))
496 kumaneko 2037 error = -EPERM;
497     break;
498     }
499     return error;
500     }
501    
502     /* Check permission for setting the local IP address/port pair of a socket. */
503 kumaneko 3502 static int __ccs_socket_bind_permission(struct socket *sock,
504     struct sockaddr *addr, int addr_len)
505 kumaneko 2037 {
506     int error = 0;
507     const unsigned int type = sock->type;
508 kumaneko 3702 const u32 *address;
509     u16 port;
510     u8 operation;
511     bool is_ipv6;
512 kumaneko 2037 /* Nothing to do if I am a kernel service. */
513     if (segment_eq(get_fs(), KERNEL_DS))
514     return 0;
515     switch (type) {
516     case SOCK_STREAM:
517 kumaneko 3702 operation = CCS_NETWORK_TCP_BIND;
518     break;
519 kumaneko 2037 case SOCK_DGRAM:
520 kumaneko 3702 operation = CCS_NETWORK_UDP_BIND;
521     break;
522 kumaneko 2037 case SOCK_RAW:
523 kumaneko 3702 operation = CCS_NETWORK_RAW_BIND;
524 kumaneko 2037 break;
525     default:
526     return 0;
527     }
528     switch (addr->sa_family) {
529     case AF_INET6:
530     if (addr_len < SIN6_LEN_RFC2133)
531 kumaneko 3702 goto skip;
532     is_ipv6 = true;
533     address = (u32 *) ((struct sockaddr_in6 *) addr)->sin6_addr
534     .s6_addr;
535     port = ((struct sockaddr_in6 *) addr)->sin6_port;
536 kumaneko 2037 break;
537     case AF_INET:
538     if (addr_len < sizeof(struct sockaddr_in))
539 kumaneko 3702 goto skip;
540     is_ipv6 = false;
541     address = (u32 *) &((struct sockaddr_in *) addr)->sin_addr;
542     port = ((struct sockaddr_in *) addr)->sin_port;
543 kumaneko 2037 break;
544 kumaneko 3702 default:
545     goto skip;
546 kumaneko 2037 }
547 kumaneko 3702 if (type == SOCK_RAW)
548     port = htons(sock->sk->sk_protocol);
549     error = ccs_network_entry(is_ipv6, operation, address, port);
550     skip:
551 kumaneko 2037 return error;
552     }
553    
554 kumaneko 3825 /* Check permission for accepting a TCP socket. */
555     static int __ccs_socket_post_accept_permission(struct socket *sock,
556     struct socket *newsock)
557 kumaneko 2037 {
558 kumaneko 3825 struct sockaddr_storage addr;
559 kumaneko 3702 struct task_struct * const task = current;
560 kumaneko 2037 int error = 0;
561     int addr_len;
562 kumaneko 3702 u32 *address;
563     u16 port;
564     bool is_ipv6;
565 kumaneko 2037 /* Nothing to do if I am a kernel service. */
566     if (segment_eq(get_fs(), KERNEL_DS))
567     return 0;
568 kumaneko 3825 switch (newsock->sk->sk_family) {
569 kumaneko 2037 case PF_INET:
570     case PF_INET6:
571     break;
572     default:
573     return 0;
574     }
575 kumaneko 3825 error = newsock->ops->getname(newsock, (struct sockaddr *) &addr,
576     &addr_len, 2);
577 kumaneko 2037 if (error)
578     return error;
579 kumaneko 3825 switch (((struct sockaddr *) &addr)->sa_family) {
580 kumaneko 2037 case AF_INET6:
581 kumaneko 3702 is_ipv6 = true;
582 kumaneko 3825 address = (u32 *) ((struct sockaddr_in6 *) &addr)->sin6_addr
583 kumaneko 3702 .s6_addr;
584 kumaneko 3825 port = ((struct sockaddr_in6 *) &addr)->sin6_port;
585 kumaneko 2037 break;
586     case AF_INET:
587 kumaneko 3702 is_ipv6 = false;
588 kumaneko 3825 address = (u32 *) &((struct sockaddr_in *) &addr)->sin_addr;
589     port = ((struct sockaddr_in *) &addr)->sin_port;
590 kumaneko 2037 break;
591 kumaneko 3702 default:
592     goto skip;
593 kumaneko 2037 }
594 kumaneko 3702 task->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
595     error = ccs_network_entry(is_ipv6, CCS_NETWORK_TCP_ACCEPT, address,
596     port);
597     task->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
598     skip:
599 kumaneko 2037 return error;
600     }
601    
602     /* Check permission for sending a datagram via a UDP or RAW socket. */
603 kumaneko 3502 static int __ccs_socket_sendmsg_permission(struct socket *sock,
604     struct msghdr *msg, int size)
605 kumaneko 2037 {
606 kumaneko 3075 struct sockaddr *addr = (struct sockaddr *) msg->msg_name;
607     const int addr_len = msg->msg_namelen;
608 kumaneko 2037 int error = 0;
609     const int type = sock->type;
610 kumaneko 3702 u32 *address;
611     u16 port;
612     bool is_ipv6;
613     u8 operation;
614     if (!addr)
615     return 0;
616 kumaneko 2037 /* Nothing to do if I am a kernel service. */
617     if (segment_eq(get_fs(), KERNEL_DS))
618     return 0;
619 kumaneko 3702 switch (type) {
620     case SOCK_DGRAM:
621     operation = CCS_NETWORK_UDP_CONNECT;
622     break;
623     case SOCK_RAW:
624     operation = CCS_NETWORK_RAW_CONNECT;
625     break;
626     default:
627 kumaneko 2037 return 0;
628 kumaneko 3702 }
629 kumaneko 2037 switch (addr->sa_family) {
630     case AF_INET6:
631     if (addr_len < SIN6_LEN_RFC2133)
632 kumaneko 3702 goto skip;
633     is_ipv6 = true;
634     address = (u32 *) ((struct sockaddr_in6 *) addr)->sin6_addr
635     .s6_addr;
636     port = ((struct sockaddr_in6 *) addr)->sin6_port;
637 kumaneko 2037 break;
638     case AF_INET:
639     if (addr_len < sizeof(struct sockaddr_in))
640 kumaneko 3702 goto skip;
641     is_ipv6 = false;
642     address = (u32 *) &((struct sockaddr_in *) addr)->sin_addr;
643     port = ((struct sockaddr_in *) addr)->sin_port;
644 kumaneko 2037 break;
645 kumaneko 3702 default:
646     goto skip;
647 kumaneko 2037 }
648 kumaneko 3702 if (type == SOCK_RAW)
649     port = htons(sock->sk->sk_protocol);
650     error = ccs_network_entry(is_ipv6, operation, address, port);
651     skip:
652 kumaneko 2037 return error;
653     }
654    
655     #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
656     #if !defined(RHEL_MAJOR) || RHEL_MAJOR != 5
657 kumaneko 3018 #if !defined(AX_MAJOR) || AX_MAJOR != 3 || !defined(AX_MINOR) || AX_MINOR < 2
658 kumaneko 2037
659     static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
660     {
661     return skb->nh.iph;
662     }
663    
664     static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
665     {
666     return skb->h.uh;
667     }
668    
669     static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
670     {
671     return skb->nh.ipv6h;
672     }
673    
674     #endif
675     #endif
676 kumaneko 3018 #endif
677 kumaneko 2037
678 kumaneko 3825 /* Check permission for receiving a datagram via a UDP or RAW socket. */
679     static int __ccs_socket_post_recvmsg_permission(struct sock *sk,
680     struct sk_buff *skb)
681 kumaneko 2459 {
682 kumaneko 3702 struct task_struct * const task = current;
683 kumaneko 2037 int error = 0;
684     const unsigned int type = sk->sk_type;
685 kumaneko 3702 u16 port;
686     bool is_ipv6;
687     u8 operation;
688     union {
689     struct in6_addr sin6;
690     struct in_addr sin4;
691     } address;
692     switch (type) {
693     case SOCK_DGRAM:
694     operation = CCS_NETWORK_UDP_CONNECT;
695     break;
696     case SOCK_RAW:
697     operation = CCS_NETWORK_RAW_CONNECT;
698     break;
699     default:
700 kumaneko 2037 return 0;
701 kumaneko 3702 }
702 kumaneko 2037 /* Nothing to do if I am a kernel service. */
703     if (segment_eq(get_fs(), KERNEL_DS))
704     return 0;
705     switch (sk->sk_family) {
706     case PF_INET6:
707 kumaneko 3702 is_ipv6 = true;
708     if (type == SOCK_DGRAM && skb->protocol == htons(ETH_P_IP))
709     ipv6_addr_set(&address.sin6, 0, 0, htonl(0xffff),
710     ip_hdr(skb)->saddr);
711     else
712     ipv6_addr_copy(&address.sin6, &ipv6_hdr(skb)->saddr);
713 kumaneko 2037 break;
714     case PF_INET:
715 kumaneko 3702 is_ipv6 = false;
716     address.sin4.s_addr = ip_hdr(skb)->saddr;
717 kumaneko 2037 break;
718 kumaneko 3702 default:
719     goto skip;
720 kumaneko 2037 }
721 kumaneko 3702 if (type == SOCK_DGRAM)
722     port = udp_hdr(skb)->source;
723     else
724     port = htons(sk->sk_protocol);
725     task->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
726     error = ccs_network_entry(is_ipv6, operation, (u32 *) &address, port);
727     task->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
728     skip:
729 kumaneko 3825 return error;
730 kumaneko 2037 }
731 kumaneko 3502
732     void __init ccs_network_init(void)
733     {
734     ccsecurity_ops.socket_create_permission =
735     __ccs_socket_create_permission;
736     ccsecurity_ops.socket_listen_permission =
737     __ccs_socket_listen_permission;
738     ccsecurity_ops.socket_connect_permission =
739     __ccs_socket_connect_permission;
740     ccsecurity_ops.socket_bind_permission = __ccs_socket_bind_permission;
741 kumaneko 3825 ccsecurity_ops.socket_post_accept_permission =
742     __ccs_socket_post_accept_permission;
743 kumaneko 3502 ccsecurity_ops.socket_sendmsg_permission =
744     __ccs_socket_sendmsg_permission;
745 kumaneko 3825 ccsecurity_ops.socket_post_recvmsg_permission =
746     __ccs_socket_post_recvmsg_permission;
747 kumaneko 3502 }
748 kumaneko 3625
749     #endif

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