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

Subversion リポジトリの参照

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

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

revision 4048 by kumaneko, Wed Sep 8 05:42:22 2010 UTC revision 4049 by kumaneko, Thu Oct 7 07:14:01 2010 UTC
# Line 3  Line 3 
3   *   *
4   * Copyright (C) 2005-2010  NTT DATA CORPORATION   * Copyright (C) 2005-2010  NTT DATA CORPORATION
5   *   *
6   * Version: 1.8.0-pre   2010/09/01   * Version: 1.8.0-pre   2010/10/05
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 12  Line 12 
12    
13  #include "internal.h"  #include "internal.h"
14    
 struct ccs_preference ccs_preference = {  
 #ifdef CONFIG_CCSECURITY_AUDIT  
         .audit_max_grant_log = CONFIG_CCSECURITY_MAX_GRANT_LOG,  
         .audit_max_reject_log = CONFIG_CCSECURITY_MAX_REJECT_LOG,  
 #endif  
         .audit_task_info = true,  
         .audit_path_info = true,  
         .enforcing_penalty = 0,  
         .enforcing_verbose = true,  
         .learning_max_entry = CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY,  
         .learning_verbose = false,  
         .learning_exec_realpath = true,  
         .learning_exec_argv0 = true,  
         .learning_symlink_target = true,  
         .permissive_verbose = true,  
 };  
   
15  /* Profile version. Currently only 20100903 is defined. */  /* Profile version. Currently only 20100903 is defined. */
16  static unsigned int ccs_profile_version;  static unsigned int ccs_profile_version;
17    
# Line 61  const char * const ccs_mac_keywords[CCS_ Line 44  const char * const ccs_mac_keywords[CCS_
44          [CCS_MAC_FILE_LINK]       = "link",          [CCS_MAC_FILE_LINK]       = "link",
45          [CCS_MAC_FILE_RENAME]     = "rename",          [CCS_MAC_FILE_RENAME]     = "rename",
46          [CCS_MAC_FILE_CHMOD]      = "chmod",          [CCS_MAC_FILE_CHMOD]      = "chmod",
47          [CCS_MAC_FILE_CHOWN]      = "chown",          [CCS_MAC_FILE_CHOWN]      = "chown",
48          [CCS_MAC_FILE_CHGRP]      = "chgrp",          [CCS_MAC_FILE_CHGRP]      = "chgrp",
49          [CCS_MAC_FILE_IOCTL]      = "ioctl",          [CCS_MAC_FILE_IOCTL]      = "ioctl",
50          [CCS_MAC_FILE_CHROOT]     = "chroot",          [CCS_MAC_FILE_CHROOT]     = "chroot",
# Line 193  const char * const ccs_condition_keyword Line 176  const char * const ccs_condition_keyword
176          [CCS_PATH2_PARENT_PERM]    = "path2.parent.perm",          [CCS_PATH2_PARENT_PERM]    = "path2.parent.perm",
177  };  };
178    
179    static const char * const ccs_pref_keywords[CCS_MAX_PREF] = {
180            [CCS_PREF_MAX_GRANT_LOG]      = "max_grant_log",
181            [CCS_PREF_MAX_REJECT_LOG]     = "max_reject_log",
182            [CCS_PREF_MAX_LEARNING_ENTRY] = "max_learning_entry",
183            [CCS_PREF_ENFORCING_PENALTY]  = "enforcing_penalty",
184    };
185    
186  /* Permit policy management by non-root user? */  /* Permit policy management by non-root user? */
187  static bool ccs_manage_by_non_root;  static bool ccs_manage_by_non_root;
188    
# Line 207  static const char *ccs_yesno(const unsig Line 197  static const char *ccs_yesno(const unsig
197  }  }
198    
199  static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)  static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
200         __attribute__ ((format(printf, 3, 4)));
201    
202    static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
203  {  {
204          va_list args;          va_list args;
205          const int pos = strlen(buffer);          const int pos = strlen(buffer);
# Line 339  static struct ccs_profile *ccs_assign_pr Line 332  static struct ccs_profile *ccs_assign_pr
332                          CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG;                          CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG;
333                  memset(ptr->config, CCS_CONFIG_USE_DEFAULT,                  memset(ptr->config, CCS_CONFIG_USE_DEFAULT,
334                         sizeof(ptr->config));                         sizeof(ptr->config));
335                    ptr->pref[CCS_PREF_MAX_GRANT_LOG] =
336                            CONFIG_CCSECURITY_MAX_GRANT_LOG;
337                    ptr->pref[CCS_PREF_MAX_REJECT_LOG] =
338                            CONFIG_CCSECURITY_MAX_REJECT_LOG;
339                    ptr->pref[CCS_PREF_MAX_LEARNING_ENTRY] =
340                            CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY;
341                  mb(); /* Avoid out-of-order execution. */                  mb(); /* Avoid out-of-order execution. */
342                  ccs_profile_ptr[profile] = ptr;                  ccs_profile_ptr[profile] = ptr;
343                  entry = NULL;                  entry = NULL;
344          }          }
345          mutex_unlock(&ccs_policy_lock);          mutex_unlock(&ccs_policy_lock);
346   out:  out:
347          kfree(entry);          kfree(entry);
348          return ptr;          return ptr;
349  }  }
# Line 357  static void ccs_check_profile(void) Line 356  static void ccs_check_profile(void)
356          struct ccs_domain_info *domain;          struct ccs_domain_info *domain;
357          const int idx = ccs_read_lock();          const int idx = ccs_read_lock();
358          ccs_policy_loaded = true;          ccs_policy_loaded = true;
359          list_for_each_entry_rcu(domain, &ccs_domain_list, list) {          list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
360                  const u8 profile = domain->profile;                  const u8 profile = domain->profile;
361                  if (ccs_profile_ptr[profile])                  if (ccs_profile_ptr[profile])
362                          continue;                          continue;
# Line 368  static void ccs_check_profile(void) Line 367  static void ccs_check_profile(void)
367          if (ccs_profile_version != 20100903)          if (ccs_profile_version != 20100903)
368                  panic("Profile version %u is not supported.\n",                  panic("Profile version %u is not supported.\n",
369                        ccs_profile_version);                        ccs_profile_version);
370          printk(KERN_INFO "CCSecurity: 1.8.0-pre   2010/09/01\n");          printk(KERN_INFO "CCSecurity: 1.8.0-pre   2010/10/05\n");
371          printk(KERN_INFO "Mandatory Access Control activated.\n");          printk(KERN_INFO "Mandatory Access Control activated.\n");
372  }  }
373    
# Line 401  static s8 ccs_find_yesno(const char *str Line 400  static s8 ccs_find_yesno(const char *str
400          return -1;          return -1;
401  }  }
402    
 static void ccs_set_bool(bool *b, const char *string, const char *find)  
 {  
         switch (ccs_find_yesno(string, find)) {  
         case 1:  
                 *b = true;  
                 break;  
         case 0:  
                 *b = false;  
                 break;  
         }  
 }  
   
