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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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