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

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 2951 by kumaneko, Tue Aug 25 04:26:20 2009 UTC revision 3162 by kumaneko, Mon Nov 9 06:10:32 2009 UTC
# Line 3  Line 3 
3   *   *
4   * Copyright (C) 2005-2009  NTT DATA CORPORATION   * Copyright (C) 2005-2009  NTT DATA CORPORATION
5   *   *
6   * Version: 1.7.0-pre   2009/08/24   * Version: 1.7.1-rc   2009/11/09
7   *   *
8   * 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.
9   * See README.ccs for ChangeLog.   * See README.ccs for ChangeLog.
# Line 22  Line 22 
22  #endif  #endif
23  #include "internal.h"  #include "internal.h"
24    
 /* For compatibility with older kernels. */  
 #ifndef for_each_process  
 #define for_each_process for_each_task  
 #endif  
   
25  /* Variables definitions.*/  /* Variables definitions.*/
26    
27  /* The initial domain. */  /* The initial domain. */
# Line 653  static int ccs_find_next_domain(struct c Line 648  static int ccs_find_next_domain(struct c
648          domain = ccs_find_domain(ee->tmp);          domain = ccs_find_domain(ee->tmp);
649          if (domain)          if (domain)
650                  goto done;                  goto done;
651          if (r->mode == CCS_MAC_MODE_ENFORCING) {          if (r->mode == CCS_CONFIG_ENFORCING) {
652                  int error = ccs_supervisor(r, "# wants to create domain\n"                  int error = ccs_supervisor(r, "# wants to create domain\n"
653                                             "%s\n", ee->tmp);                                             "%s\n", ee->tmp);
654                  if (error == 1)                  if (error == 1)
# Line 668  static int ccs_find_next_domain(struct c Line 663  static int ccs_find_next_domain(struct c
663          if (!domain) {          if (!domain) {
664                  printk(KERN_WARNING "ERROR: Domain '%s' not defined.\n",                  printk(KERN_WARNING "ERROR: Domain '%s' not defined.\n",
665                         ee->tmp);                         ee->tmp);
666                  if (r->mode == CCS_MAC_MODE_ENFORCING)                  if (r->mode == CCS_CONFIG_ENFORCING)
667                          retval = -EPERM;                          retval = -EPERM;
668                  else {                  else {
669                          retval = 0;                          retval = 0;
# Line 696  static int ccs_environ(struct ccs_execve Line 691  static int ccs_environ(struct ccs_execve
691  {  {
692          struct ccs_request_info *r = &ee->r;          struct ccs_request_info *r = &ee->r;
693          struct linux_binprm *bprm = ee->bprm;          struct linux_binprm *bprm = ee->bprm;
694          char *arg_ptr = ee->tmp;          /* env_page->data is allocated by ccs_dump_page(). */
695            struct ccs_page_dump env_page = { };
696            char *arg_ptr; /* Size is CCS_EXEC_TMPSIZE bytes */
697          int arg_len = 0;          int arg_len = 0;
698          unsigned long pos = bprm->p;          unsigned long pos = bprm->p;
699          int offset = pos % PAGE_SIZE;          int offset = pos % PAGE_SIZE;
# Line 706  static int ccs_environ(struct ccs_execve Line 703  static int ccs_environ(struct ccs_execve
703          int error = -ENOMEM;          int error = -ENOMEM;
704          if (!r->mode || !envp_count)          if (!r->mode || !envp_count)
705                  return 0;                  return 0;
706            arg_ptr = kzalloc(CCS_EXEC_TMPSIZE, GFP_KERNEL);
707            if (!arg_ptr)
708                    goto out;
709          while (error == -ENOMEM) {          while (error == -ENOMEM) {
710                  if (!ccs_dump_page(bprm, pos, &ee->dump))                  if (!ccs_dump_page(bprm, pos, &env_page))
711                          goto out;                          goto out;
712                  pos += PAGE_SIZE - offset;                  pos += PAGE_SIZE - offset;
713                  /* Read. */                  /* Read. */
714                  while (argv_count && offset < PAGE_SIZE) {                  while (argv_count && offset < PAGE_SIZE) {
715                          const char *kaddr = ee->dump.data;                          if (!env_page.data[offset++])
                         if (!kaddr[offset++])  
716                                  argv_count--;                                  argv_count--;
717                  }                  }
718                  if (argv_count) {                  if (argv_count) {
# Line 721  static int ccs_environ(struct ccs_execve Line 720  static int ccs_environ(struct ccs_execve
720                          continue;                          continue;
721                  }                  }
722                  while (offset < PAGE_SIZE) {                  while (offset < PAGE_SIZE) {
723                          const char *kaddr = ee->dump.data;                          const unsigned char c = env_page.data[offset++];
                         const unsigned char c = kaddr[offset++];  
724                          if (c && arg_len < CCS_EXEC_TMPSIZE - 10) {                          if (c && arg_len < CCS_EXEC_TMPSIZE - 10) {
725                                  if (c == '=') {                                  if (c == '=') {
726                                          arg_ptr[arg_len++] = '\0';                                          arg_ptr[arg_len++] = '\0';
# Line 758  static int ccs_environ(struct ccs_execve Line 756  static int ccs_environ(struct ccs_execve
756   out:   out:
757          if (r->mode != 3)          if (r->mode != 3)
758                  error = 0;                  error = 0;
759            kfree(env_page.data);
760          return error;          return error;
761  }  }
762    
# Line 862  static int ccs_get_root_depth(void) Line 861  static int ccs_get_root_depth(void)
861          return depth;          return depth;
862  }  }
863    
 static LIST_HEAD(ccs_execve_list);  
 static DEFINE_SPINLOCK(ccs_execve_list_lock);  
   
 /**  
  * ccs_allocate_execve_entry - Allocate memory for execve().  
  *  
  * Returns pointer to "struct ccs_execve_entry" on success, NULL otherwise.  
  */  
 static struct ccs_execve_entry *ccs_allocate_execve_entry(void)  
 {  
         struct ccs_execve_entry *ee = kzalloc(sizeof(*ee), GFP_KERNEL);  
         if (!ee)  
                 return NULL;  
         ee->tmp = kzalloc(CCS_EXEC_TMPSIZE, GFP_KERNEL);  
         if (!ee->tmp) {  
                 kfree(ee);  
                 return NULL;  
         }  
         ee->reader_idx = ccs_read_lock();  
         /* ee->dump->data is allocated by ccs_dump_page(). */  
         ee->task = current;  
         spin_lock(&ccs_execve_list_lock);  
         list_add(&ee->list, &ccs_execve_list);  
         spin_unlock(&ccs_execve_list_lock);  
         return ee;  
 }  
   
 /**  
  * ccs_find_execve_entry - Find ccs_execve_entry of current process.  
  *  
  * Returns pointer to "struct ccs_execve_entry" on success, NULL otherwise.  
  */  
 static struct ccs_execve_entry *ccs_find_execve_entry(void)  
 {  
         struct task_struct *task = current;  
         struct ccs_execve_entry *ee = NULL;  
         struct ccs_execve_entry *p;  
         spin_lock(&ccs_execve_list_lock);  
         list_for_each_entry(p, &ccs_execve_list, list) {  
                 if (p->task != task)  
                         continue;  
                 ee = p;  
                 break;  
         }  
         spin_unlock(&ccs_execve_list_lock);  
         return ee;  
 }  
   
 /**  
  * ccs_free_execve_entry - Free memory for execve().  
  *  
  * @ee: Pointer to "struct ccs_execve_entry".  
  */  
 static void ccs_free_execve_entry(struct ccs_execve_entry *ee)  
 {  
         if (!ee)  
                 return;  
         spin_lock(&ccs_execve_list_lock);  
         list_del(&ee->list);  
         spin_unlock(&ccs_execve_list_lock);  
         kfree(ee->handler_path);  
         kfree(ee->tmp);  
         kfree(ee->dump.data);  
         ccs_read_unlock(ee->reader_idx);  
         kfree(ee);  
 }  
   
864  /**  /**
865   * ccs_try_alt_exec - Try to start execute handler.   * ccs_try_alt_exec - Try to start execute handler.
866   *   *
# Line 982  static int ccs_try_alt_exec(struct ccs_e Line 914  static int ccs_try_alt_exec(struct ccs_e
914          struct task_struct *task = current;          struct task_struct *task = current;
915    
916          /* Close the requested program's dentry. */          /* Close the requested program's dentry. */
917            ee->obj.path1.dentry = NULL;
918            ee->obj.path1.mnt = NULL;
919            ee->obj.validate_done = false;
920          allow_write_access(bprm->file);          allow_write_access(bprm->file);
921          fput(bprm->file);          fput(bprm->file);
922          bprm->file = NULL;          bprm->file = NULL;
# Line 1073  static int ccs_try_alt_exec(struct ccs_e Line 1008  static int ccs_try_alt_exec(struct ccs_e
1008                  int len = ee->handler->total_len + 1;                  int len = ee->handler->total_len + 1;
1009                  char *cp = kmalloc(len, GFP_KERNEL);                  char *cp = kmalloc(len, GFP_KERNEL);
1010                  if (!cp) {                  if (!cp) {
1011                          retval = ENOMEM;                          retval = -ENOMEM;
1012                          goto out;                          goto out;
1013                  }                  }
1014                  ee->handler_path = cp;                  ee->handler_path = cp;
# Line 1108  static int ccs_try_alt_exec(struct ccs_e Line 1043  static int ccs_try_alt_exec(struct ccs_e
1043                  retval = PTR_ERR(filp);                  retval = PTR_ERR(filp);
1044                  goto out;                  goto out;
1045          }          }
1046            ee->obj.path1.dentry = filp->f_dentry;
1047            ee->obj.path1.mnt = filp->f_vfsmnt;
1048          bprm->file = filp;          bprm->file = filp;
1049          bprm->filename = ee->handler_path;          bprm->filename = ee->handler_path;
1050  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 0)
# Line 1172  bool ccs_dump_page(struct linux_binprm * Line 1109  bool ccs_dump_page(struct linux_binprm *
1109                     struct ccs_page_dump *dump)                     struct ccs_page_dump *dump)
1110  {  {
1111          struct page *page;          struct page *page;
1112          /* dump->data is released by ccs_free_execve_entry(). */          /* dump->data is released by ccs_finish_execve(). */
1113          if (!dump->data) {          if (!dump->data) {
1114                  dump->data = kzalloc(PAGE_SIZE, GFP_KERNEL);                  dump->data = kzalloc(PAGE_SIZE, GFP_KERNEL);
1115                  if (!dump->data)                  if (!dump->data)
# Line 1182  bool ccs_dump_page(struct linux_binprm * Line 1119  bool ccs_dump_page(struct linux_binprm *
1119  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)
1120          if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)          if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
1121                  return false;                  return false;
1122  #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR == 3 && defined(CONFIG_MMU)  #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR >= 3 && defined(CONFIG_MMU)
1123            if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
1124                    return false;
1125    #elif defined(AX_MAJOR) && AX_MAJOR == 3 && defined(AX_MINOR) && AX_MINOR >= 2 && defined(CONFIG_MMU)
1126          if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)          if (get_user_pages(current, bprm->mm, pos, 1, 0, 1, &page, NULL) <= 0)
1127                  return false;                  return false;
1128  #else  #else
# Line 1203  bool ccs_dump_page(struct linux_binprm * Line 1143  bool ccs_dump_page(struct linux_binprm *
1143          /* Same with put_arg_page(page) in fs/exec.c */          /* Same with put_arg_page(page) in fs/exec.c */
1144  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 23) && defined(CONFIG_MMU)
1145          put_page(page);          put_page(page);
1146  #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR == 3 && defined(CONFIG_MMU)  #elif defined(RHEL_MAJOR) && RHEL_MAJOR == 5 && defined(RHEL_MINOR) && RHEL_MINOR >= 3 && defined(CONFIG_MMU)
1147            put_page(page);
1148    #elif defined(AX_MAJOR) && AX_MAJOR == 3 && defined(AX_MINOR) && AX_MINOR >= 2 && defined(CONFIG_MMU)
1149          put_page(page);          put_page(page);
1150  #endif  #endif
1151          return true;          return true;
1152  }  }
1153    
1154  /**  /**
  * ccs_fetch_next_domain - Fetch next_domain from the list.  
  *  
  * Returns pointer to "struct ccs_domain_info" which will be used if execve()  
  * succeeds. This function does not return NULL.  
  */  
 struct ccs_domain_info *ccs_fetch_next_domain(void)  
 {  
         struct ccs_execve_entry *ee = ccs_find_execve_entry();  
         struct ccs_domain_info *next_domain = NULL;  
         if (ee)  
                 next_domain = ee->r.domain;  
         if (!next_domain)  
                 next_domain = ccs_current_domain();  
         return next_domain;  
 }  
   
 /**  
1155   * ccs_start_execve - Prepare for execve() operation.   * ccs_start_execve - Prepare for execve() operation.
1156   *   *
1157   * @bprm: Pointer to "struct linux_binprm".   * @bprm: Pointer to "struct linux_binprm".
1158     * @eep:  Pointer to "struct ccs_execve_entry *".
1159   *   *
1160   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1161   */   */
1162  int ccs_start_execve(struct linux_binprm *bprm)  int ccs_start_execve(struct linux_binprm *bprm, struct ccs_execve_entry **eep)
1163  {  {
1164          int retval;          int retval;
1165          struct task_struct *task = current;          struct task_struct *task = current;
1166          struct ccs_execve_entry *ee = ccs_allocate_execve_entry();          struct ccs_execve_entry *ee;
1167            *eep = NULL;
1168          if (!ccs_policy_loaded)          if (!ccs_policy_loaded)
1169                  ccs_load_policy(bprm->filename);                  ccs_load_policy(bprm->filename);
1170            ee = kzalloc(sizeof(*ee), GFP_KERNEL);
1171          if (!ee)          if (!ee)
1172                  return -ENOMEM;                  return -ENOMEM;
1173            ee->tmp = kzalloc(CCS_EXEC_TMPSIZE, GFP_KERNEL);
1174            if (!ee->tmp) {
1175                    kfree(ee);
1176                    return -ENOMEM;
1177            }
1178            ee->reader_idx = ccs_read_lock();
1179            /* ee->dump->data is allocated by ccs_dump_page(). */
1180            ee->previous_domain = task->ccs_domain_info;
1181            /* Clear manager flag. */
1182            task->ccs_flags &= ~CCS_TASK_IS_POLICY_MANAGER;
1183            /* Tell GC that I started execve(). */
1184            task->ccs_flags |= CCS_TASK_IS_IN_EXECVE;
1185            /*
1186             * Make task->ccs_flags visible to GC before changing
1187             * task->ccs_domain_info .
1188             */
1189            smp_mb();
1190            *eep = ee;
1191          ccs_init_request_info(&ee->r, NULL, CCS_MAC_FILE_EXECUTE);          ccs_init_request_info(&ee->r, NULL, CCS_MAC_FILE_EXECUTE);
1192          ee->r.ee = ee;          ee->r.ee = ee;
1193          ee->bprm = bprm;          ee->bprm = bprm;
1194          ee->r.obj = &ee->obj;          ee->r.obj = &ee->obj;
1195          ee->obj.path1.dentry = bprm->file->f_dentry;          ee->obj.path1.dentry = bprm->file->f_dentry;
1196          ee->obj.path1.mnt = bprm->file->f_vfsmnt;          ee->obj.path1.mnt = bprm->file->f_vfsmnt;
         /* Clear manager flag. */  
         task->ccs_flags &= ~CCS_TASK_IS_POLICY_MANAGER;  
1197          if (ccs_find_execute_handler(ee, CCS_TYPE_EXECUTE_HANDLER)) {          if (ccs_find_execute_handler(ee, CCS_TYPE_EXECUTE_HANDLER)) {
1198                  retval = ccs_try_alt_exec(ee);                  retval = ccs_try_alt_exec(ee);
1199                  if (!retval)                  if (!retval)
# Line 1267  int ccs_start_execve(struct linux_binprm Line 1211  int ccs_start_execve(struct linux_binprm
1211   ok:   ok:
1212          if (retval < 0)          if (retval < 0)
1213                  goto out;                  goto out;
1214          ee->r.mode = ccs_get_mode(ee->r.profile, CCS_MAC_ENVIRON);          /*
1215             * Proceed to the next domain in order to allow reaching via PID.
1216             * It will be reverted if execve() failed. Reverting is not good.
1217             * But it is better than being unable to reach via PID in interactive
1218             * enforcing mode.
1219             */
1220            task->ccs_domain_info = ee->r.domain;
1221            ee->r.mode = ccs_get_mode(ee->r.domain->profile, CCS_MAC_ENVIRON);
1222          retval = ccs_environ(ee);          retval = ccs_environ(ee);
1223          if (retval < 0)          if (retval < 0)
1224                  goto out;                  goto out;
         task->ccs_flags |= CCS_CHECK_READ_FOR_OPEN_EXEC;  
1225          retval = 0;          retval = 0;
1226   out:   out:
         if (retval)  
                 ccs_finish_execve(retval);  
1227          return retval;          return retval;
1228  }  }
1229    
# Line 1283  int ccs_start_execve(struct linux_binprm Line 1231  int ccs_start_execve(struct linux_binprm
1231   * ccs_finish_execve - Clean up execve() operation.   * ccs_finish_execve - Clean up execve() operation.
1232   *   *
1233   * @retval: Return code of an execve() operation.   * @retval: Return code of an execve() operation.
1234     * @ee:     Pointer to "struct ccs_execve_entry".
1235   *   *
1236   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1237   */   */
1238  void ccs_finish_execve(int retval)  void ccs_finish_execve(int retval, struct ccs_execve_entry *ee)
1239  {  {
1240          struct task_struct *task = current;          struct task_struct *task = current;
         struct ccs_execve_entry *ee = ccs_find_execve_entry();  
         task->ccs_flags &= ~CCS_CHECK_READ_FOR_OPEN_EXEC;  
1241          if (!ee)          if (!ee)
1242                  return;                  return;
1243          if (retval < 0)          if (retval < 0) {
1244                  goto out;                  task->ccs_domain_info = ee->previous_domain;
1245          /* Proceed to next domain if execution suceeded. */                  /*
1246          task->ccs_domain_info = ee->r.domain;                   * Make task->ccs_domain_info visible to GC before changing
1247          /* Mark the current process as execute handler. */                   * task->ccs_flags .
1248          if (ee->handler)                   */
1249                  task->ccs_flags |= CCS_TASK_IS_EXECUTE_HANDLER;                  smp_mb();
1250          /* Mark the current process as normal process. */          } else {
1251          else                  /* Mark the current process as execute handler. */
1252                  task->ccs_flags &= ~CCS_TASK_IS_EXECUTE_HANDLER;                  if (ee->handler)
1253   out:                          task->ccs_flags |= CCS_TASK_IS_EXECUTE_HANDLER;
1254          ccs_free_execve_entry(ee);                  /* Mark the current process as normal process. */
1255                    else
1256                            task->ccs_flags &= ~CCS_TASK_IS_EXECUTE_HANDLER;
1257            }
1258            /* Tell GC that I finished execve(). */
1259            task->ccs_flags &= ~CCS_TASK_IS_IN_EXECVE;
1260            ccs_read_unlock(ee->reader_idx);
1261            kfree(ee->handler_path);
1262            kfree(ee->tmp);
1263            kfree(ee->dump.data);
1264            kfree(ee);
1265  }  }

Legend:
Removed from v.2951  
changed lines
  Added in v.3162

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