403  static void ccs_set_uint(unsigned int *i, const char *string, const char *find)  static void ccs_set_uint(unsigned int *i, const char *string, const char *find)
404  {  {
405          const char *cp = strstr(string, find);          const char *cp = strstr(string, find);
# Line 420  static void ccs_set_uint(unsigned int *i Line 407  static void ccs_set_uint(unsigned int *i
407                  sscanf(cp + strlen(find), "=%u", i);                  sscanf(cp + strlen(find), "=%u", i);
408  }  }
409    
 static int ccs_set_pref(char *data)  
 {  
         if (ccs_str_starts(&data, "audit")) {  
 #ifdef CONFIG_CCSECURITY_AUDIT  
                 ccs_set_uint(&ccs_preference.audit_max_grant_log, data,  
                              "max_grant_log");  
                 ccs_set_uint(&ccs_preference.audit_max_reject_log, data,  
                              "max_reject_log");  
 #endif  
                 ccs_set_bool(&ccs_preference.audit_task_info, data,  
                              "task_info");  
                 ccs_set_bool(&ccs_preference.audit_path_info, data,  
                              "path_info");  
         } else if (ccs_str_starts(&data, "enforcing")) {  
                 ccs_set_bool(&ccs_preference.enforcing_verbose, data,  
                              "verbose");  
                 ccs_set_uint(&ccs_preference.enforcing_penalty, data,  
                              "penalty");  
         } else if (ccs_str_starts(&data, "permissive")) {  
                 ccs_set_bool(&ccs_preference.permissive_verbose, data,  
                              "verbose");  
         } else if (ccs_str_starts(&data, "learning")) {  
                 ccs_set_bool(&ccs_preference.learning_verbose, data,  
                              "verbose");  
                 ccs_set_uint(&ccs_preference.learning_max_entry, data,  
                              "max_entry");  
                 ccs_set_bool(&ccs_preference.learning_exec_realpath, data,  
                              ccs_condition_keyword[CCS_EXEC_REALPATH]);  
                 ccs_set_bool(&ccs_preference.learning_exec_argv0, data,  
                              "exec.argv0");  
                 ccs_set_bool(&ccs_preference.learning_symlink_target, data,  
                              ccs_condition_keyword[CCS_SYMLINK_TARGET]);  
         } else  
                 return -EINVAL;  
         return 0;  
 }  
   
