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

Subversion リポジトリの参照

Diff of /trunk/1.8.x/ccs-patch/security/ccsecurity/domain.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1029 by kumaneko, Mon Mar 10 08:00:50 2008 UTC revision 1031 by kumaneko, Tue Mar 11 04:38:56 2008 UTC
# Line 5  Line 5 
5   *   *
6   * Copyright (C) 2005-2008  NTT DATA CORPORATION   * Copyright (C) 2005-2008  NTT DATA CORPORATION
7   *   *
8   * Version: 1.6.0-pre   2008/03/10   * Version: 1.6.0-pre   2008/03/11
9   *   *
10   * This file is applicable to both 2.4.30 and 2.6.11 and later.   * This file is applicable to both 2.4.30 and 2.6.11 and later.
11   * See README.ccs for ChangeLog.   * See README.ccs for ChangeLog.
# Line 534  struct domain_info *FindOrAssignNewDomai Line 534  struct domain_info *FindOrAssignNewDomai
534          return domain;          return domain;
535  }  }
536    
537  static int Escape(char *dest, const char *src, int dest_len)  static bool get_argv0(struct linux_binprm *bprm, struct ccs_page_buffer *tmp)
538  {  {
539          while (*src) {          char *arg_ptr = tmp->buffer;
                 const unsigned char c = * (const unsigned char *) src;  
                 if (c == '\\') {  
                         dest_len -= 2;  
                         if (dest_len <= 0) goto out;  
                         *dest++ = '\\';  
                         *dest++ = '\\';  
                 } else if (c > ' ' && c < 127) {  
                         if (--dest_len <= 0) goto out;  
                         *dest++ = c;  
                 } else {  
                         dest_len -= 4;  
                         if (dest_len <= 0) goto out;  
                         *dest++ = '\\';  
                         *dest++ = (c >> 6) + '0';  
                         *dest++ = ((c >> 3) & 7) + '0';  
                         *dest++ = (c & 7) + '0';  
                 }  
                 src++;  
         }  
         if (--dest_len <= 0) goto out;  
         *dest = '\0';  
         return 0;  
  out:  
         return -ENOMEM;  
 }  
   
 static char *get_argv0(struct linux_binprm *bprm)  
 {  
         char *arg_ptr = ccs_alloc(PAGE_SIZE); /* Initial buffer. */  
540          int arg_len = 0;          int arg_len = 0;
541          unsigned long pos = bprm->p;          unsigned long pos = bprm->p;
542          int i = pos / PAGE_SIZE, offset = pos % PAGE_SIZE;          int i = pos / PAGE_SIZE, offset = pos % PAGE_SIZE;
543          if (!bprm->argc || !arg_ptr) goto out;          bool done = false;
544            if (!bprm->argc) goto out;
545          while (1) {          while (1) {
546                  struct page *page;                  struct page *page;
547                    const char *kaddr;
548  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) && defined(CONFIG_MMU)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) && defined(CONFIG_MMU)
549                  if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0) goto out;                  if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0) goto out;
550                    pos += PAGE_SIZE - offset;
551  #else  #else
552                  page = bprm->page[i];                  page = bprm->page[i];
553  #endif  #endif
554                  { /* Map and copy to kernel buffer and unmap. */                  /* Map. */
555                          const char *kaddr = kmap(page);                  kaddr = kmap(page);
556                          if (!kaddr) { /* Mapping failed. */                  if (!kaddr) { /* Mapping failed. */
557  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) && defined(CONFIG_MMU)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) && defined(CONFIG_MMU)
558                                  put_page(page);                          put_page(page);
559  #endif  #endif
560                                  goto out;                          goto out;
561                    }
562                    /* Read. */
563                    while (offset < PAGE_SIZE) {
564                            const unsigned char c = kaddr[offset++];
565                            if (c && arg_len < CCS_MAX_PATHNAME_LEN - 10) {
566                                    if (c == '\\') {
567                                            arg_ptr[arg_len++] = '\\';
568                                            arg_ptr[arg_len++] = '\\';
569                                    } else if (c == '/') {
570                                            arg_len = 0;
571                                    } else if (c > ' ' && c < 127) {
572                                            arg_ptr[arg_len++] = c;
573                                    } else {
574                                            arg_ptr[arg_len++] = '\\';
575                                            arg_ptr[arg_len++] = (c >> 6) + '0';
576                                            arg_ptr[arg_len++] = ((c >> 3) & 7) + '0';
577                                            arg_ptr[arg_len++] = (c & 7) + '0';
578                                    }
579                            } else {
580                                    arg_ptr[arg_len] = '\0';
581                                    done = true;
582                                    break;
583                          }                          }
                         memmove(arg_ptr + arg_len, kaddr + offset, PAGE_SIZE - offset);  
                         kunmap(page);  
