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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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