410  static int ccs_set_mode(char *name, const char *value,  static int ccs_set_mode(char *name, const char *value,
411                          struct ccs_profile *profile)                          struct ccs_profile *profile)
412  {  {
# Line 472  static int ccs_set_mode(char *name, cons Line 422  static int ccs_set_mode(char *name, cons
422                          int len = 0;                          int len = 0;
423                          if (i < CCS_MAX_MAC_INDEX) {                          if (i < CCS_MAX_MAC_INDEX) {
424                                  const u8 c = ccs_index2category[i];                                  const u8 c = ccs_index2category[i];
425                                  const char *category = ccs_category_keywords[c];                                  const char *category =
426                                            ccs_category_keywords[c];
427                                  len = strlen(category);                                  len = strlen(category);
428                                  if (strncmp(name, category, len) ||                                  if (strncmp(name, category, len) ||
429                                      name[len++] != ':' || name[len++] != ':')                                      name[len++] != ':' || name[len++] != ':')
# Line 499  static int ccs_set_mode(char *name, cons Line 450  static int ccs_set_mode(char *name, cons
450                                   * 'config' from 'CCS_CONFIG_USE_DEAFULT'.                                   * 'config' from 'CCS_CONFIG_USE_DEAFULT'.
451                                   */                                   */
452                                  config = (config & ~7) | mode;                                  config = (config & ~7) | mode;
 #ifdef CONFIG_CCSECURITY_AUDIT  
453                  if (config != CCS_CONFIG_USE_DEFAULT) {                  if (config != CCS_CONFIG_USE_DEFAULT) {
454                          switch (ccs_find_yesno(value, "grant_log")) {                          switch (ccs_find_yesno(value, "grant_log")) {
455                          case 1:                          case 1:
# Line 518  static int ccs_set_mode(char *name, cons Line 468  static int ccs_set_mode(char *name, cons
468                                  break;                                  break;
469                          }                          }
470                  }                  }
 #endif  
471          }          }
472          if (i < CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX)          if (i < CCS_MAX_MAC_INDEX + CCS_MAX_MAC_CATEGORY_INDEX)
473                  profile->config[i] = config;                  profile->config[i] = config;
# Line 542  static int ccs_write_profile(struct ccs_ Line 491  static int ccs_write_profile(struct ccs_
491          struct ccs_profile *profile;          struct ccs_profile *profile;
492          if (sscanf(data, "PROFILE_VERSION=%u", &ccs_profile_version) == 1)          if (sscanf(data, "PROFILE_VERSION=%u", &ccs_profile_version) == 1)
493                  return 0;                  return 0;
         if (ccs_str_starts(&data, "PREFERENCE::"))  
                 return ccs_set_pref(data);  
494          i = simple_strtoul(data, &cp, 10);          i = simple_strtoul(data, &cp, 10);
495          if (*cp != '-')          if (*cp != '-')
496                  return -EINVAL;                  return -EINVAL;
# Line 561  static int ccs_write_profile(struct ccs_ Line 508  static int ccs_write_profile(struct ccs_
508                  ccs_put_name(old_comment);                  ccs_put_name(old_comment);
509                  return 0;                  return 0;
510          }          }
511            if (!strcmp(data, "PREFERENCE")) {
512                    for (i = 0; i < CCS_MAX_PREF; i++)
513                            ccs_set_uint(&profile->pref[i], cp,
514                                         ccs_pref_keywords[i]);
515                    return 0;
516            }
517          return ccs_set_mode(data, cp, profile);          return ccs_set_mode(data, cp, profile);
518  }  }
519    
 static void ccs_print_preference(struct ccs_io_buffer *head)  
 {  
         ccs_io_printf(head, "PREFERENCE::%s={ "  
 #ifdef CONFIG_CCSECURITY_AUDIT  
                       "max_grant_log=%u max_reject_log=%u "  
 #endif  
                       "task_info=%s path_info=%s }\n", "audit",  
 #ifdef CONFIG_CCSECURITY_AUDIT  
                       ccs_preference.audit_max_grant_log,  
                       ccs_preference.audit_max_reject_log,  
 #endif  
                       ccs_yesno(ccs_preference.audit_task_info),  
                       ccs_yesno(ccs_preference.audit_path_info));  
         ccs_io_printf(head, "PREFERENCE::%s={ verbose=%s max_entry=%u "  
                       "exec.realpath=%s exec.argv0=%s symlink.target=%s }\n",  
                       "learning", ccs_yesno(ccs_preference.learning_verbose),  
                       ccs_preference.learning_max_entry,  
                       ccs_yesno(ccs_preference.learning_exec_realpath),  
                       ccs_yesno(ccs_preference.learning_exec_argv0),  
                       ccs_yesno(ccs_preference.learning_symlink_target));  
         ccs_io_printf(head, "PREFERENCE::%s={ verbose=%s }\n", "permissive",  
                       ccs_yesno(ccs_preference.permissive_verbose));  
         ccs_io_printf(head, "PREFERENCE::%s={ verbose=%s penalty=%u }\n",  
                       "enforcing", ccs_yesno(ccs_preference.enforcing_verbose),  
                       ccs_preference.enforcing_penalty);  
 }  
   
520  static void ccs_print_config(struct ccs_io_buffer *head, const u8 config)  static void ccs_print_config(struct ccs_io_buffer *head, const u8 config)
521  {  {
522          ccs_io_printf(head, "={ mode=%s", ccs_mode[config & 3]);          ccs_io_printf(head, "={ mode=%s grant_log=%s reject_log=%s }\n",
523  #ifdef CONFIG_CCSECURITY_AUDIT                        ccs_mode[config & 3],
         ccs_io_printf(head, " grant_log=%s reject_log=%s",  
524                        ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG),                        ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG),
525                        ccs_yesno(config & CCS_CONFIG_WANT_REJECT_LOG));                        ccs_yesno(config & CCS_CONFIG_WANT_REJECT_LOG));
 #endif  
         ccs_set_string(head, " }\n");  