584                  }                  }
585                    /* Unmap. */
586                    kunmap(page);
587  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) && defined(CONFIG_MMU)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) && defined(CONFIG_MMU)
588                  put_page(page);                  put_page(page);
                 pos += PAGE_SIZE - offset;  
589  #endif  #endif
                 arg_len += PAGE_SIZE - offset;  
                 if (memchr(arg_ptr, '\0', arg_len)) break;  
                 { /* Initial buffer was too small for argv[0]. Retry after expanding buffer. */  
                         char *tmp_arg_ptr = ccs_alloc(arg_len + PAGE_SIZE);  
                         if (!tmp_arg_ptr) goto out;  
                         memmove(tmp_arg_ptr, arg_ptr, arg_len);  
                         ccs_free(arg_ptr);  
                         arg_ptr = tmp_arg_ptr;  
                 }  
590                  i++;                  i++;
591                  offset = 0;                  offset = 0;
592                    if (done) break;
593          }          }
594          return arg_ptr;          return true;
595   out: /* Release initial buffer. */   out:
596          ccs_free(arg_ptr);          return false;
         return NULL;  
597  }  }
598    
599  static int FindNextDomain(struct linux_binprm *bprm, struct domain_info **next_domain, const struct path_info *path_to_verify)  static int FindNextDomain(struct linux_binprm *bprm, struct domain_info **next_domain, const struct path_info *path_to_verify, struct ccs_page_buffer *tmp)
600  {  {
601          /* This function assumes that the size of buffer returned by realpath() = CCS_MAX_PATHNAME_LEN. */          /* This function assumes that the size of buffer returned by realpath() = CCS_MAX_PATHNAME_LEN. */
602          struct domain_info *old_domain = current->domain_info, *domain = NULL;          struct domain_info *old_domain = current->domain_info, *domain = NULL;
# Line 675  static int FindNextDomain(struct linux_b Line 661  static int FindNextDomain(struct linux_b
661                    
662          /* Compare basename of real_program_name and argv[0] */          /* Compare basename of real_program_name and argv[0] */
663          if (bprm->argc > 0 && CheckCCSFlags(CCS_TOMOYO_MAC_FOR_ARGV0)) {          if (bprm->argc > 0 && CheckCCSFlags(CCS_TOMOYO_MAC_FOR_ARGV0)) {
664                  char *org_argv0 = get_argv0(bprm);                  char *base_argv0 = tmp->buffer;
665                    const char *base_filename;
666                  retval = -ENOMEM;                  retval = -ENOMEM;
667                  if (org_argv0) {                  if (!get_argv0(bprm, tmp)) goto out;
668                          const int len = strlen(org_argv0);                  if ((base_filename = strrchr(real_program_name, '/')) == NULL) base_filename = real_program_name; else base_filename++;
669                          char *printable_argv0 = ccs_alloc(len * 4 + 8);                  if (strcmp(base_argv0, base_filename)) {
670                          if (printable_argv0 && Escape(printable_argv0, org_argv0, len * 4 + 8) == 0) {                          retval = CheckArgv0Perm(&r, base_argv0);
671                                  const char *base_argv0, *base_filename;                          if (retval) goto out;
                                 if ((base_argv0 = strrchr(printable_argv0, '/')) == NULL) base_argv0 = printable_argv0; else base_argv0++;  
                                 if ((base_filename = strrchr(real_program_name, '/')) == NULL) base_filename = real_program_name; else base_filename++;  
                                 if (strcmp(base_argv0, base_filename)) retval = CheckArgv0Perm(&r, base_argv0);  
                                 else retval = 0;  
                         }  
                         ccs_free(printable_argv0);  
                         ccs_free(org_argv0);  
672                  }                  }
                 if (retval) goto out;  
673          }          }
674                    
675          /* Check 'aggregator' directive. */          /* Check 'aggregator' directive. */
# Line 707  static int FindNextDomain(struct linux_b Line 686  static int FindNextDomain(struct linux_b
686          }          }
687    
688          /* Check execute permission. */          /* Check execute permission. */
689          if ((retval = CheckExecPerm(&r, bprm)) < 0) goto out;          if ((retval = CheckExecPerm(&r, bprm, tmp)) < 0) goto out;
690    
691   ok: ;   ok: ;
692          /* Allocate memory for calcurating domain name. */          new_domain_name = tmp->buffer;
         retval = -ENOMEM;  
         if ((new_domain_name = ccs_alloc(CCS_MAX_PATHNAME_LEN + 16)) == NULL) goto out;  
           
