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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3731 - (hide annotations) (download) (as text)
Fri Jun 4 01:42:54 2010 UTC (13 years, 11 months ago) by kumaneko
Original Path: branches/ccs-patch/security/ccsecurity/network.c
File MIME type: text/x-csrc
File size: 22621 byte(s)


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

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