526  }  }
527    
528  /**  /**
# Line 611  static void ccs_read_profile(struct ccs_ Line 534  static void ccs_read_profile(struct ccs_
534  {  {
535          u8 index;          u8 index;
536          const struct ccs_profile *profile;          const struct ccs_profile *profile;
537   next:  next:
538          index = head->r.index;          index = head->r.index;
539          profile = ccs_profile_ptr[index];          profile = ccs_profile_ptr[index];
540          switch (head->r.step) {          switch (head->r.step) {
541          case 0:          case 0:
542                  ccs_io_printf(head, "PROFILE_VERSION=%s\n", "20100903");                  ccs_io_printf(head, "PROFILE_VERSION=%s\n", "20100903");
                 ccs_print_preference(head);  
543                  head->r.step++;                  head->r.step++;
544                  break;                  break;
545          case 1:          case 1:
# Line 631  static void ccs_read_profile(struct ccs_ Line 553  static void ccs_read_profile(struct ccs_
553                  break;                  break;
554          case 2:          case 2:
555                  {                  {
556                            u8 i;
557                          const struct ccs_path_info *comment = profile->comment;                          const struct ccs_path_info *comment = profile->comment;
558                          ccs_io_printf(head, "%u-COMMENT=", index);                          ccs_io_printf(head, "%u-COMMENT=", index);
559                          ccs_set_string(head, comment ? comment->name : "");                          ccs_set_string(head, comment ? comment->name : "");
560                          ccs_set_lf(head);                          ccs_set_lf(head);
561                            ccs_io_printf(head, "%u-PREFERENCE={ ", index);
562                            for (i = 0; i < CCS_MAX_PREF; i++)
563                                    ccs_io_printf(head, "%s=%u ",
564                                                  ccs_pref_keywords[i],
565                                                  profile->pref[i]);
566                            ccs_set_string(head, " }\n");
567                          head->r.step++;                          head->r.step++;
568                  }                  }
569                  break;                  break;
# Line 767  static bool ccs_manager(void) Line 696  static bool ccs_manager(void)
696  {  {
697          struct ccs_manager *ptr;          struct ccs_manager *ptr;
698          const char *exe;          const char *exe;
699          struct task_struct *task = current;          struct ccs_security *task = ccs_current_security();
700          const struct ccs_path_info *domainname          const struct ccs_path_info *domainname
701                  = ccs_current_domain()->domainname;                  = ccs_current_domain()->domainname;
702          bool found = false;          bool found = false;
# Line 778  static bool ccs_manager(void) Line 707  static bool ccs_manager(void)
707          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))
708                  return false;                  return false;
709          exe = ccs_get_exe();          exe = ccs_get_exe();
710          list_for_each_entry_rcu(ptr, &ccs_policy_list[CCS_ID_MANAGER],          list_for_each_entry_srcu(ptr, &ccs_policy_list[CCS_ID_MANAGER],
711                                  head.list) {                                   head.list, &ccs_ss) {
712                  if (ptr->head.is_deleted)                  if (ptr->head.is_deleted)
713                          continue;                          continue;
714                  if (ptr->is_domain) {                  if (ptr->is_domain) {
# Line 1269  static bool ccs_print_entry(struct ccs_i Line 1198  static bool ccs_print_entry(struct ccs_i
1198                  goto print_cond_part;                  goto print_cond_part;
1199          if (acl->is_deleted)          if (acl->is_deleted)
1200                  return true;                  return true;
1201   next:  next:
1202          bit = head->r.bit;          bit = head->r.bit;
1203          if (!ccs_flush(head))          if (!ccs_flush(head))
1204                  return false;                  return false;
# Line 1428  static bool ccs_print_entry(struct ccs_i Line 1357  static bool ccs_print_entry(struct ccs_i
1357                  head->r.cond_step = 0;                  head->r.cond_step = 0;
1358                  if (!ccs_flush(head))                  if (!ccs_flush(head))
1359                          return false;                          return false;
1360   print_cond_part:  print_cond_part:
1361                  if (!ccs_print_condition(head, acl->cond))                  if (!ccs_print_condition(head, acl->cond))
1362                          return false;                          return false;
1363                  head->r.print_cond_part = false;                  head->r.print_cond_part = false;
# Line 1444  static bool ccs_print_entry(struct ccs_i Line 1373  static bool ccs_print_entry(struct ccs_i
1373          case CCS_TYPE_UNIX_ACL:          case CCS_TYPE_UNIX_ACL:
1374                  goto next;                  goto next;
1375          }          }
1376   done:  done:
1377          head->r.bit = 0;          head->r.bit = 0;
1378          return true;          return true;
1379  }  }
# Line 1524  static void ccs_read_domain(struct ccs_i Line 1453  static void ccs_read_domain(struct ccs_i
1453                                  goto done;                                  goto done;
1454                  }                  }
1455          }          }
1456   done:  done:
1457          head->r.eof = true;          head->r.eof = true;
1458  }  }
1459    
# Line 1649  static void ccs_read_pid(struct ccs_io_b Line 1578  static void ccs_read_pid(struct ccs_io_b
1578  #endif  #endif
1579          if (p) {          if (p) {
1580                  domain = ccs_task_domain(p);                  domain = ccs_task_domain(p);
1581                  ccs_flags = p->ccs_flags;                  ccs_flags = ccs_task_flags(p);
1582          }          }
1583          ccs_tasklist_unlock();          ccs_tasklist_unlock();
1584          if (!domain)          if (!domain)
# Line 1694  static int ccs_write_exception(struct cc Line 1623  static int ccs_write_exception(struct cc
1623          static const struct {          static const struct {
1624                  const char *keyword;                  const char *keyword;
1625                  int (*write) (char *, const bool);                  int (*write) (char *, const bool);
1626          } ccs_callback[3] = {          } ccs_callback[2] = {
1627                  { "aggregator ",    ccs_write_aggregator },                  { "aggregator ",    ccs_write_aggregator },
                 { "file_pattern ",  ccs_write_pattern },  
1628                  { "deny_autobind ", ccs_write_reserved_port },                  { "deny_autobind ", ccs_write_reserved_port },
1629          };          };
1630          for (i = 0; i < 3; i++)          for (i = 0; i < 2; i++)
1631                  if (ccs_str_starts(&data, ccs_callback[i].keyword))                  if (ccs_str_starts(&data, ccs_callback[i].keyword))
1632                          return ccs_callback[i].write(data, is_delete);                          return ccs_callback[i].write(data, is_delete);
1633          for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)          for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)
# Line 1754  static bool ccs_read_group(struct ccs_io Line 1682  static bool ccs_read_group(struct ccs_io
1682                                                  head)->member_name->name);                                                  head)->member_name->name);
1683                          } else if (idx == CCS_NUMBER_GROUP) {                          } else if (idx == CCS_NUMBER_GROUP) {
1684                                  ccs_print_number_union(head, &container_of                                  ccs_print_number_union(head, &container_of
1685                                                         (ptr, struct ccs_number_group,                                                 (ptr, struct ccs_number_group,
1686                                                          head)->number);                                                  head)->number);
1687                          } else if (idx == CCS_ADDRESS_GROUP) {                          } else if (idx == CCS_ADDRESS_GROUP) {
1688                                  char buffer[128];                                  char buffer[128];
1689                                  struct ccs_address_group *member =                                  struct ccs_address_group *member =
# Line 1823  static bool ccs_read_policy(struct ccs_i Line 1751  static bool ccs_read_policy(struct ccs_i
1751                                                 ptr->aggregated_name->name);                                                 ptr->aggregated_name->name);
1752                          }                          }
1753                          break;                          break;
                 case CCS_ID_PATTERN:  
                         {  
                                 struct ccs_pattern *ptr =  
                                         container_of(acl, typeof(*ptr), head);  
                                 ccs_set_string(head, "file_pattern ");  
                                 ccs_set_string(head, ptr->pattern->name);  
                         }  
                         break;  
1754                  case CCS_ID_RESERVEDPORT:                  case CCS_ID_RESERVEDPORT:
1755                          {                          {
1756                                  struct ccs_reserved *ptr =                                  struct ccs_reserved *ptr =
# Line 1888  static void ccs_read_exception(struct cc Line 1808  static void ccs_read_exception(struct cc
1808    
1809  /* Wait queue for ccs_query_list. */  /* Wait queue for ccs_query_list. */
1810  static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);  static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);
1811    static DECLARE_WAIT_QUEUE_HEAD(ccs_answer_wait);
1812    
1813  /* Lock for manipulating ccs_query_list. */  /* Lock for manipulating ccs_query_list. */
1814  static DEFINE_SPINLOCK(ccs_query_list_lock);  static DEFINE_SPINLOCK(ccs_query_list_lock);
# Line 1900  struct ccs_query { Line 1821  struct ccs_query {
1821          unsigned int serial;          unsigned int serial;
1822          int timer;          int timer;
1823          int answer;          int answer;
1824            u8 retry;
1825  };  };
1826    
1827  /* The list for "struct ccs_query". */  /* The list for "struct ccs_query". */
# Line 1908  static LIST_HEAD(ccs_query_list); Line 1830  static LIST_HEAD(ccs_query_list);
1830  /* Number of "struct file" referring /proc/ccs/query interface. */  /* Number of "struct file" referring /proc/ccs/query interface. */
1831  static atomic_t ccs_query_observers = ATOMIC_INIT(0);  static atomic_t ccs_query_observers = ATOMIC_INIT(0);
1832    
1833  static void ccs_truncate(char *str)  static int ccs_truncate(char *str)
1834  {  {
1835          while (* (unsigned char *) str > (unsigned char) ' ')          char *start = str;
1836            while (*(unsigned char *) str > (unsigned char) ' ')
1837                  str++;                  str++;
1838          *str = '\0';          *str = '\0';
1839            return strlen(start) + 1;
1840    }
1841    
1842    static void ccs_add_entry(char *header)
1843    {
1844            char *buffer;
1845            char *realpath = NULL;
1846            char *argv0 = NULL;
1847            char *symlink = NULL;
1848            char *handler;
1849            char *cp = strchr(header, '\n');
1850            int len;
1851            if (!cp)
1852                    return;
1853            cp = strchr(cp + 1, '\n');
1854            if (!cp)
1855                    return;
1856            *cp++ = '\0';
1857            len = strlen(cp) + 1;
1858            /* strstr() will return NULL if ordering is wrong. */
1859            if (*cp == 'f') {
1860                    argv0 = strstr(header, " argv[]={ \"");
1861                    if (argv0) {
1862                            argv0 += 10;
1863                            len += ccs_truncate(argv0) + 14;
1864                    }
1865                    realpath = strstr(header, " exec={ realpath=\"");
1866                    if (realpath) {
1867                            realpath += 8;
1868                            len += ccs_truncate(realpath) + 6;
1869                    }
1870                    symlink = strstr(header, " symlink.target=\"");
1871                    if (symlink)
1872                            len += ccs_truncate(symlink + 1) + 1;
1873            }
1874            handler = strstr(header, "type=execute_handler");
1875            if (handler)
1876                    len += ccs_truncate(handler) + 6;
1877            buffer = kmalloc(len, CCS_GFP_FLAGS);
1878            if (!buffer)
1879                    return;
1880            snprintf(buffer, len - 1, "%s", cp);
1881            if (handler)
1882                    ccs_addprintf(buffer, len, " task.%s", handler);
1883            if (realpath)
1884                    ccs_addprintf(buffer, len, " exec.%s", realpath);
1885            if (argv0)
1886                    ccs_addprintf(buffer, len, " exec.argv[0]=%s", argv0);
1887            if (symlink)
1888                    ccs_addprintf(buffer, len, "%s", symlink);
1889            ccs_normalize_line(buffer);
1890            if (!ccs_write_domain2(buffer, ccs_current_domain(), false))
1891                    ccs_update_stat(CCS_STAT_POLICY_UPDATES);
1892            kfree(buffer);
1893  }  }
1894    
1895  /**  /**
# Line 1929  static void ccs_truncate(char *str) Line 1906  static void ccs_truncate(char *str)
1906  int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...)  int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...)
1907  {  {
1908          va_list args;          va_list args;
1909          int error = -EPERM;          int error;
         int pos;  
1910          int len;          int len;
1911          static unsigned int ccs_serial;          static unsigned int ccs_serial;
1912          struct ccs_query *entry = NULL;          struct ccs_query entry = { };
1913          bool quota_exceeded = false;          bool quota_exceeded = false;
1914          char *header;          /* Write /proc/ccs/grant_log or /proc/ccs/reject_log . */
         struct ccs_domain_info * const domain = ccs_current_domain();  