693          if (IsDomainInitializer(old_domain->domainname, &r, &l)) {          if (IsDomainInitializer(old_domain->domainname, &r, &l)) {
694                  /* Transit to the child of KERNEL_DOMAIN domain. */                  /* Transit to the child of KERNEL_DOMAIN domain. */
695                  snprintf(new_domain_name, CCS_MAX_PATHNAME_LEN + 1, ROOT_NAME " " "%s", real_program_name);                  snprintf(new_domain_name, CCS_MAX_PATHNAME_LEN + 1, ROOT_NAME " " "%s", real_program_name);
# Line 745  static int FindNextDomain(struct linux_b Line 721  static int FindNextDomain(struct linux_b
721                  retval = 0;                  retval = 0;
722          }          }
723   out: ;   out: ;
         ccs_free(new_domain_name);  
724          ccs_free(real_program_name);          ccs_free(real_program_name);
725          ccs_free(symlink_program_name);          ccs_free(symlink_program_name);
726          *next_domain = domain ? domain : old_domain;          *next_domain = domain ? domain : old_domain;
727          return retval;          return retval;
728  }  }
729    
730  static int CheckEnviron(struct linux_binprm *bprm)  static int CheckEnviron(struct linux_binprm *bprm, struct ccs_page_buffer *tmp)
731  {  {
732          const u8 profile = current->domain_info->profile;          const u8 profile = current->domain_info->profile;
733          const u8 mode = CheckCCSFlags(CCS_TOMOYO_MAC_FOR_ENV);          const u8 mode = CheckCCSFlags(CCS_TOMOYO_MAC_FOR_ENV);
734          char *arg_ptr;          char *arg_ptr = tmp->buffer;
735          int arg_len = 0;          int arg_len = 0;
736          unsigned long pos = bprm->p;          unsigned long pos = bprm->p;
737          int i = pos / PAGE_SIZE, offset = pos % PAGE_SIZE;          int i = pos / PAGE_SIZE, offset = pos % PAGE_SIZE;
# Line 765  static int CheckEnviron(struct linux_bin Line 740  static int CheckEnviron(struct linux_bin
740          //printk("start %d %d\n", argv_count, envp_count);          //printk("start %d %d\n", argv_count, envp_count);
741          int error = -ENOMEM;          int error = -ENOMEM;
742          if (!mode || !envp_count) return 0;          if (!mode || !envp_count) return 0;
         arg_ptr = ccs_alloc(CCS_MAX_PATHNAME_LEN);  
         if (!arg_ptr) goto out;  
743          while (error == -ENOMEM) {          while (error == -ENOMEM) {
744                  struct page *page;                  struct page *page;
745                  const char *kaddr;                  const char *kaddr;
# Line 776  static int CheckEnviron(struct linux_bin Line 749  static int CheckEnviron(struct linux_bin
749  #else  #else
750                  page = bprm->page[i];                  page = bprm->page[i];
751  #endif  #endif
752                  /* Map */                  /* Map. */
753                  kaddr = kmap(page);                  kaddr = kmap(page);
754                  if (!kaddr) { /* Mapping failed. */                  if (!kaddr) { /* Mapping failed. */
755  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) && defined(CONFIG_MMU)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23) && defined(CONFIG_MMU)
# Line 829  static int CheckEnviron(struct linux_bin Line 802  static int CheckEnviron(struct linux_bin
802                  offset = 0;                  offset = 0;
803          }          }
804   out:   out:
         ccs_free(arg_ptr);  
805          if (error && mode != 3) error = 0;          if (error && mode != 3) error = 0;
806          return error;          return error;
807  }  }
# Line 914  static int GetRootDepth(void) Line 886  static int GetRootDepth(void)
886          return depth;          return depth;
887  }  }
888    
889  static int try_alt_exec(struct linux_binprm *bprm, const struct path_info *filename, char **work, struct domain_info **next_domain)  static int try_alt_exec(struct linux_binprm *bprm, const struct path_info *filename, char **work, struct domain_info **next_domain, struct ccs_page_buffer *tmp)
890  {  {
891          /*          /*
892           * Contents of modified bprm.           * Contents of modified bprm.
# Line 957  static int try_alt_exec(struct linux_bin Line 929  static int try_alt_exec(struct linux_bin
929          const int original_argc = bprm->argc;          const int original_argc = bprm->argc;
930          const int original_envc = bprm->envc;          const int original_envc = bprm->envc;
931          struct task_struct *task = current;          struct task_struct *task = current;
932          static const int buffer_len = CCS_MAX_PATHNAME_LEN;          char *buffer = tmp->buffer;
         char *buffer = NULL;  
         char *execute_handler;  
   
         /* Close the requested program's dentry. */  
         allow_write_access(bprm->file);  
         fput(bprm->file);  
         bprm->file = NULL;  
   
933          /* Allocate memory for execute handler's pathname. */          /* Allocate memory for execute handler's pathname. */
934          execute_handler = ccs_alloc(buffer_len);          char *execute_handler = ccs_alloc(sizeof(struct ccs_page_buffer));
935          *work = execute_handler;          *work = execute_handler;
936          if (!execute_handler) return -ENOMEM;          if (!execute_handler) return -ENOMEM;
937          strncpy(execute_handler, filename->name, buffer_len - 1);          strncpy(execute_handler, filename->name, sizeof(struct ccs_page_buffer) - 1);
938          UnEscape(execute_handler);          UnEscape(execute_handler);
939                    
940          if (1) { /* Adjust root directory for open_exec(). */          /* Close the requested program's dentry. */
941            allow_write_access(bprm->file);
942            fput(bprm->file);
943            bprm->file = NULL;
944    
945            { /* Adjust root directory for open_exec(). */
946                  int depth = GetRootDepth();                  int depth = GetRootDepth();
947                  char *cp = execute_handler;                  char *cp = execute_handler;
948                  if (!*cp || *cp != '/') return -ENOENT;                  if (!*cp || *cp != '/') return -ENOENT;
# Line 985  static int try_alt_exec(struct linux_bin Line 954  static int try_alt_exec(struct linux_bin
954                  memmove(execute_handler, cp, strlen(cp) + 1);                  memmove(execute_handler, cp, strlen(cp) + 1);
955          }          }
956    
         /* Allocate buffer. */  
         buffer = ccs_alloc(buffer_len);  
         if (!buffer) return -ENOMEM;  
   
957          /* Move envp[] to argv[] */          /* Move envp[] to argv[] */
958          bprm->argc += bprm->envc;          bprm->argc += bprm->envc;
959          bprm->envc = 0;          bprm->envc = 0;
960    
961          /* Set argv[6] */          /* Set argv[6] */
962          {          {
963                  snprintf(buffer, buffer_len - 1, "%d", original_envc);                  snprintf(buffer, sizeof(struct ccs_page_buffer) - 1, "%d", original_envc);
964                  retval = copy_strings_kernel(1, &buffer, bprm);                  retval = copy_strings_kernel(1, &buffer, bprm);
965                  if (retval < 0) goto out;                  if (retval < 0) goto out;
966                  bprm->argc++;                  bprm->argc++;
# Line 1003  static int try_alt_exec(struct linux_bin Line 968  static int try_alt_exec(struct linux_bin
968    
969          /* Set argv[5] */          /* Set argv[5] */
970          {          {
971                  snprintf(buffer, buffer_len - 1, "%d", original_argc);                  snprintf(buffer, sizeof(struct ccs_page_buffer) - 1, "%d", original_argc);
972                  retval = copy_strings_kernel(1, &buffer, bprm);                  retval = copy_strings_kernel(1, &buffer, bprm);
973                  if (retval < 0) goto out;                  if (retval < 0) goto out;
974                  bprm->argc++;                  bprm->argc++;
# Line 1019  static int try_alt_exec(struct linux_bin Line 984  static int try_alt_exec(struct linux_bin
984          /* Set argv[3] */          /* Set argv[3] */
985          {          {
986                  const u32 tomoyo_flags = task->tomoyo_flags;                  const u32 tomoyo_flags = task->tomoyo_flags;
987                  snprintf(buffer, buffer_len - 1, "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d sgid=%d fsuid=%d fsgid=%d state[0]=%u state[1]=%u state[2]=%u", task->pid, task->uid, task->gid, task->euid, task->egid, task->suid, task->sgid, task->fsuid, task->fsgid, (u8) (tomoyo_flags >> 24), (u8) (tomoyo_flags >> 16), (u8) (tomoyo_flags >> 8));                  snprintf(buffer, sizeof(struct ccs_page_buffer) - 1, "pid=%d uid=%d gid=%d euid=%d egid=%d suid=%d sgid=%d fsuid=%d fsgid=%d state[0]=%u state[1]=%u state[2]=%u", task->pid, task->uid, task->gid, task->euid, task->egid, task->suid, task->sgid, task->fsuid, task->fsgid, (u8) (tomoyo_flags >> 24), (u8) (tomoyo_flags >> 16), (u8) (tomoyo_flags >> 8));
988                  retval = copy_strings_kernel(1, &buffer, bprm);                  retval = copy_strings_kernel(1, &buffer, bprm);
989                  if (retval < 0) goto out;                  if (retval < 0) goto out;
990                  bprm->argc++;                  bprm->argc++;
# Line 1032  static int try_alt_exec(struct linux_bin Line 997  static int try_alt_exec(struct linux_bin
997                          retval = copy_strings_kernel(1, &exe, bprm);                          retval = copy_strings_kernel(1, &exe, bprm);
998                          ccs_free(exe);                          ccs_free(exe);
999                  } else {                  } else {
1000                          snprintf(buffer, buffer_len - 1, "<unknown>");                          snprintf(buffer, sizeof(struct ccs_page_buffer) - 1, "<unknown>");
1001                          retval = copy_strings_kernel(1, &buffer, bprm);                          retval = copy_strings_kernel(1, &buffer, bprm);
1002                  }                  }
1003                  if (retval < 0) goto out;                  if (retval < 0) goto out;
# Line 1041  static int try_alt_exec(struct linux_bin Line 1006  static int try_alt_exec(struct linux_bin
1006    
1007          /* Set argv[1] */          /* Set argv[1] */
1008          {          {
1009                  strncpy(buffer, task->domain_info->domainname->name, buffer_len - 1);                  strncpy(buffer, task->domain_info->domainname->name, sizeof(struct ccs_page_buffer) - 1);
1010                  retval = copy_strings_kernel(1, &buffer, bprm);                  retval = copy_strings_kernel(1, &buffer, bprm);
1011                  if (retval < 0) goto out;                  if (retval < 0) goto out;
1012                  bprm->argc++;                  bprm->argc++;
# Line 1071  static int try_alt_exec(struct linux_bin Line 1036  static int try_alt_exec(struct linux_bin
1036          retval = prepare_binprm(bprm);          retval = prepare_binprm(bprm);
1037          if (retval < 0) goto out;          if (retval < 0) goto out;
1038          task->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          task->tomoyo_flags |= CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1039          retval = FindNextDomain(bprm, next_domain, filename);          retval = FindNextDomain(bprm, next_domain, filename, tmp);
1040          task->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;          task->tomoyo_flags &= ~CCS_DONT_SLEEP_ON_ENFORCE_ERROR;
1041   out:   out:
         /* Free buffer. */  
         ccs_free(buffer);  
1042          return retval;          return retval;
1043  }  }
1044    
# Line 1100  int search_binary_handler_with_transitio Line 1063  int search_binary_handler_with_transitio
1063          const struct path_info *handler;          const struct path_info *handler;
1064          int retval;          int retval;
1065          char *work = NULL; /* Keep valid until search_binary_handler() finishes. */          char *work = NULL; /* Keep valid until search_binary_handler() finishes. */
1066            struct ccs_page_buffer *buf = ccs_alloc(sizeof(struct ccs_page_buffer));
1067          CCS_LoadPolicy(bprm->filename);          CCS_LoadPolicy(bprm->filename);
1068            if (!buf) return -ENOMEM;
1069          //printk("rootdepth=%d\n", GetRootDepth());          //printk("rootdepth=%d\n", GetRootDepth());
1070          handler = FindExecuteHandler(true);          handler = FindExecuteHandler(true);
1071          if (handler) {          if (handler) {
1072                  retval = try_alt_exec(bprm, handler, &work, &next_domain);                  retval = try_alt_exec(bprm, handler, &work, &next_domain, buf);
1073          } else if ((retval = FindNextDomain(bprm, &next_domain, NULL)) == -EPERM) {          } else if ((retval = FindNextDomain(bprm, &next_domain, NULL, buf)) == -EPERM) {
1074                  handler = FindExecuteHandler(false);                  handler = FindExecuteHandler(false);
1075                  if (handler) retval = try_alt_exec(bprm, handler, &work, &next_domain);                  if (handler) retval = try_alt_exec(bprm, handler, &work, &next_domain, buf);
1076          }          }
1077          if (retval) goto out;          if (retval) goto out;
1078          task->domain_info = next_domain;          task->domain_info = next_domain;
1079          retval = CheckEnviron(bprm);          retval = CheckEnviron(bprm, buf);
1080          if (retval) goto out;          if (retval) goto out;
1081          task->tomoyo_flags |= TOMOYO_CHECK_READ_FOR_OPEN_EXEC;          task->tomoyo_flags |= TOMOYO_CHECK_READ_FOR_OPEN_EXEC;
1082          retval = search_binary_handler(bprm, regs);          retval = search_binary_handler(bprm, regs);
# Line 1119  int search_binary_handler_with_transitio Line 1084  int search_binary_handler_with_transitio
1084   out:   out:
1085          if (retval < 0) task->domain_info = prev_domain;          if (retval < 0) task->domain_info = prev_domain;
1086          ccs_free(work);          ccs_free(work);
1087            ccs_free(buf);
1088          return retval;          return retval;
1089  }  }
1090    

Legend:
Removed from v.1029  
changed lines
  Added in v.1031

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