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

Subversion リポジトリの参照

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3949 - (show annotations) (download) (as text)
Sun Sep 5 11:50:03 2010 UTC (13 years, 9 months ago) by kumaneko
File MIME type: text/x-csrc
File size: 25348 byte(s)


1 /*
2 * security/ccsecurity/network.c
3 *
4 * Copyright (C) 2005-2010 NTT DATA CORPORATION
5 *
6 * Version: 1.8.0-pre 2010/09/01
7 *
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 #include <linux/net.h>
14 #include <linux/inet.h>
15 #include <linux/in.h>
16 #include <linux/in6.h>
17 #include <linux/un.h>
18 #include <net/sock.h>
19 #include <net/af_unix.h>
20 #include <net/ip.h>
21 #include <net/ipv6.h>
22 #include <net/udp.h>
23 #include "internal.h"
24
25 struct ccs_inet_addr_info {
26 u16 port; /* In network byte order. */
27 const u32 *address; /* In network byte order. */
28 bool is_ipv6;
29 };
30
31 struct ccs_unix_addr_info {
32 u8 *addr;
33 unsigned int addr_len;
34 };
35
36 struct ccs_addr_info {
37 u8 protocol;
38 u8 operation;
39 struct ccs_inet_addr_info inet;
40 struct ccs_unix_addr_info unix0;
41 };
42
43 const char *ccs_proto_keyword[CCS_SOCK_MAX] = {
44 [SOCK_STREAM] = "stream",
45 [SOCK_DGRAM] = "dgram",
46 [SOCK_RAW] = "raw",
47 [SOCK_SEQPACKET] = "seqpacket",
48 };
49
50 const char *ccs_socket_keyword[CCS_MAX_NETWORK_OPERATION] = {
51 [CCS_NETWORK_BIND] = "bind",
52 [CCS_NETWORK_LISTEN] = "listen",
53 [CCS_NETWORK_CONNECT] = "connect",
54 [CCS_NETWORK_ACCEPT] = "accept",
55 [CCS_NETWORK_SEND] = "send",
56 [CCS_NETWORK_RECV] = "recv",
57 };
58
59 static int ccs_audit_net_log(struct ccs_request_info *r, const char *family,
60 const u8 proto, const u8 ope, const char *address)
61 {
62 const char *protocol = ccs_proto_keyword[proto];
63 const char *operation = ccs_socket_keyword[ope];
64 ccs_write_log(r, "network %s %s %s %s\n", family,
65 protocol, operation, address);
66 if (r->granted)
67 return 0;
68 ccs_warn_log(r, "network %s %s %s %s", family, protocol, operation,
69 address);
70 return ccs_supervisor(r, "network %s %s %s %s\n", family, protocol,
71 operation, address);
72 }
73
74 /**
75 * ccs_audit_inet_log - Audit INET network log.
76 *
77 * @r: Pointer to "struct ccs_request_info".
78 *
79 * Returns 0 on success, negative value otherwise.
80 */
81 static int ccs_audit_inet_log(struct ccs_request_info *r)
82 {
83 char buf[128];
84 int len;
85 const u32 *address = r->param.inet_network.address;
86 if (r->param.inet_network.is_ipv6)
87 ccs_print_ipv6(buf, sizeof(buf), (const struct in6_addr *)
88 address, (const struct in6_addr *) address);
89 else
90 ccs_print_ipv4(buf, sizeof(buf), r->param.inet_network.ip,
91 r->param.inet_network.ip);
92 len = strlen(buf);
93 snprintf(buf + len, sizeof(buf) - len, " %u",
94 r->param.inet_network.port);
95 return ccs_audit_net_log(r, "inet", r->param.inet_network.protocol,
96 r->param.inet_network.operation, buf);
97 }
98
99 /**
100 * ccs_audit_unix_log - Audit UNIX network log.
101 *
102 * @r: Pointer to "struct ccs_request_info".
103 *
104 * Returns 0 on success, negative value otherwise.
105 */
106 static int ccs_audit_unix_log(struct ccs_request_info *r)
107 {
108 return ccs_audit_net_log(r, "unix", r->param.unix_network.protocol,
109 r->param.unix_network.operation,
110 r->param.unix_network.address->name);
111 }
112
113 /**
114 * ccs_parse_ip_address - Parse an IP address.
115 *
116 * @address: String to parse.
117 * @min: Pointer to store min address.
118 * @max: Pointer to store max address.
119 *
120 * Returns CCS_IP_ADDRESS_TYPE_IPv6 if @address is an IPv6,
121 * CCS_IP_ADDRESS_TYPE_IPv4 if @address is an IPv4,
122 * CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP otherwise.
123 */
124 int ccs_parse_ip_address(char *address, u16 *min, u16 *max)
125 {
126 int count = sscanf(address, "%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx"
127 "-%hx:%hx:%hx:%hx:%hx:%hx:%hx:%hx",
128 &min[0], &min[1], &min[2], &min[3],
129 &min[4], &min[5], &min[6], &min[7],
130 &max[0], &max[1], &max[2], &max[3],
131 &max[4], &max[5], &max[6], &max[7]);
132 if (count == 8 || count == 16) {
133 u8 i;
134 if (count == 8)
135 memmove(max, min, sizeof(u16) * 8);
136 for (i = 0; i < 8; i++) {
137 min[i] = htons(min[i]);
138 max[i] = htons(max[i]);
139 }
140 return CCS_IP_ADDRESS_TYPE_IPv6;
141 }
142 count = sscanf(address, "%hu.%hu.%hu.%hu-%hu.%hu.%hu.%hu",
143 &min[0], &min[1], &min[2], &min[3],
144 &max[0], &max[1], &max[2], &max[3]);
145 if (count == 4 || count == 8) {
146 u32 ip = htonl((((u8) min[0]) << 24) + (((u8) min[1]) << 16)
147 + (((u8) min[2]) << 8) + (u8) min[3]);
148 memmove(min, &ip, sizeof(ip));
149 if (count == 8)
150 ip = htonl((((u8) max[0]) << 24)
151 + (((u8) max[1]) << 16)
152 + (((u8) max[2]) << 8) + (u8) max[3]);
153 memmove(max, &ip, sizeof(ip));
154 return CCS_IP_ADDRESS_TYPE_IPv4;
155 }
156 return CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP;
157 }
158
159 /**
160 * ccs_print_ipv4 - Print an IPv4 address.
161 *
162 * @buffer: Buffer to write to.
163 * @buffer_len: Size of @buffer.
164 * @min_ip: Min address in host byte order.
165 * @max_ip: Max address in host byte order.
166 *
167 * Returns nothing.
168 */
169 void ccs_print_ipv4(char *buffer, const int buffer_len,
170 const u32 min_ip, const u32 max_ip)
171 {
172 memset(buffer, 0, buffer_len);
173 snprintf(buffer, buffer_len - 1, "%u.%u.%u.%u%c%u.%u.%u.%u",
174 HIPQUAD(min_ip), min_ip == max_ip ? '\0' : '-',
175 HIPQUAD(max_ip));
176 }
177
178 #if !defined(NIP6)
179 #define NIP6(addr) \
180 ntohs((addr).s6_addr16[0]), ntohs((addr).s6_addr16[1]), \
181 ntohs((addr).s6_addr16[2]), ntohs((addr).s6_addr16[3]), \
182 ntohs((addr).s6_addr16[4]), ntohs((addr).s6_addr16[5]), \
183 ntohs((addr).s6_addr16[6]), ntohs((addr).s6_addr16[7])
184 #endif
185
186 /**
187 * ccs_print_ipv6 - Print an IPv6 address.
188 *
189 * @buffer: Buffer to write to.
190 * @buffer_len: Size of @buffer.
191 * @min_ip: Pointer to "struct in6_addr".
192 * @max_ip: Pointer to "struct in6_addr".
193 *
194 * Returns nothing.
195 */
196 void ccs_print_ipv6(char *buffer, const int buffer_len,
197 const struct in6_addr *min_ip,
198 const struct in6_addr *max_ip)
199 {
200 memset(buffer, 0, buffer_len);
201 snprintf(buffer, buffer_len - 1,
202 "%x:%x:%x:%x:%x:%x:%x:%x%c%x:%x:%x:%x:%x:%x:%x:%x",
203 NIP6(*min_ip), min_ip == max_ip ? '\0' : '-',
204 NIP6(*max_ip));
205 }
206
207 static bool ccs_check_inet_acl(struct ccs_request_info *r,
208 const struct ccs_acl_info *ptr)
209 {
210 const struct ccs_inet_acl *acl = container_of(ptr, typeof(*acl), head);
211 bool ret;
212 if (!(acl->perm & (1 << r->param.inet_network.operation)) ||
213 !ccs_compare_number_union(r->param.inet_network.port, &acl->port))
214 return false;
215 switch (acl->address_type) {
216 case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP:
217 ret = ccs_address_matches_group(r->param.inet_network.is_ipv6,
218 r->param.inet_network.address,
219 acl->address.group);
220 break;
221 case CCS_IP_ADDRESS_TYPE_IPv4:
222 ret = !r->param.inet_network.is_ipv6 &&
223 acl->address.ipv4.min <= r->param.inet_network.ip &&
224 r->param.inet_network.ip <= acl->address.ipv4.max;
225 break;
226 default:
227 ret = r->param.inet_network.is_ipv6 &&
228 memcmp(acl->address.ipv6.min,
229 r->param.inet_network.address, 16) <= 0 &&
230 memcmp(r->param.inet_network.address,
231 acl->address.ipv6.max, 16) <= 0;
232 break;
233 }
234 return ret;
235 }
236
237 static bool ccs_check_unix_acl(struct ccs_request_info *r,
238 const struct ccs_acl_info *ptr)
239 {
240 const struct ccs_unix_acl *acl = container_of(ptr, typeof(*acl), head);
241 return (acl->perm & (1 << r->param.unix_network.operation)) &&
242 ccs_compare_name_union(r->param.unix_network.address,
243 &acl->name);
244 }
245
246 static const u8
247 ccs_inet2mac[CCS_SOCK_MAX][CCS_MAX_NETWORK_OPERATION] = {
248 [SOCK_STREAM] = {
249 [CCS_NETWORK_BIND] = CCS_MAC_NETWORK_INET_STREAM_BIND,
250 [CCS_NETWORK_LISTEN] = CCS_MAC_NETWORK_INET_STREAM_LISTEN,
251 [CCS_NETWORK_CONNECT] = CCS_MAC_NETWORK_INET_STREAM_CONNECT,
252 [CCS_NETWORK_ACCEPT] = CCS_MAC_NETWORK_INET_STREAM_ACCEPT,
253 },
254 [SOCK_DGRAM] = {
255 [CCS_NETWORK_BIND] = CCS_MAC_NETWORK_INET_DGRAM_BIND,
256 [CCS_NETWORK_SEND] = CCS_MAC_NETWORK_INET_DGRAM_SEND,
257 [CCS_NETWORK_RECV] = CCS_MAC_NETWORK_INET_DGRAM_RECV,
258 },
259 [SOCK_RAW] = {
260 [CCS_NETWORK_BIND] = CCS_MAC_NETWORK_INET_RAW_BIND,
261 [CCS_NETWORK_SEND] = CCS_MAC_NETWORK_INET_RAW_SEND,
262 [CCS_NETWORK_RECV] = CCS_MAC_NETWORK_INET_RAW_RECV,
263 },
264 };
265
266 static const u8
267 ccs_unix2mac[CCS_SOCK_MAX][CCS_MAX_NETWORK_OPERATION] = {
268 [SOCK_STREAM] = {
269 [CCS_NETWORK_BIND] = CCS_MAC_NETWORK_UNIX_STREAM_BIND,
270 [CCS_NETWORK_LISTEN] = CCS_MAC_NETWORK_UNIX_STREAM_LISTEN,
271 [CCS_NETWORK_CONNECT] = CCS_MAC_NETWORK_UNIX_STREAM_CONNECT,
272 [CCS_NETWORK_ACCEPT] = CCS_MAC_NETWORK_UNIX_STREAM_ACCEPT,
273 },
274 [SOCK_DGRAM] = {
275 [CCS_NETWORK_BIND] = CCS_MAC_NETWORK_UNIX_DGRAM_BIND,
276 [CCS_NETWORK_SEND] = CCS_MAC_NETWORK_UNIX_DGRAM_SEND,
277 [CCS_NETWORK_RECV] = CCS_MAC_NETWORK_UNIX_DGRAM_RECV,
278 },
279 [SOCK_SEQPACKET] = {
280 [CCS_NETWORK_BIND] = CCS_MAC_NETWORK_UNIX_SEQPACKET_BIND,
281 [CCS_NETWORK_LISTEN] = CCS_MAC_NETWORK_UNIX_SEQPACKET_LISTEN,
282 [CCS_NETWORK_CONNECT] = CCS_MAC_NETWORK_UNIX_SEQPACKET_CONNECT,
283 [CCS_NETWORK_ACCEPT] = CCS_MAC_NETWORK_UNIX_SEQPACKET_ACCEPT,
284 },
285 };
286
287 static bool ccs_same_inet_acl(const struct ccs_acl_info *a,
288 const struct ccs_acl_info *b)
289 {
290 const struct ccs_inet_acl *p1 = container_of(a, typeof(*p1), head);
291 const struct ccs_inet_acl *p2 = container_of(b, typeof(*p2), head);
292 return p1->protocol == p2->protocol &&
293 p1->address_type == p2->address_type &&
294 p1->address.ipv4.min == p2->address.ipv4.min &&
295 p1->address.ipv6.min == p2->address.ipv6.min &&
296 p1->address.ipv4.max == p2->address.ipv4.max &&
297 p1->address.ipv6.max == p2->address.ipv6.max &&
298 p1->address.group == p2->address.group &&
299 ccs_same_number_union(&p1->port, &p2->port);
300 }
301
302 static bool ccs_same_unix_acl(const struct ccs_acl_info *a,
303 const struct ccs_acl_info *b)
304 {
305 const struct ccs_unix_acl *p1 = container_of(a, typeof(*p1), head);
306 const struct ccs_unix_acl *p2 = container_of(b, typeof(*p2), head);
307 return p1->protocol == p2->protocol &&
308 ccs_same_name_union(&p1->name, &p2->name);
309 }
310
311 static bool ccs_merge_inet_acl(struct ccs_acl_info *a, struct ccs_acl_info *b,
312 const bool is_delete)
313 {
314 u8 * const a_perm = &container_of(a, struct ccs_inet_acl, head)->perm;
315 u8 perm = *a_perm;
316 const u8 b_perm = container_of(b, struct ccs_inet_acl, head)->perm;
317 if (is_delete)
318 perm &= ~b_perm;
319 else
320 perm |= b_perm;
321 *a_perm = perm;
322 return !perm;
323 }
324
325 static bool ccs_merge_unix_acl(struct ccs_acl_info *a, struct ccs_acl_info *b,
326 const bool is_delete)
327 {
328 u8 * const a_perm = &container_of(a, struct ccs_unix_acl, head)->perm;
329 u8 perm = *a_perm;
330 const u8 b_perm = container_of(b, struct ccs_unix_acl, head)->perm;
331 if (is_delete)
332 perm &= ~b_perm;
333 else
334 perm |= b_perm;
335 *a_perm = perm;
336 return !perm;
337 }
338
339 /**
340 * ccs_write_inet_network - Write "struct ccs_inet_acl" list.
341 *
342 * @data: String to parse.
343 * @param: Pointer to "struct ccs_acl_param".
344 *
345 * Returns 0 on success, negative value otherwise.
346 */
347 int ccs_write_inet_network(char *data, struct ccs_acl_param *param)
348 {
349 struct ccs_inet_acl e = { .head.type = CCS_TYPE_INET_ACL };
350 u16 min_address[8];
351 u16 max_address[8];
352 int error = -EINVAL;
353 u8 type;
354 if (!ccs_tokenize(data, param->w, sizeof(param->w)) || !param->w[3][0])
355 return -EINVAL;
356 for (e.protocol = 0; e.protocol < CCS_SOCK_MAX; e.protocol++)
357 if (!strcmp(param->w[0], ccs_proto_keyword[e.protocol]))
358 break;
359 for (type = 0; type < CCS_MAX_NETWORK_OPERATION; type++)
360 if (ccs_permstr(param->w[1], ccs_socket_keyword[type]))
361 e.perm |= 1 << type;
362 if (e.protocol == CCS_SOCK_MAX || !e.perm)
363 return -EINVAL;
364 switch (ccs_parse_ip_address(param->w[2], min_address, max_address)) {
365 case CCS_IP_ADDRESS_TYPE_IPv6:
366 e.address_type = CCS_IP_ADDRESS_TYPE_IPv6;
367 e.address.ipv6.min = ccs_get_ipv6_address((struct in6_addr *)
368 min_address);
369 e.address.ipv6.max = ccs_get_ipv6_address((struct in6_addr *)
370 max_address);
371 if (!e.address.ipv6.min || !e.address.ipv6.max)
372 goto out;
373 break;
374 case CCS_IP_ADDRESS_TYPE_IPv4:
375 e.address_type = CCS_IP_ADDRESS_TYPE_IPv4;
376 /* use host byte order to allow u32 comparison.*/
377 e.address.ipv4.min = ntohl(*(u32 *) min_address);
378 e.address.ipv4.max = ntohl(*(u32 *) max_address);
379 break;
380 default:
381 if (param->w[2][0] != '@')
382 return -EINVAL;
383 e.address_type = CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP;
384 e.address.group = ccs_get_group(param->w[2] + 1,
385 CCS_ADDRESS_GROUP);
386 if (!e.address.group)
387 return -ENOMEM;
388 break;
389 }
390 if (!ccs_parse_number_union(param->w[3], &e.port))
391 goto out;
392 error = ccs_update_domain(&e.head, sizeof(e), param, ccs_same_inet_acl,
393 ccs_merge_inet_acl);
394 out:
395 if (e.address_type == CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP)
396 ccs_put_group(e.address.group);
397 else if (e.address_type == CCS_IP_ADDRESS_TYPE_IPv6) {
398 ccs_put_ipv6_address(e.address.ipv6.min);
399 ccs_put_ipv6_address(e.address.ipv6.max);
400 }
401 ccs_put_number_union(&e.port);
402 return error;
403 }
404
405 /**
406 * ccs_write_unix_network - Write "struct ccs_unix_acl" list.
407 *
408 * @data: String to parse.
409 * @param: Pointer to "struct ccs_acl_param".
410 *
411 * Returns 0 on success, negative value otherwise.
412 */
413 int ccs_write_unix_network(char *data, struct ccs_acl_param *param)
414 {
415 struct ccs_unix_acl e = { .head.type = CCS_TYPE_UNIX_ACL };
416 int error;
417 u8 type;
418 if (!ccs_tokenize(data, param->w, sizeof(param->w)) || !param->w[2][0])
419 return -EINVAL;
420 for (e.protocol = 0; e.protocol < CCS_SOCK_MAX; e.protocol++)
421 if (!strcmp(param->w[0], ccs_proto_keyword[e.protocol]))
422 break;
423 for (type = 0; type < CCS_MAX_NETWORK_OPERATION; type++)
424 if (ccs_permstr(param->w[1], ccs_socket_keyword[type]))
425 e.perm |= 1 << type;
426 if (e.protocol == CCS_SOCK_MAX || !e.perm)
427 return -EINVAL;
428 if (!ccs_parse_name_union(param->w[2], &e.name))
429 return -EINVAL;
430 error = ccs_update_domain(&e.head, sizeof(e), param, ccs_same_unix_acl,
431 ccs_merge_unix_acl);
432 ccs_put_name_union(&e.name);
433 return error;
434 }
435
436 #ifndef CONFIG_NET
437
438 void __init ccs_network_init(void)
439 {
440 u8 i;
441 for (i = 0; i < CCS_SOCK_MAX; i++)
442 if (!ccs_proto_keyword[i])
443 ccs_proto_keyword[i] = "unknown";
444 }
445
446 #else
447
448 /**
449 * ccs_inet_entry - Check permission for INET network operation.
450 *
451 * @address: Pointer to "struct ccs_addr_info".
452 *
453 * Returns 0 on success, negative value otherwise.
454 */
455 static int ccs_inet_entry(const struct ccs_addr_info *address)
456 {
457 const int idx = ccs_read_lock();
458 struct ccs_request_info r;
459 int error = 0;
460 const u8 type = ccs_inet2mac[address->protocol][address->operation];
461 if (type && ccs_init_request_info(&r, type) != CCS_CONFIG_DISABLED) {
462 struct task_struct * const task = current;
463 const bool no_sleep = address->operation == CCS_NETWORK_ACCEPT
464 || address->operation == CCS_NETWORK_RECV;
465 r.param_type = CCS_TYPE_INET_ACL;
466 r.param.inet_network.protocol = address->protocol;
467 r.param.inet_network.operation = address->operation;
468 r.param.inet_network.is_ipv6 = address->inet.is_ipv6;
469 r.param.inet_network.address = address->inet.address;
470 r.param.inet_network.port = ntohs(address->inet.port);
471 /* use host byte order to allow u32 comparison than memcmp().*/
472 r.param.inet_network.ip = ntohl(*address->inet.address);
473 if (no_sleep)
474 task->ccs_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
475 do {
476 ccs_check_acl(&r, ccs_check_inet_acl);
477 error = ccs_audit_inet_log(&r);
478 } while (error == CCS_RETRY_REQUEST);
479 if (no_sleep)
480 task->ccs_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
481 }
482 ccs_read_unlock(idx);
483 return error;
484 }
485
486 static int ccs_check_inet_address(const struct sockaddr *addr,
487 const unsigned int addr_len, const u16 port,
488 struct ccs_addr_info *address)
489 {
490 struct ccs_inet_addr_info *i = &address->inet;
491 switch (addr->sa_family) {
492 case AF_INET6:
493 if (addr_len < SIN6_LEN_RFC2133)
494 goto skip;
495 i->is_ipv6 = true;
496 i->address = (u32 *)
497 ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr;
498 i->port = ((struct sockaddr_in6 *) addr)->sin6_port;
499 break;
500 case AF_INET:
501 if (addr_len < sizeof(struct sockaddr_in))
502 goto skip;
503 i->is_ipv6 = false;
504 i->address = (u32 *) &((struct sockaddr_in *) addr)->sin_addr;
505 i->port = ((struct sockaddr_in *) addr)->sin_port;
506 break;
507 default:
508 goto skip;
509 }
510 if (address->protocol == SOCK_RAW)
511 i->port = htons(port);
512 return ccs_inet_entry(address);
513 skip:
514 return 0;
515 }
516
517 /**
518 * ccs_unix_entry - Check permission for UNIX network operation.
519 *
520 * @address: Pointer to "struct ccs_addr_info".
521 *
522 * Returns 0 on success, negative value otherwise.
523 */
524 static int ccs_unix_entry(const struct ccs_addr_info *address)
525 {
526 const int idx = ccs_read_lock();
527 struct ccs_request_info r;
528 int error = 0;
529 const u8 type = ccs_unix2mac[address->protocol][address->operation];
530 if (type && ccs_init_request_info(&r, type) != CCS_CONFIG_DISABLED) {
531 char *buf;
532 if (address->unix0.addr_len <= sizeof(sa_family_t))
533 buf = ccs_encode2("anonymous", 9);
534 else if (address->unix0.addr[0])
535 buf = ccs_encode(address->unix0.addr);
536 else
537 buf = ccs_encode2(address->unix0.addr,
538 address->unix0.addr_len
539 - sizeof(sa_family_t));
540 if (buf) {
541 struct task_struct * const task = current;
542 const bool no_sleep =
543 address->operation == CCS_NETWORK_ACCEPT ||
544 address->operation == CCS_NETWORK_RECV;
545 struct ccs_path_info addr;
546 addr.name = buf;
547 ccs_fill_path_info(&addr);
548 r.param_type = CCS_TYPE_UNIX_ACL;
549 r.param.unix_network.protocol = address->protocol;
550 r.param.unix_network.operation = address->operation;
551 r.param.unix_network.address = &addr;
552 if (no_sleep)
553 task->ccs_flags |=
554 CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
555
556 do {
557 ccs_check_acl(&r, ccs_check_unix_acl);
558 error = ccs_audit_unix_log(&r);
559 } while (error == CCS_RETRY_REQUEST);
560 if (no_sleep)
561 task->ccs_flags &=
562 ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
563 kfree(buf);
564 } else
565 error = -ENOMEM;
566 }
567 ccs_read_unlock(idx);
568 return error;
569 }
570
571 static int ccs_check_unix_address(struct sockaddr *addr,
572 const unsigned int addr_len,
573 struct ccs_addr_info *address)
574 {
575 struct ccs_unix_addr_info *u = &address->unix0;
576 if (addr->sa_family != AF_UNIX)
577 return 0;
578 u->addr = ((struct sockaddr_un *) addr)->sun_path;
579 u->addr_len = addr_len;
580 /*
581 * Terminate pathname with '\0' like unix_mkname() does.
582 * This is needed because pathname was copied by move_addr_to_kernel()
583 * but not yet terminated by unix_mkname().
584 */
585 if (u->addr[0] && addr_len > sizeof(short) &&
586 addr_len <= sizeof(struct sockaddr_un))
587 ((char *) u->addr)[addr_len] = '\0';
588 return ccs_unix_entry(address);
589 }
590
591 static bool ccs_kernel_service(void)
592 {
593 /* Nothing to do if I am a kernel service. */
594 return segment_eq(get_fs(), KERNEL_DS);
595 }
596
597 static u8 ccs_sock_family(struct sock *sk)
598 {
599 u8 family;
600 if (ccs_kernel_service())
601 return 0;
602 family = sk->sk_family;
603 switch (family) {
604 case PF_INET:
605 case PF_INET6:
606 case PF_UNIX:
607 return family;
608 default:
609 return 0;
610 }
611 }
612
613 /* Check permission for creating a socket. */
614 static int __ccs_socket_create_permission(int family, int type, int protocol)
615 {
616 if (ccs_kernel_service())
617 return 0;
618 if (family == PF_PACKET && !ccs_capable(CCS_USE_PACKET_SOCKET))
619 return -EPERM;
620 if (family == PF_ROUTE && !ccs_capable(CCS_USE_ROUTE_SOCKET))
621 return -EPERM;
622 return 0;
623 }
624
625 /* Check permission for listening a socket. */
626 static int __ccs_socket_listen_permission(struct socket *sock)
627 {
628 struct ccs_addr_info address;
629 const u8 family = ccs_sock_family(sock->sk);
630 const unsigned int type = sock->type;
631 struct sockaddr_storage addr;
632 int addr_len;
633 if (!family || (type != SOCK_STREAM && type != SOCK_SEQPACKET))
634 return 0;
635 {
636 const int error = sock->ops->getname(sock, (struct sockaddr *)
637 &addr, &addr_len, 0);
638 if (error)
639 return error;
640 }
641 address.protocol = type;
642 address.operation = CCS_NETWORK_LISTEN;
643 if (family == PF_UNIX)
644 return ccs_check_unix_address((struct sockaddr *) &addr,
645 addr_len, &address);
646 return ccs_check_inet_address((struct sockaddr *) &addr, addr_len, 0,
647 &address);
648 }
649
650 /* Check permission for setting the remote address of a socket. */
651 static int __ccs_socket_connect_permission(struct socket *sock,
652 struct sockaddr *addr, int addr_len)
653 {
654 struct ccs_addr_info address;
655 const u8 family = ccs_sock_family(sock->sk);
656 const unsigned int type = sock->type;
657 if (!family)
658 return 0;
659 address.protocol = type;
660 switch (type) {
661 case SOCK_DGRAM:
662 case SOCK_RAW:
663 address.operation = CCS_NETWORK_SEND;
664 break;
665 case SOCK_STREAM:
666 case SOCK_SEQPACKET:
667 address.operation = CCS_NETWORK_CONNECT;
668 break;
669 default:
670 return 0;
671 }
672 if (family == PF_UNIX)
673 return ccs_check_unix_address(addr, addr_len, &address);
674 return ccs_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
675 &address);
676 }
677
678 /* Check permission for setting the local address of a socket. */
679 static int __ccs_socket_bind_permission(struct socket *sock,
680 struct sockaddr *addr, int addr_len)
681 {
682 struct ccs_addr_info address;
683 const u8 family = ccs_sock_family(sock->sk);
684 const unsigned int type = sock->type;
685 if (!family)
686 return 0;
687 switch (type) {
688 case SOCK_STREAM:
689 case SOCK_DGRAM:
690 case SOCK_RAW:
691 case SOCK_SEQPACKET:
692 address.protocol = type;
693 address.operation = CCS_NETWORK_BIND;
694 break;
695 default:
696 return 0;
697 }
698 if (family == PF_UNIX)
699 return ccs_check_unix_address(addr, addr_len, &address);
700 return ccs_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
701 &address);
702 }
703
704 /* Check permission for sending a datagram. */
705 static int __ccs_socket_sendmsg_permission(struct socket *sock,
706 struct msghdr *msg, int size)
707 {
708 struct ccs_addr_info address;
709 const u8 family = ccs_sock_family(sock->sk);
710 const unsigned int type = sock->type;
711 if (!msg->msg_name || !family ||
712 (type != SOCK_DGRAM && type != SOCK_RAW))
713 return 0;
714 address.protocol = type;
715 address.operation = CCS_NETWORK_SEND;
716 if (family == PF_UNIX)
717 return ccs_check_unix_address((struct sockaddr *)
718 msg->msg_name, msg->msg_namelen,
719 &address);
720 return ccs_check_inet_address((struct sockaddr *) msg->msg_name,
721 msg->msg_namelen, sock->sk->sk_protocol,
722 &address);
723 }
724
725 /* Check permission for accepting a socket. */
726 static int __ccs_socket_post_accept_permission(struct socket *sock,
727 struct socket *newsock)
728 {
729 struct ccs_addr_info address;
730 const u8 family = ccs_sock_family(sock->sk);
731 const unsigned int type = sock->type;
732 struct sockaddr_storage addr;
733 int addr_len;
734 if (!family || (type != SOCK_STREAM && type != SOCK_SEQPACKET))
735 return 0;
736 {
737 const int error = newsock->ops->getname(newsock,
738 (struct sockaddr *)
739 &addr, &addr_len, 2);
740 if (error)
741 return error;
742 }
743 address.protocol = type;
744 address.operation = CCS_NETWORK_ACCEPT;
745 if (family == PF_UNIX)
746 return ccs_check_unix_address((struct sockaddr *) &addr,
747 addr_len, &address);
748 return ccs_check_inet_address((struct sockaddr *) &addr, addr_len, 0,
749 &address);
750 }
751
752 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
753 #if !defined(RHEL_MAJOR) || RHEL_MAJOR != 5
754 #if !defined(AX_MAJOR) || AX_MAJOR != 3 || !defined(AX_MINOR) || AX_MINOR < 2
755
756 static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
757 {
758 return skb->nh.iph;
759 }
760
761 static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
762 {
763 return skb->h.uh;
764 }
765
766 static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
767 {
768 return skb->nh.ipv6h;
769 }
770
771 #endif
772 #endif
773 #endif
774
775 /* Check permission for receiving a datagram. */
776 static int __ccs_socket_post_recvmsg_permission(struct sock *sk,
777 struct sk_buff *skb)
778 {
779 struct ccs_addr_info address;
780 const u8 family = ccs_sock_family(sk);
781 const unsigned int type = sk->sk_type;
782 struct sockaddr_storage addr;
783 if (!family)
784 return 0;
785 switch (type) {
786 case SOCK_DGRAM:
787 case SOCK_RAW:
788 address.protocol = type;
789 break;
790 default:
791 return 0;
792 }
793 address.operation = CCS_NETWORK_RECV;
794 switch (family) {
795 case PF_INET6:
796 {
797 struct in6_addr *sin6 = (struct in6_addr *) &addr;
798 address.inet.is_ipv6 = true;
799 if (type == SOCK_DGRAM &&
800 skb->protocol == htons(ETH_P_IP))
801 ipv6_addr_set(sin6, 0, 0, htonl(0xffff),
802 ip_hdr(skb)->saddr);
803 else
804 ipv6_addr_copy(sin6, &ipv6_hdr(skb)->saddr);
805 break;
806 }
807 case PF_INET:
808 {
809 struct in_addr *sin4 = (struct in_addr *) &addr;
810 address.inet.is_ipv6 = false;
811 sin4->s_addr = ip_hdr(skb)->saddr;
812 break;
813 }
814 default: /* == PF_UNIX */
815 {
816 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
817 struct unix_address *u = unix_sk(skb->sk)->addr;
818 #else
819 struct unix_address *u = skb->sk->protinfo.af_unix.addr;
820 #endif
821 unsigned int addr_len;
822 if (!u)
823 return 0;
824 addr_len = u->len;
825 if (addr_len >= sizeof(addr))
826 return 0;
827 memcpy(&addr, u->name, addr_len);
828 return ccs_check_unix_address((struct sockaddr *) &addr,
829 addr_len, &address);
830 }
831 }
832 address.inet.address = (u32 *) &addr;
833 if (type == SOCK_DGRAM)
834 address.inet.port = udp_hdr(skb)->source;
835 else
836 address.inet.port = htons(sk->sk_protocol);
837 return ccs_inet_entry(&address);
838 }
839
840 void __init ccs_network_init(void)
841 {
842 u8 i;
843 for (i = 0; i < CCS_SOCK_MAX; i++)
844 if (!ccs_proto_keyword[i])
845 ccs_proto_keyword[i] = "unknown";
846 ccsecurity_ops.socket_create_permission =
847 __ccs_socket_create_permission;
848 ccsecurity_ops.socket_listen_permission =
849 __ccs_socket_listen_permission;
850 ccsecurity_ops.socket_connect_permission =
851 __ccs_socket_connect_permission;
852 ccsecurity_ops.socket_bind_permission = __ccs_socket_bind_permission;
853 ccsecurity_ops.socket_post_accept_permission =
854 __ccs_socket_post_accept_permission;
855 ccsecurity_ops.socket_sendmsg_permission =
856 __ccs_socket_sendmsg_permission;
857 ccsecurity_ops.socket_post_recvmsg_permission =
858 __ccs_socket_post_recvmsg_permission;
859 }
860
861 #endif

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