1915          va_start(args, fmt);          va_start(args, fmt);
1916          len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 80;          ccs_write_log2(r, fmt, args);
1917          va_end(args);          va_end(args);
1918          if (r->mode == CCS_CONFIG_LEARNING) {          /* Nothing more to do if granted. */
1919                  char *buffer;          if (r->granted)
                 char *realpath = NULL;  
                 char *argv0 = NULL;  
                 char *symlink = NULL;  
                 char *handler = NULL;  
                 if (!ccs_domain_quota_ok(r))  
                         return 0;  
                 header = ccs_init_log(&len, r);  
                 if (!header)  
                         return 0;  
                 /* strstr() will return NULL if ordering is wrong. */  
                 if (r->param_type == CCS_TYPE_PATH_ACL &&  
                     r->param.path.operation == CCS_TYPE_EXECUTE) {  
                         if (ccs_preference.learning_exec_argv0) {  
                                 argv0 = strstr(header, " argv[]={ \"");  
                                 if (argv0) {  
                                         argv0 += 10;  
                                         ccs_truncate(argv0);  
                                 }  
                         }  
                         if (ccs_preference.learning_exec_realpath) {  
                                 realpath = strstr(header,  
                                                   " exec={ realpath=\"");  
                                 if (realpath) {  
                                         realpath += 8;  
                                         ccs_truncate(realpath);  
                                 }  
                         }  
                 } else if (r->param_type == CCS_TYPE_PATH_ACL &&  
                            r->param.path.operation == CCS_TYPE_SYMLINK &&  
                            ccs_preference.learning_symlink_target) {  
                         symlink = strstr(header, " symlink.target=\"");  
                         if (symlink)  
                                 ccs_truncate(symlink + 1);  
                 }  
                 handler = strstr(header, "type=execute_handler");  
                 if (handler)  
                         ccs_truncate(handler);  
                 buffer = kmalloc(len, CCS_GFP_FLAGS);  
                 if (buffer) {  
                         va_start(args, fmt);  
                         vsnprintf(buffer, len - 1, fmt, args);  
                         va_end(args);  
                         if (handler)  
                                 ccs_addprintf(buffer, len, " task.%s",  
                                               handler);  
                         if (realpath)  
                                 ccs_addprintf(buffer, len, " exec.%s",  
                                               realpath);  
                         if (argv0)  
                                 ccs_addprintf(buffer, len, " exec.argv[0]=%s",  
                                               argv0);  
                         if (symlink)  
                                 ccs_addprintf(buffer, len, "%s", symlink);  
                         ccs_normalize_line(buffer);  
                         ccs_write_domain2(buffer, domain, false);  
                         kfree(buffer);  
                 }  
                 kfree(header);  
1920                  return 0;                  return 0;
1921          }          if (r->mode)
1922          if (r->mode != CCS_CONFIG_ENFORCING)                  ccs_update_stat(r->mode);
1923                  return 0;          switch (r->mode) {
         if (!atomic_read(&ccs_query_observers)) {  
1924                  int i;                  int i;
1925                  if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)                  struct ccs_profile *p;
1926                          return -EPERM;          case CCS_CONFIG_ENFORCING:
1927                  for (i = 0; i < ccs_preference.enforcing_penalty; i++) {                  error = -EPERM;
1928                    if (atomic_read(&ccs_query_observers))
1929                            break;
1930                    if (ccs_current_flags() & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)
1931                            goto out;
1932                    p = ccs_profile(r->profile);
1933                    /* Check enforcing_penalty parameter. */
1934                    for (i = 0; i < p->pref[CCS_PREF_ENFORCING_PENALTY]; i++) {
1935                          set_current_state(TASK_INTERRUPTIBLE);                          set_current_state(TASK_INTERRUPTIBLE);
1936                          schedule_timeout(HZ / 10);                          schedule_timeout(HZ / 10);
1937                  }                  }
                 return -EPERM;  
         }  
         header = ccs_init_log(&len, r);  
         if (!header)  
