Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
network.c
Go to the documentation of this file.
1 /*
2  * security/tomoyo/network.c
3  *
4  * Copyright (C) 2005-2011 NTT DATA CORPORATION
5  */
6 
7 #include "common.h"
8 #include <linux/slab.h>
9 
10 /* Structure for holding inet domain socket's address. */
12  __be16 port; /* In network byte order. */
13  const __be32 *address; /* In network byte order. */
14  bool is_ipv6;
15 };
16 
17 /* Structure for holding unix domain socket's address. */
19  u8 *addr; /* This may not be '\0' terminated string. */
20  unsigned int addr_len;
21 };
22 
23 /* Structure for holding socket address. */
29 };
30 
31 /* String table for socket's protocols. */
32 const char * const tomoyo_proto_keyword[TOMOYO_SOCK_MAX] = {
33  [SOCK_STREAM] = "stream",
34  [SOCK_DGRAM] = "dgram",
35  [SOCK_RAW] = "raw",
36  [SOCK_SEQPACKET] = "seqpacket",
37  [0] = " ", /* Dummy for avoiding NULL pointer dereference. */
38  [4] = " ", /* Dummy for avoiding NULL pointer dereference. */
39 };
40 
50  struct tomoyo_ipaddr_union *ptr)
51 {
52  u8 * const min = ptr->ip[0].in6_u.u6_addr8;
53  u8 * const max = ptr->ip[1].in6_u.u6_addr8;
54  char *address = tomoyo_read_token(param);
55  const char *end;
56 
57  if (!strchr(address, ':') &&
58  in4_pton(address, -1, min, '-', &end) > 0) {
59  ptr->is_ipv6 = false;
60  if (!*end)
61  ptr->ip[1].s6_addr32[0] = ptr->ip[0].s6_addr32[0];
62  else if (*end++ != '-' ||
63  in4_pton(end, -1, max, '\0', &end) <= 0 || *end)
64  return false;
65  return true;
66  }
67  if (in6_pton(address, -1, min, '-', &end) > 0) {
68  ptr->is_ipv6 = true;
69  if (!*end)
70  memmove(max, min, sizeof(u16) * 8);
71  else if (*end++ != '-' ||
72  in6_pton(end, -1, max, '\0', &end) <= 0 || *end)
73  return false;
74  return true;
75  }
76  return false;
77 }
78 
89 static void tomoyo_print_ipv4(char *buffer, const unsigned int buffer_len,
90  const __be32 *min_ip, const __be32 *max_ip)
91 {
92  snprintf(buffer, buffer_len, "%pI4%c%pI4", min_ip,
93  *min_ip == *max_ip ? '\0' : '-', max_ip);
94 }
95 
106 static void tomoyo_print_ipv6(char *buffer, const unsigned int buffer_len,
107  const struct in6_addr *min_ip,
108  const struct in6_addr *max_ip)
109 {
110  snprintf(buffer, buffer_len, "%pI6c%c%pI6c", min_ip,
111  !memcmp(min_ip, max_ip, 16) ? '\0' : '-', max_ip);
112 }
113 
123 void tomoyo_print_ip(char *buf, const unsigned int size,
124  const struct tomoyo_ipaddr_union *ptr)
125 {
126  if (ptr->is_ipv6)
127  tomoyo_print_ipv6(buf, size, &ptr->ip[0], &ptr->ip[1]);
128  else
129  tomoyo_print_ipv4(buf, size, &ptr->ip[0].s6_addr32[0],
130  &ptr->ip[1].s6_addr32[0]);
131 }
132 
133 /*
134  * Mapping table from "enum tomoyo_network_acl_index" to
135  * "enum tomoyo_mac_index" for inet domain socket.
136  */
137 static const u8 tomoyo_inet2mac
139  [SOCK_STREAM] = {
145  },
146  [SOCK_DGRAM] = {
149  },
150  [SOCK_RAW] = {
153  },
154 };
155 
156 /*
157  * Mapping table from "enum tomoyo_network_acl_index" to
158  * "enum tomoyo_mac_index" for unix domain socket.
159  */
160 static const u8 tomoyo_unix2mac
162  [SOCK_STREAM] = {
168  },
169  [SOCK_DGRAM] = {
172  },
173  [SOCK_SEQPACKET] = {
180  },
181 };
182 
191 static bool tomoyo_same_inet_acl(const struct tomoyo_acl_info *a,
192  const struct tomoyo_acl_info *b)
193 {
194  const struct tomoyo_inet_acl *p1 = container_of(a, typeof(*p1), head);
195  const struct tomoyo_inet_acl *p2 = container_of(b, typeof(*p2), head);
196 
197  return p1->protocol == p2->protocol &&
198  tomoyo_same_ipaddr_union(&p1->address, &p2->address) &&
199  tomoyo_same_number_union(&p1->port, &p2->port);
200 }
201 
210 static bool tomoyo_same_unix_acl(const struct tomoyo_acl_info *a,
211  const struct tomoyo_acl_info *b)
212 {
213  const struct tomoyo_unix_acl *p1 = container_of(a, typeof(*p1), head);
214  const struct tomoyo_unix_acl *p2 = container_of(b, typeof(*p2), head);
215 
216  return p1->protocol == p2->protocol &&
217  tomoyo_same_name_union(&p1->name, &p2->name);
218 }
219 
229 static bool tomoyo_merge_inet_acl(struct tomoyo_acl_info *a,
230  struct tomoyo_acl_info *b,
231  const bool is_delete)
232 {
233  u8 * const a_perm =
234  &container_of(a, struct tomoyo_inet_acl, head)->perm;
235  u8 perm = *a_perm;
236  const u8 b_perm = container_of(b, struct tomoyo_inet_acl, head)->perm;
237 
238  if (is_delete)
239  perm &= ~b_perm;
240  else
241  perm |= b_perm;
242  *a_perm = perm;
243  return !perm;
244 }
245 
255 static bool tomoyo_merge_unix_acl(struct tomoyo_acl_info *a,
256  struct tomoyo_acl_info *b,
257  const bool is_delete)
258 {
259  u8 * const a_perm =
260  &container_of(a, struct tomoyo_unix_acl, head)->perm;
261  u8 perm = *a_perm;
262  const u8 b_perm = container_of(b, struct tomoyo_unix_acl, head)->perm;
263 
264  if (is_delete)
265  perm &= ~b_perm;
266  else
267  perm |= b_perm;
268  *a_perm = perm;
269  return !perm;
270 }
271 
282 {
283  struct tomoyo_inet_acl e = { .head.type = TOMOYO_TYPE_INET_ACL };
284  int error = -EINVAL;
285  u8 type;
286  const char *protocol = tomoyo_read_token(param);
287  const char *operation = tomoyo_read_token(param);
288 
289  for (e.protocol = 0; e.protocol < TOMOYO_SOCK_MAX; e.protocol++)
290  if (!strcmp(protocol, tomoyo_proto_keyword[e.protocol]))
291  break;
292  for (type = 0; type < TOMOYO_MAX_NETWORK_OPERATION; type++)
293  if (tomoyo_permstr(operation, tomoyo_socket_keyword[type]))
294  e.perm |= 1 << type;
295  if (e.protocol == TOMOYO_SOCK_MAX || !e.perm)
296  return -EINVAL;
297  if (param->data[0] == '@') {
298  param->data++;
299  e.address.group =
301  if (!e.address.group)
302  return -ENOMEM;
303  } else {
304  if (!tomoyo_parse_ipaddr_union(param, &e.address))
305  goto out;
306  }
307  if (!tomoyo_parse_number_union(param, &e.port) ||
308  e.port.values[1] > 65535)
309  goto out;
310  error = tomoyo_update_domain(&e.head, sizeof(e), param,
311  tomoyo_same_inet_acl,
312  tomoyo_merge_inet_acl);
313 out:
314  tomoyo_put_group(e.address.group);
316  return error;
317 }
318 
327 {
328  struct tomoyo_unix_acl e = { .head.type = TOMOYO_TYPE_UNIX_ACL };
329  int error;
330  u8 type;
331  const char *protocol = tomoyo_read_token(param);
332  const char *operation = tomoyo_read_token(param);
333 
334  for (e.protocol = 0; e.protocol < TOMOYO_SOCK_MAX; e.protocol++)
335  if (!strcmp(protocol, tomoyo_proto_keyword[e.protocol]))
336  break;
337  for (type = 0; type < TOMOYO_MAX_NETWORK_OPERATION; type++)
338  if (tomoyo_permstr(operation, tomoyo_socket_keyword[type]))
339  e.perm |= 1 << type;
340  if (e.protocol == TOMOYO_SOCK_MAX || !e.perm)
341  return -EINVAL;
342  if (!tomoyo_parse_name_union(param, &e.name))
343  return -EINVAL;
344  error = tomoyo_update_domain(&e.head, sizeof(e), param,
345  tomoyo_same_unix_acl,
346  tomoyo_merge_unix_acl);
348  return error;
349 }
350 
362 static int tomoyo_audit_net_log(struct tomoyo_request_info *r,
363  const char *family, const u8 protocol,
364  const u8 operation, const char *address)
365 {
366  return tomoyo_supervisor(r, "network %s %s %s %s\n", family,
367  tomoyo_proto_keyword[protocol],
368  tomoyo_socket_keyword[operation], address);
369 }
370 
378 static int tomoyo_audit_inet_log(struct tomoyo_request_info *r)
379 {
380  char buf[128];
381  int len;
382  const __be32 *address = r->param.inet_network.address;
383 
384  if (r->param.inet_network.is_ipv6)
385  tomoyo_print_ipv6(buf, sizeof(buf), (const struct in6_addr *)
386  address, (const struct in6_addr *) address);
387  else
388  tomoyo_print_ipv4(buf, sizeof(buf), address, address);
389  len = strlen(buf);
390  snprintf(buf + len, sizeof(buf) - len, " %u",
391  r->param.inet_network.port);
392  return tomoyo_audit_net_log(r, "inet", r->param.inet_network.protocol,
393  r->param.inet_network.operation, buf);
394 }
395 
403 static int tomoyo_audit_unix_log(struct tomoyo_request_info *r)
404 {
405  return tomoyo_audit_net_log(r, "unix", r->param.unix_network.protocol,
406  r->param.unix_network.operation,
407  r->param.unix_network.address->name);
408 }
409 
418 static bool tomoyo_check_inet_acl(struct tomoyo_request_info *r,
419  const struct tomoyo_acl_info *ptr)
420 {
421  const struct tomoyo_inet_acl *acl =
422  container_of(ptr, typeof(*acl), head);
423  const u8 size = r->param.inet_network.is_ipv6 ? 16 : 4;
424 
425  if (!(acl->perm & (1 << r->param.inet_network.operation)) ||
427  &acl->port))
428  return false;
429  if (acl->address.group)
431  (r->param.inet_network.is_ipv6,
432  r->param.inet_network.address, acl->address.group);
433  return acl->address.is_ipv6 == r->param.inet_network.is_ipv6 &&
434  memcmp(&acl->address.ip[0],
435  r->param.inet_network.address, size) <= 0 &&
436  memcmp(r->param.inet_network.address,
437  &acl->address.ip[1], size) <= 0;
438 }
439 
448 static bool tomoyo_check_unix_acl(struct tomoyo_request_info *r,
449  const struct tomoyo_acl_info *ptr)
450 {
451  const struct tomoyo_unix_acl *acl =
452  container_of(ptr, typeof(*acl), head);
453 
454  return (acl->perm & (1 << r->param.unix_network.operation)) &&
456  &acl->name);
457 }
458 
466 static int tomoyo_inet_entry(const struct tomoyo_addr_info *address)
467 {
468  const int idx = tomoyo_read_lock();
469  struct tomoyo_request_info r;
470  int error = 0;
471  const u8 type = tomoyo_inet2mac[address->protocol][address->operation];
472 
473  if (type && tomoyo_init_request_info(&r, NULL, type)
476  r.param.inet_network.protocol = address->protocol;
477  r.param.inet_network.operation = address->operation;
478  r.param.inet_network.is_ipv6 = address->inet.is_ipv6;
479  r.param.inet_network.address = address->inet.address;
480  r.param.inet_network.port = ntohs(address->inet.port);
481  do {
482  tomoyo_check_acl(&r, tomoyo_check_inet_acl);
483  error = tomoyo_audit_inet_log(&r);
484  } while (error == TOMOYO_RETRY_REQUEST);
485  }
486  tomoyo_read_unlock(idx);
487  return error;
488 }
489 
500 static int tomoyo_check_inet_address(const struct sockaddr *addr,
501  const unsigned int addr_len,
502  const u16 port,
503  struct tomoyo_addr_info *address)
504 {
505  struct tomoyo_inet_addr_info *i = &address->inet;
506 
507  switch (addr->sa_family) {
508  case AF_INET6:
509  if (addr_len < SIN6_LEN_RFC2133)
510  goto skip;
511  i->is_ipv6 = true;
512  i->address = (__be32 *)
513  ((struct sockaddr_in6 *) addr)->sin6_addr.s6_addr;
514  i->port = ((struct sockaddr_in6 *) addr)->sin6_port;
515  break;
516  case AF_INET:
517  if (addr_len < sizeof(struct sockaddr_in))
518  goto skip;
519  i->is_ipv6 = false;
520  i->address = (__be32 *)
521  &((struct sockaddr_in *) addr)->sin_addr;
522  i->port = ((struct sockaddr_in *) addr)->sin_port;
523  break;
524  default:
525  goto skip;
526  }
527  if (address->protocol == SOCK_RAW)
528  i->port = htons(port);
529  return tomoyo_inet_entry(address);
530 skip:
531  return 0;
532 }
533 
541 static int tomoyo_unix_entry(const struct tomoyo_addr_info *address)
542 {
543  const int idx = tomoyo_read_lock();
544  struct tomoyo_request_info r;
545  int error = 0;
546  const u8 type = tomoyo_unix2mac[address->protocol][address->operation];
547 
548  if (type && tomoyo_init_request_info(&r, NULL, type)
550  char *buf = address->unix0.addr;
551  int len = address->unix0.addr_len - sizeof(sa_family_t);
552 
553  if (len <= 0) {
554  buf = "anonymous";
555  len = 9;
556  } else if (buf[0]) {
557  len = strnlen(buf, len);
558  }
559  buf = tomoyo_encode2(buf, len);
560  if (buf) {
561  struct tomoyo_path_info addr;
562 
563  addr.name = buf;
564  tomoyo_fill_path_info(&addr);
566  r.param.unix_network.protocol = address->protocol;
567  r.param.unix_network.operation = address->operation;
568  r.param.unix_network.address = &addr;
569  do {
570  tomoyo_check_acl(&r, tomoyo_check_unix_acl);
571  error = tomoyo_audit_unix_log(&r);
572  } while (error == TOMOYO_RETRY_REQUEST);
573  kfree(buf);
574  } else
575  error = -ENOMEM;
576  }
577  tomoyo_read_unlock(idx);
578  return error;
579 }
580 
590 static int tomoyo_check_unix_address(struct sockaddr *addr,
591  const unsigned int addr_len,
592  struct tomoyo_addr_info *address)
593 {
594  struct tomoyo_unix_addr_info *u = &address->unix0;
595 
596  if (addr->sa_family != AF_UNIX)
597  return 0;
598  u->addr = ((struct sockaddr_un *) addr)->sun_path;
599  u->addr_len = addr_len;
600  return tomoyo_unix_entry(address);
601 }
602 
608 static bool tomoyo_kernel_service(void)
609 {
610  /* Nothing to do if I am a kernel service. */
611  return segment_eq(get_fs(), KERNEL_DS);
612 }
613 
621 static u8 tomoyo_sock_family(struct sock *sk)
622 {
623  u8 family;
624 
625  if (tomoyo_kernel_service())
626  return 0;
627  family = sk->sk_family;
628  switch (family) {
629  case PF_INET:
630  case PF_INET6:
631  case PF_UNIX:
632  return family;
633  default:
634  return 0;
635  }
636 }
637 
646 {
647  struct tomoyo_addr_info address;
648  const u8 family = tomoyo_sock_family(sock->sk);
649  const unsigned int type = sock->type;
650  struct sockaddr_storage addr;
651  int addr_len;
652 
653  if (!family || (type != SOCK_STREAM && type != SOCK_SEQPACKET))
654  return 0;
655  {
656  const int error = sock->ops->getname(sock, (struct sockaddr *)
657  &addr, &addr_len, 0);
658 
659  if (error)
660  return error;
661  }
662  address.protocol = type;
664  if (family == PF_UNIX)
665  return tomoyo_check_unix_address((struct sockaddr *) &addr,
666  addr_len, &address);
667  return tomoyo_check_inet_address((struct sockaddr *) &addr, addr_len,
668  0, &address);
669 }
670 
681  struct sockaddr *addr, int addr_len)
682 {
683  struct tomoyo_addr_info address;
684  const u8 family = tomoyo_sock_family(sock->sk);
685  const unsigned int type = sock->type;
686 
687  if (!family)
688  return 0;
689  address.protocol = type;
690  switch (type) {
691  case SOCK_DGRAM:
692  case SOCK_RAW:
693  address.operation = TOMOYO_NETWORK_SEND;
694  break;
695  case SOCK_STREAM:
696  case SOCK_SEQPACKET:
698  break;
699  default:
700  return 0;
701  }
702  if (family == PF_UNIX)
703  return tomoyo_check_unix_address(addr, addr_len, &address);
704  return tomoyo_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
705  &address);
706 }
707 
718  int addr_len)
719 {
720  struct tomoyo_addr_info address;
721  const u8 family = tomoyo_sock_family(sock->sk);
722  const unsigned int type = sock->type;
723 
724  if (!family)
725  return 0;
726  switch (type) {
727  case SOCK_STREAM:
728  case SOCK_DGRAM:
729  case SOCK_RAW:
730  case SOCK_SEQPACKET:
731  address.protocol = type;
732  address.operation = TOMOYO_NETWORK_BIND;
733  break;
734  default:
735  return 0;
736  }
737  if (family == PF_UNIX)
738  return tomoyo_check_unix_address(addr, addr_len, &address);
739  return tomoyo_check_inet_address(addr, addr_len, sock->sk->sk_protocol,
740  &address);
741 }
742 
753  int size)
754 {
755  struct tomoyo_addr_info address;
756  const u8 family = tomoyo_sock_family(sock->sk);
757  const unsigned int type = sock->type;
758 
759  if (!msg->msg_name || !family ||
760  (type != SOCK_DGRAM && type != SOCK_RAW))
761  return 0;
762  address.protocol = type;
763  address.operation = TOMOYO_NETWORK_SEND;
764  if (family == PF_UNIX)
765  return tomoyo_check_unix_address((struct sockaddr *)
766  msg->msg_name,
767  msg->msg_namelen, &address);
768  return tomoyo_check_inet_address((struct sockaddr *) msg->msg_name,
769  msg->msg_namelen,
770  sock->sk->sk_protocol, &address);
771 }