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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2922 - (hide annotations) (download) (as text)
Wed Aug 19 04:26:56 2009 UTC (14 years, 9 months ago) by kumaneko
Original Path: branches/ccs-patch/security/ccsecurity/network.c
File MIME type: text/x-csrc
File size: 24358 byte(s)


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

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