1938                  goto out;                  goto out;
1939          entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);          case CCS_CONFIG_LEARNING:
1940          if (!entry)                  error = 0;
1941                    /* Check mac_learning_entry parameter. */
1942                    if (ccs_domain_quota_ok(r))
1943                            break;
1944                    /* fall through */
1945            default:
1946                    return 0;
1947            }
1948            /* Get message. */
1949            va_start(args, fmt);
1950            entry.query = ccs_init_log(&len, r, fmt, args);
1951            va_end(args);
1952            if (!entry.query)
1953                  goto out;                  goto out;
1954          len = ccs_round2(len);          entry.query_len = strlen(entry.query) + 1;
1955          entry->query = kzalloc(len, CCS_GFP_FLAGS);          if (!error) {
1956          if (!entry->query)                  ccs_add_entry(entry.query);
1957                  goto out;                  goto out;
1958            }
1959          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
1960          if (ccs_quota_for_query && ccs_query_memory_size + len +          if (ccs_memory_quota[CCS_MEMORY_QUERY] &&
1961              sizeof(*entry) >= ccs_quota_for_query) {              ccs_memory_used[CCS_MEMORY_QUERY] + len
1962                >= ccs_memory_quota[CCS_MEMORY_QUERY]) {
1963                  quota_exceeded = true;                  quota_exceeded = true;
1964          } else {          } else {
1965                  ccs_query_memory_size += len + sizeof(*entry);                  entry.serial = ccs_serial++;
1966                  entry->serial = ccs_serial++;                  entry.retry = r->retry;
1967                    ccs_memory_used[CCS_MEMORY_QUERY] += len;
1968                    list_add_tail(&entry.list, &ccs_query_list);
1969          }          }
1970          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
1971          if (quota_exceeded)          if (quota_exceeded)
1972                  goto out;                  goto out;
         pos = snprintf(entry->query, len - 1, "Q%u-%hu\n%s",  
                        entry->serial, r->retry, header);  
         kfree(header);  
         header = NULL;  
         va_start(args, fmt);  
         vsnprintf(entry->query + pos, len - 1 - pos, fmt, args);  
         entry->query_len = strlen(entry->query) + 1;  
         va_end(args);  
         spin_lock(&ccs_query_list_lock);  
         list_add_tail(&entry->list, &ccs_query_list);  
         spin_unlock(&ccs_query_list_lock);  
