Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
file.c
Go to the documentation of this file.
1 /*
2  * security/tomoyo/file.c
3  *
4  * Copyright (C) 2005-2011 NTT DATA CORPORATION
5  */
6 
7 #include "common.h"
8 #include <linux/slab.h>
9 
10 /*
11  * Mapping table from "enum tomoyo_path_acl_index" to "enum tomoyo_mac_index".
12  */
13 static const u8 tomoyo_p2mac[TOMOYO_MAX_PATH_OPERATION] = {
25 };
26 
27 /*
28  * Mapping table from "enum tomoyo_mkdev_acl_index" to "enum tomoyo_mac_index".
29  */
33 };
34 
35 /*
36  * Mapping table from "enum tomoyo_path2_acl_index" to "enum tomoyo_mac_index".
37  */
42 };
43 
44 /*
45  * Mapping table from "enum tomoyo_path_number_acl_index" to
46  * "enum tomoyo_mac_index".
47  */
57 };
58 
67 {
68  tomoyo_put_group(ptr->group);
69  tomoyo_put_name(ptr->filename);
70 }
71 
80 const struct tomoyo_path_info *
82  const struct tomoyo_name_union *ptr)
83 {
84  if (ptr->group)
85  return tomoyo_path_matches_group(name, ptr->group);
86  if (tomoyo_path_matches_pattern(name, ptr->filename))
87  return ptr->filename;
88  return NULL;
89 }
90 
99 {
100  tomoyo_put_group(ptr->group);
101 }
102 
111 bool tomoyo_compare_number_union(const unsigned long value,
112  const struct tomoyo_number_union *ptr)
113 {
114  if (ptr->group)
115  return tomoyo_number_matches_group(value, value, ptr->group);
116  return value >= ptr->values[0] && value <= ptr->values[1];
117 }
118 
129 static void tomoyo_add_slash(struct tomoyo_path_info *buf)
130 {
131  if (buf->is_dir)
132  return;
133  /*
134  * This is OK because tomoyo_encode() reserves space for appending "/".
135  */
136  strcat((char *) buf->name, "/");
138 }
139 
148 static bool tomoyo_get_realpath(struct tomoyo_path_info *buf, struct path *path)
149 {
150  buf->name = tomoyo_realpath_from_path(path);
151  if (buf->name) {
153  return true;
154  }
155  return false;
156 }
157 
165 static int tomoyo_audit_path_log(struct tomoyo_request_info *r)
166 {
167  return tomoyo_supervisor(r, "file %s %s\n", tomoyo_path_keyword
168  [r->param.path.operation],
169  r->param.path.filename->name);
170 }
171 
179 static int tomoyo_audit_path2_log(struct tomoyo_request_info *r)
180 {
181  return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords
182  [tomoyo_pp2mac[r->param.path2.operation]],
183  r->param.path2.filename1->name,
184  r->param.path2.filename2->name);
185 }
186 
194 static int tomoyo_audit_mkdev_log(struct tomoyo_request_info *r)
195 {
196  return tomoyo_supervisor(r, "file %s %s 0%o %u %u\n",
198  [tomoyo_pnnn2mac[r->param.mkdev.operation]],
199  r->param.mkdev.filename->name,
200  r->param.mkdev.mode, r->param.mkdev.major,
201  r->param.mkdev.minor);
202 }
203 
211 static int tomoyo_audit_path_number_log(struct tomoyo_request_info *r)
212 {
213  const u8 type = r->param.path_number.operation;
214  u8 radix;
215  char buffer[64];
216  switch (type) {
217  case TOMOYO_TYPE_CREATE:
218  case TOMOYO_TYPE_MKDIR:
219  case TOMOYO_TYPE_MKFIFO:
220  case TOMOYO_TYPE_MKSOCK:
221  case TOMOYO_TYPE_CHMOD:
222  radix = TOMOYO_VALUE_TYPE_OCTAL;
223  break;
224  case TOMOYO_TYPE_IOCTL:
226  break;
227  default:
229  break;
230  }
231  tomoyo_print_ulong(buffer, sizeof(buffer), r->param.path_number.number,
232  radix);
233  return tomoyo_supervisor(r, "file %s %s %s\n", tomoyo_mac_keywords
234  [tomoyo_pn2mac[type]],
235  r->param.path_number.filename->name, buffer);
236 }
237 
250 static bool tomoyo_check_path_acl(struct tomoyo_request_info *r,
251  const struct tomoyo_acl_info *ptr)
252 {
253  const struct tomoyo_path_acl *acl = container_of(ptr, typeof(*acl),
254  head);
255  if (acl->perm & (1 << r->param.path.operation)) {
256  r->param.path.matched_path =
258  &acl->name);
259  return r->param.path.matched_path != NULL;
260  }
261  return false;
262 }
263 
272 static bool tomoyo_check_path_number_acl(struct tomoyo_request_info *r,
273  const struct tomoyo_acl_info *ptr)
274 {
275  const struct tomoyo_path_number_acl *acl =
276  container_of(ptr, typeof(*acl), head);
277  return (acl->perm & (1 << r->param.path_number.operation)) &&
279  &acl->number) &&
281  &acl->name);
282 }
283 
292 static bool tomoyo_check_path2_acl(struct tomoyo_request_info *r,
293  const struct tomoyo_acl_info *ptr)
294 {
295  const struct tomoyo_path2_acl *acl =
296  container_of(ptr, typeof(*acl), head);
297  return (acl->perm & (1 << r->param.path2.operation)) &&
298  tomoyo_compare_name_union(r->param.path2.filename1, &acl->name1)
299  && tomoyo_compare_name_union(r->param.path2.filename2,
300  &acl->name2);
301 }
302 
311 static bool tomoyo_check_mkdev_acl(struct tomoyo_request_info *r,
312  const struct tomoyo_acl_info *ptr)
313 {
314  const struct tomoyo_mkdev_acl *acl =
315  container_of(ptr, typeof(*acl), head);
316  return (acl->perm & (1 << r->param.mkdev.operation)) &&
318  &acl->mode) &&
320  &acl->major) &&
322  &acl->minor) &&
324  &acl->name);
325 }
326 
335 static bool tomoyo_same_path_acl(const struct tomoyo_acl_info *a,
336  const struct tomoyo_acl_info *b)
337 {
338  const struct tomoyo_path_acl *p1 = container_of(a, typeof(*p1), head);
339  const struct tomoyo_path_acl *p2 = container_of(b, typeof(*p2), head);
340  return tomoyo_same_name_union(&p1->name, &p2->name);
341 }
342 
352 static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
353  struct tomoyo_acl_info *b,
354  const bool is_delete)
355 {
356  u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head)
357  ->perm;
358  u16 perm = *a_perm;
359  const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm;
360  if (is_delete)
361  perm &= ~b_perm;
362  else
363  perm |= b_perm;
364  *a_perm = perm;
365  return !perm;
366 }
367 
378 static int tomoyo_update_path_acl(const u16 perm,
379  struct tomoyo_acl_param *param)
380 {
381  struct tomoyo_path_acl e = {
382  .head.type = TOMOYO_TYPE_PATH_ACL,
383  .perm = perm
384  };
385  int error;
386  if (!tomoyo_parse_name_union(param, &e.name))
387  error = -EINVAL;
388  else
389  error = tomoyo_update_domain(&e.head, sizeof(e), param,
390  tomoyo_same_path_acl,
391  tomoyo_merge_path_acl);
393  return error;
394 }
395 
404 static bool tomoyo_same_mkdev_acl(const struct tomoyo_acl_info *a,
405  const struct tomoyo_acl_info *b)
406 {
407  const struct tomoyo_mkdev_acl *p1 = container_of(a, typeof(*p1), head);
408  const struct tomoyo_mkdev_acl *p2 = container_of(b, typeof(*p2), head);
409  return tomoyo_same_name_union(&p1->name, &p2->name) &&
410  tomoyo_same_number_union(&p1->mode, &p2->mode) &&
411  tomoyo_same_number_union(&p1->major, &p2->major) &&
412  tomoyo_same_number_union(&p1->minor, &p2->minor);
413 }
414 
424 static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
425  struct tomoyo_acl_info *b,
426  const bool is_delete)
427 {
428  u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl,
429  head)->perm;
430  u8 perm = *a_perm;
431  const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head)
432  ->perm;
433  if (is_delete)
434  perm &= ~b_perm;
435  else
436  perm |= b_perm;
437  *a_perm = perm;
438  return !perm;
439 }
440 
451 static int tomoyo_update_mkdev_acl(const u8 perm,
452  struct tomoyo_acl_param *param)
453 {
454  struct tomoyo_mkdev_acl e = {
455  .head.type = TOMOYO_TYPE_MKDEV_ACL,
456  .perm = perm
457  };
458  int error;
459  if (!tomoyo_parse_name_union(param, &e.name) ||
460  !tomoyo_parse_number_union(param, &e.mode) ||
461  !tomoyo_parse_number_union(param, &e.major) ||
462  !tomoyo_parse_number_union(param, &e.minor))
463  error = -EINVAL;
464  else
465  error = tomoyo_update_domain(&e.head, sizeof(e), param,
466  tomoyo_same_mkdev_acl,
467  tomoyo_merge_mkdev_acl);
472  return error;
473 }
474 
483 static bool tomoyo_same_path2_acl(const struct tomoyo_acl_info *a,
484  const struct tomoyo_acl_info *b)
485 {
486  const struct tomoyo_path2_acl *p1 = container_of(a, typeof(*p1), head);
487  const struct tomoyo_path2_acl *p2 = container_of(b, typeof(*p2), head);
488  return tomoyo_same_name_union(&p1->name1, &p2->name1) &&
489  tomoyo_same_name_union(&p1->name2, &p2->name2);
490 }
491 
501 static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
502  struct tomoyo_acl_info *b,
503  const bool is_delete)
504 {
505  u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head)
506  ->perm;
507  u8 perm = *a_perm;
508  const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm;
509  if (is_delete)
510  perm &= ~b_perm;
511  else
512  perm |= b_perm;
513  *a_perm = perm;
514  return !perm;
515 }
516 
527 static int tomoyo_update_path2_acl(const u8 perm,
528  struct tomoyo_acl_param *param)
529 {
530  struct tomoyo_path2_acl e = {
531  .head.type = TOMOYO_TYPE_PATH2_ACL,
532  .perm = perm
533  };
534  int error;
535  if (!tomoyo_parse_name_union(param, &e.name1) ||
536  !tomoyo_parse_name_union(param, &e.name2))
537  error = -EINVAL;
538  else
539  error = tomoyo_update_domain(&e.head, sizeof(e), param,
540  tomoyo_same_path2_acl,
541  tomoyo_merge_path2_acl);
544  return error;
545 }
546 
558 static int tomoyo_path_permission(struct tomoyo_request_info *r, u8 operation,
559  const struct tomoyo_path_info *filename)
560 {
561  int error;
562 
563  r->type = tomoyo_p2mac[operation];
564  r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type);
565  if (r->mode == TOMOYO_CONFIG_DISABLED)
566  return 0;
568  r->param.path.filename = filename;
569  r->param.path.operation = operation;
570  do {
571  tomoyo_check_acl(r, tomoyo_check_path_acl);
572  error = tomoyo_audit_path_log(r);
573  } while (error == TOMOYO_RETRY_REQUEST);
574  return error;
575 }
576 
588  const struct tomoyo_path_info *filename)
589 {
590  /*
591  * Unlike other permission checks, this check is done regardless of
592  * profile mode settings in order to check for domain transition
593  * preference.
594  */
596  r->mode = tomoyo_get_mode(r->domain->ns, r->profile, r->type);
598  r->param.path.filename = filename;
599  r->param.path.operation = TOMOYO_TYPE_EXECUTE;
600  tomoyo_check_acl(r, tomoyo_check_path_acl);
601  r->ee->transition = r->matched_acl && r->matched_acl->cond ?
602  r->matched_acl->cond->transit : NULL;
603  if (r->mode != TOMOYO_CONFIG_DISABLED)
604  return tomoyo_audit_path_log(r);
605  return 0;
606 }
607 
616 static bool tomoyo_same_path_number_acl(const struct tomoyo_acl_info *a,
617  const struct tomoyo_acl_info *b)
618 {
619  const struct tomoyo_path_number_acl *p1 = container_of(a, typeof(*p1),
620  head);
621  const struct tomoyo_path_number_acl *p2 = container_of(b, typeof(*p2),
622  head);
623  return tomoyo_same_name_union(&p1->name, &p2->name) &&
624  tomoyo_same_number_union(&p1->number, &p2->number);
625 }
626 
636 static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
637  struct tomoyo_acl_info *b,
638  const bool is_delete)
639 {
640  u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl,
641  head)->perm;
642  u8 perm = *a_perm;
643  const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head)
644  ->perm;
645  if (is_delete)
646  perm &= ~b_perm;
647  else
648  perm |= b_perm;
649  *a_perm = perm;
650  return !perm;
651 }
652 
661 static int tomoyo_update_path_number_acl(const u8 perm,
662  struct tomoyo_acl_param *param)
663 {
664  struct tomoyo_path_number_acl e = {
666  .perm = perm
667  };
668  int error;
669  if (!tomoyo_parse_name_union(param, &e.name) ||
670  !tomoyo_parse_number_union(param, &e.number))
671  error = -EINVAL;
672  else
673  error = tomoyo_update_domain(&e.head, sizeof(e), param,
674  tomoyo_same_path_number_acl,
675  tomoyo_merge_path_number_acl);
678  return error;
679 }
680 
690 int tomoyo_path_number_perm(const u8 type, struct path *path,
691  unsigned long number)
692 {
693  struct tomoyo_request_info r;
694  struct tomoyo_obj_info obj = {
695  .path1 = *path,
696  };
697  int error = -ENOMEM;
698  struct tomoyo_path_info buf;
699  int idx;
700 
702  == TOMOYO_CONFIG_DISABLED || !path->dentry)
703  return 0;
704  idx = tomoyo_read_lock();
705  if (!tomoyo_get_realpath(&buf, path))
706  goto out;
707  r.obj = &obj;
708  if (type == TOMOYO_TYPE_MKDIR)
709  tomoyo_add_slash(&buf);
711  r.param.path_number.operation = type;
712  r.param.path_number.filename = &buf;
713  r.param.path_number.number = number;
714  do {
715  tomoyo_check_acl(&r, tomoyo_check_path_number_acl);
716  error = tomoyo_audit_path_number_log(&r);
717  } while (error == TOMOYO_RETRY_REQUEST);
718  kfree(buf.name);
719  out:
720  tomoyo_read_unlock(idx);
721  if (r.mode != TOMOYO_CONFIG_ENFORCING)
722  error = 0;
723  return error;
724 }
725 
736  struct path *path, const int flag)
737 {
738  const u8 acc_mode = ACC_MODE(flag);
739  int error = 0;
740  struct tomoyo_path_info buf;
741  struct tomoyo_request_info r;
742  struct tomoyo_obj_info obj = {
743  .path1 = *path,
744  };
745  int idx;
746 
747  buf.name = NULL;
749  idx = tomoyo_read_lock();
750  if (acc_mode &&
753  if (!tomoyo_get_realpath(&buf, path)) {
754  error = -ENOMEM;
755  goto out;
756  }
757  r.obj = &obj;
758  if (acc_mode & MAY_READ)
759  error = tomoyo_path_permission(&r, TOMOYO_TYPE_READ,
760  &buf);
761  if (!error && (acc_mode & MAY_WRITE))
762  error = tomoyo_path_permission(&r, (flag & O_APPEND) ?
765  &buf);
766  }
767  out:
768  kfree(buf.name);
769  tomoyo_read_unlock(idx);
770  if (r.mode != TOMOYO_CONFIG_ENFORCING)
771  error = 0;
772  return error;
773 }
774 
785 int tomoyo_path_perm(const u8 operation, struct path *path, const char *target)
786 {
787  struct tomoyo_request_info r;
788  struct tomoyo_obj_info obj = {
789  .path1 = *path,
790  };
791  int error;
792  struct tomoyo_path_info buf;
793  bool is_enforce;
794  struct tomoyo_path_info symlink_target;
795  int idx;
796 
797  if (tomoyo_init_request_info(&r, NULL, tomoyo_p2mac[operation])
799  return 0;
800  is_enforce = (r.mode == TOMOYO_CONFIG_ENFORCING);
801  error = -ENOMEM;
802  buf.name = NULL;
803  idx = tomoyo_read_lock();
804  if (!tomoyo_get_realpath(&buf, path))
805  goto out;
806  r.obj = &obj;
807  switch (operation) {
808  case TOMOYO_TYPE_RMDIR:
809  case TOMOYO_TYPE_CHROOT:
810  tomoyo_add_slash(&buf);
811  break;
812  case TOMOYO_TYPE_SYMLINK:
813  symlink_target.name = tomoyo_encode(target);
814  if (!symlink_target.name)
815  goto out;
816  tomoyo_fill_path_info(&symlink_target);
817  obj.symlink_target = &symlink_target;
818  break;
819  }
820  error = tomoyo_path_permission(&r, operation, &buf);
821  if (operation == TOMOYO_TYPE_SYMLINK)
822  kfree(symlink_target.name);
823  out:
824  kfree(buf.name);
825  tomoyo_read_unlock(idx);
826  if (!is_enforce)
827  error = 0;
828  return error;
829 }
830 
841 int tomoyo_mkdev_perm(const u8 operation, struct path *path,
842  const unsigned int mode, unsigned int dev)
843 {
844  struct tomoyo_request_info r;
845  struct tomoyo_obj_info obj = {
846  .path1 = *path,
847  };
848  int error = -ENOMEM;
849  struct tomoyo_path_info buf;
850  int idx;
851 
852  if (tomoyo_init_request_info(&r, NULL, tomoyo_pnnn2mac[operation])
854  return 0;
855  idx = tomoyo_read_lock();
856  error = -ENOMEM;
857  if (tomoyo_get_realpath(&buf, path)) {
858  r.obj = &obj;
859  dev = new_decode_dev(dev);
861  r.param.mkdev.filename = &buf;
862  r.param.mkdev.operation = operation;
863  r.param.mkdev.mode = mode;
864  r.param.mkdev.major = MAJOR(dev);
865  r.param.mkdev.minor = MINOR(dev);
866  tomoyo_check_acl(&r, tomoyo_check_mkdev_acl);
867  error = tomoyo_audit_mkdev_log(&r);
868  kfree(buf.name);
869  }
870  tomoyo_read_unlock(idx);
871  if (r.mode != TOMOYO_CONFIG_ENFORCING)
872  error = 0;
873  return error;
874 }
875 
885 int tomoyo_path2_perm(const u8 operation, struct path *path1,
886  struct path *path2)
887 {
888  int error = -ENOMEM;
889  struct tomoyo_path_info buf1;
890  struct tomoyo_path_info buf2;
891  struct tomoyo_request_info r;
892  struct tomoyo_obj_info obj = {
893  .path1 = *path1,
894  .path2 = *path2,
895  };
896  int idx;
897 
898  if (tomoyo_init_request_info(&r, NULL, tomoyo_pp2mac[operation])
900  return 0;
901  buf1.name = NULL;
902  buf2.name = NULL;
903  idx = tomoyo_read_lock();
904  if (!tomoyo_get_realpath(&buf1, path1) ||
905  !tomoyo_get_realpath(&buf2, path2))
906  goto out;
907  switch (operation) {
908  struct dentry *dentry;
909  case TOMOYO_TYPE_RENAME:
910  case TOMOYO_TYPE_LINK:
911  dentry = path1->dentry;
912  if (!dentry->d_inode || !S_ISDIR(dentry->d_inode->i_mode))
913  break;
914  /* fall through */
916  tomoyo_add_slash(&buf1);
917  tomoyo_add_slash(&buf2);
918  break;
919  }
920  r.obj = &obj;
922  r.param.path2.operation = operation;
923  r.param.path2.filename1 = &buf1;
924  r.param.path2.filename2 = &buf2;
925  do {
926  tomoyo_check_acl(&r, tomoyo_check_path2_acl);
927  error = tomoyo_audit_path2_log(&r);
928  } while (error == TOMOYO_RETRY_REQUEST);
929  out:
930  kfree(buf1.name);
931  kfree(buf2.name);
932  tomoyo_read_unlock(idx);
933  if (r.mode != TOMOYO_CONFIG_ENFORCING)
934  error = 0;
935  return error;
936 }
937 
946 static bool tomoyo_same_mount_acl(const struct tomoyo_acl_info *a,
947  const struct tomoyo_acl_info *b)
948 {
949  const struct tomoyo_mount_acl *p1 = container_of(a, typeof(*p1), head);
950  const struct tomoyo_mount_acl *p2 = container_of(b, typeof(*p2), head);
951  return tomoyo_same_name_union(&p1->dev_name, &p2->dev_name) &&
952  tomoyo_same_name_union(&p1->dir_name, &p2->dir_name) &&
953  tomoyo_same_name_union(&p1->fs_type, &p2->fs_type) &&
954  tomoyo_same_number_union(&p1->flags, &p2->flags);
955 }
956 
966 static int tomoyo_update_mount_acl(struct tomoyo_acl_param *param)
967 {
968  struct tomoyo_mount_acl e = { .head.type = TOMOYO_TYPE_MOUNT_ACL };
969  int error;
970  if (!tomoyo_parse_name_union(param, &e.dev_name) ||
971  !tomoyo_parse_name_union(param, &e.dir_name) ||
972  !tomoyo_parse_name_union(param, &e.fs_type) ||
973  !tomoyo_parse_number_union(param, &e.flags))
974  error = -EINVAL;
975  else
976  error = tomoyo_update_domain(&e.head, sizeof(e), param,
977  tomoyo_same_mount_acl, NULL);
982  return error;
983 }
984 
995 {
996  u16 perm = 0;
997  u8 type;
998  const char *operation = tomoyo_read_token(param);
999  for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++)
1000  if (tomoyo_permstr(operation, tomoyo_path_keyword[type]))
1001  perm |= 1 << type;
1002  if (perm)
1003  return tomoyo_update_path_acl(perm, param);
1004  for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++)
1005  if (tomoyo_permstr(operation,
1007  perm |= 1 << type;
1008  if (perm)
1009  return tomoyo_update_path2_acl(perm, param);
1010  for (type = 0; type < TOMOYO_MAX_PATH_NUMBER_OPERATION; type++)
1011  if (tomoyo_permstr(operation,
1013  perm |= 1 << type;
1014  if (perm)
1015  return tomoyo_update_path_number_acl(perm, param);
1016  for (type = 0; type < TOMOYO_MAX_MKDEV_OPERATION; type++)
1017  if (tomoyo_permstr(operation,
1019  perm |= 1 << type;
1020  if (perm)
1021  return tomoyo_update_mkdev_acl(perm, param);
1022  if (tomoyo_permstr(operation,
1024  return tomoyo_update_mount_acl(param);
1025  return -EINVAL;
1026 }