1973          /* Give 10 seconds for supervisor's opinion. */          /* Give 10 seconds for supervisor's opinion. */
1974          for (entry->timer = 0;          while (entry.timer < 10) {
1975               atomic_read(&ccs_query_observers) && entry->timer < 100;                  wake_up_all(&ccs_query_wait);
1976               entry->timer++) {                  if (wait_event_interruptible_timeout
1977                  wake_up(&ccs_query_wait);                      (ccs_answer_wait, entry.answer ||
1978                  set_current_state(TASK_INTERRUPTIBLE);                       !atomic_read(&ccs_query_observers), HZ))
                 schedule_timeout(HZ / 10);  
                 if (entry->answer)  
1979                          break;                          break;
1980                    else
1981                            entry.timer++;
1982          }          }
1983          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
1984          list_del(&entry->list);          list_del(&entry.list);
1985          ccs_query_memory_size -= len + sizeof(*entry);          ccs_memory_used[CCS_MEMORY_QUERY] -= len;
1986          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
1987          switch (entry->answer) {          switch (entry.answer) {
1988          case 3: /* Asked to retry by administrator. */          case 3: /* Asked to retry by administrator. */
1989                  error = CCS_RETRY_REQUEST;                  error = CCS_RETRY_REQUEST;
1990                  r->retry++;                  r->retry++;
# Line 2069  int ccs_supervisor(struct ccs_request_in Line 1993  int ccs_supervisor(struct ccs_request_in
1993                  /* Granted by administrator. */                  /* Granted by administrator. */
1994                  error = 0;                  error = 0;
1995                  break;                  break;
         case 0:  
                 /* Timed out. */  
                 break;  
1996          default:          default:
1997                  /* Rejected by administrator. */                  /* Timed out or rejected by administrator. */
1998                  break;                  break;
1999          }          }
2000   out:  out:
2001          if (entry)          kfree(entry.query);
                 kfree(entry->query);  
         kfree(entry);  
         kfree(header);  
2002          return error;          return error;
2003  }  }
2004    
# Line 2151  static void ccs_read_query(struct ccs_io Line 2069  static void ccs_read_query(struct ccs_io
2069                  head->r.query_index = 0;                  head->r.query_index = 0;
2070                  return;                  return;
2071          }          }
2072          buf = kzalloc(len, CCS_GFP_FLAGS);          buf = kzalloc(len + 32, CCS_GFP_FLAGS);
2073          if (!buf)          if (!buf)
2074                  return;                  return;
2075          pos = 0;          pos = 0;
# Line 2167  static void ccs_read_query(struct ccs_io Line 2085  static void ccs_read_query(struct ccs_io
2085                   * can change, but I don't care.                   * can change, but I don't care.
2086                   */                   */
2087                  if (len == ptr->query_len)                  if (len == ptr->query_len)
2088                          memmove(buf, ptr->query, len);                          snprintf(buf, len + 32, "Q%u-%hu\n%s", ptr->serial,
2089                                     ptr->retry, ptr->query);
2090                  break;                  break;
2091          }          }
2092          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
# Line 2211  static int ccs_write_answer(struct ccs_i Line 2130  static int ccs_write_answer(struct ccs_i
2130                  break;                  break;
2131          }          }
2132          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
2133            wake_up_all(&ccs_answer_wait);
2134          return 0;          return 0;
2135  }  }
2136    
# Line 2228  static void ccs_read_version(struct ccs_ Line 2148  static void ccs_read_version(struct ccs_
2148  }  }
2149    
2150  /**  /**
  * ccs_read_self_domain - Get the current process's domainname.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  */  
 static void ccs_read_self_domain(struct ccs_io_buffer *head)  
 {  
         if (head->r.eof)  
                 return;  
         /*  
          * ccs_current_domain()->domainname != NULL because every process  
          * belongs to a domain and the domain's name cannot be NULL.  
          */  
         ccs_io_printf(head, "%s", ccs_current_domain()->domainname->name);  
         head->r.eof = true;  
 }  
   
 /**  
2151   * ccs_open_control - open() for /proc/ccs/ interface.   * ccs_open_control - open() for /proc/ccs/ interface.
2152   *   *
2153   * @type: Type of interface.   * @type: Type of interface.
# Line 2268  int ccs_open_control(const u8 type, stru Line 2171  int ccs_open_control(const u8 type, stru
2171                  head->write = ccs_write_exception;                  head->write = ccs_write_exception;
2172                  head->read = ccs_read_exception;                  head->read = ccs_read_exception;
2173                  break;                  break;
 #ifdef CONFIG_CCSECURITY_AUDIT  
2174          case CCS_GRANTLOG: /* /proc/ccs/grant_log */          case CCS_GRANTLOG: /* /proc/ccs/grant_log */
2175          case CCS_REJECTLOG: /* /proc/ccs/reject_log */          case CCS_REJECTLOG: /* /proc/ccs/reject_log */
2176                  head->poll = ccs_poll_log;                  head->poll = ccs_poll_log;
2177                  head->read = ccs_read_log;                  head->read = ccs_read_log;
2178                  break;                  break;
 #endif  
         case CCS_SELFDOMAIN: /* /proc/ccs/self_domain */  
                 head->read = ccs_read_self_domain;  
                 break;  
2179          case CCS_DOMAIN_STATUS: /* /proc/ccs/.domain_status */          case CCS_DOMAIN_STATUS: /* /proc/ccs/.domain_status */
2180                  head->write = ccs_write_domain_profile;                  head->write = ccs_write_domain_profile;
2181                  head->read = ccs_read_domain_profile;                  head->read = ccs_read_domain_profile;
2182                  break;                  break;
2183          case CCS_EXECUTE_HANDLER: /* /proc/ccs/.execute_handler */          case CCS_EXECUTE_HANDLER: /* /proc/ccs/.execute_handler */
2184                  /* Allow execute_handler to read process's status. */                  /* Allow execute_handler to read process's status. */
2185                  if (!(current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)) {                  if (!(ccs_current_flags() & CCS_TASK_IS_EXECUTE_HANDLER)) {
2186                          kfree(head);                          kfree(head);
2187                          return -EPERM;                          return -EPERM;
2188                  }                  }
# Line 2348  int ccs_open_control(const u8 type, stru Line 2246  int ccs_open_control(const u8 type, stru
2246                          return -ENOMEM;                          return -ENOMEM;
2247                  }                  }
2248          }          }
         if (type != CCS_QUERY &&  
             type != CCS_GRANTLOG && type != CCS_REJECTLOG)  
                 head->reader_idx = ccs_lock();  
         file->private_data = head;  
         /*  
          * Call the handler now if the file is /proc/ccs/self_domain  
          * so that the user can use "cat < /proc/ccs/self_domain" to  
          * know the current process's domainname.  
          */  
         if (type == CCS_SELFDOMAIN)  
                 ccs_read_control(file, NULL, 0);  
2249          /*          /*
2250           * If the file is /proc/ccs/query , increment the observer counter.           * If the file is /proc/ccs/query , increment the observer counter.
2251           * The obserber counter is used by ccs_supervisor() to see if           * The obserber counter is used by ccs_supervisor() to see if
2252           * there is some process monitoring /proc/ccs/query.           * there is some process monitoring /proc/ccs/query.
2253           */           */
2254          else if (type == CCS_QUERY)          if (type == CCS_QUERY)
2255                  atomic_inc(&ccs_query_observers);                  atomic_inc(&ccs_query_observers);
2256            else if (type != CCS_GRANTLOG && type != CCS_REJECTLOG)
2257                    head->reader_idx = ccs_lock();
2258            file->private_data = head;
2259          return 0;          return 0;
2260  }  }
2261    
# Line 2481  int ccs_write_control(struct file *file, Line 2371  int ccs_write_control(struct file *file,
2371                  cp0[head->w.avail - 1] = '\0';                  cp0[head->w.avail - 1] = '\0';
2372                  head->w.avail = 0;                  head->w.avail = 0;
2373                  ccs_normalize_line(cp0);                  ccs_normalize_line(cp0);
2374                  head->write(head);                  if (head->write(head))
2375                            continue;
2376                    switch (head->type) {
2377                    case CCS_DOMAINPOLICY:
2378                    case CCS_EXCEPTIONPOLICY:
2379                    case CCS_DOMAIN_STATUS:
2380                    case CCS_MEMINFO:
2381                    case CCS_PROFILE:
2382                    case CCS_MANAGER:
2383                            ccs_update_stat(CCS_STAT_POLICY_UPDATES);
2384                    }
2385          }          }
2386          ccs_read_unlock(idx);          ccs_read_unlock(idx);
2387          mutex_unlock(&head->io_sem);          mutex_unlock(&head->io_sem);
# Line 2503  int ccs_close_control(struct file *file) Line 2403  int ccs_close_control(struct file *file)
2403          /*          /*
2404           * If the file is /proc/ccs/query , decrement the observer counter.           * If the file is /proc/ccs/query , decrement the observer counter.
2405           */           */
2406          if (type == CCS_QUERY)          if (type == CCS_QUERY) {
2407                  atomic_dec(&ccs_query_observers);                  if (atomic_dec_and_test(&ccs_query_observers))
2408          if (type != CCS_QUERY &&                          wake_up_all(&ccs_answer_wait);
2409              type != CCS_GRANTLOG && type != CCS_REJECTLOG)          } else if (type != CCS_GRANTLOG && type != CCS_REJECTLOG)
2410                  ccs_unlock(head->reader_idx);                  ccs_unlock(head->reader_idx);
2411          /* Release memory used for policy I/O. */          /* Release memory used for policy I/O. */
2412          kfree(head->read_buf);          kfree(head->read_buf);

Legend:
Removed from v.4048  
changed lines
  Added in v.4049

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