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

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

trunk/1.7.x/ccs-patch/security/ccsecurity/policy_io.c revision 3079 by kumaneko, Fri Oct 2 06:23:24 2009 UTC branches/ccs-patch/security/ccsecurity/policy_io.c revision 3695 by kumaneko, Mon May 24 04:35:02 2010 UTC
# Line 1  Line 1 
1  /*  /*
2   * security/ccsecurity/policy_io.c   * security/ccsecurity/policy_io.c
3   *   *
4   * Copyright (C) 2005-2009  NTT DATA CORPORATION   * Copyright (C) 2005-2010  NTT DATA CORPORATION
5   *   *
6   * Version: 1.7.0   2009/10/01   * Version: 1.7.2   2010/04/01
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 33  static struct ccs_profile ccs_default_pr Line 33  static struct ccs_profile ccs_default_pr
33          .preference.permissive_verbose = true          .preference.permissive_verbose = true
34  };  };
35    
36    /* Profile version. Currently only 20090903 is defined. */
37    static unsigned int ccs_profile_version;
38    
39  /* Profile table. Memory is allocated as needed. */  /* Profile table. Memory is allocated as needed. */
40  static struct ccs_profile *ccs_profile_ptr[CCS_MAX_PROFILES];  static struct ccs_profile *ccs_profile_ptr[CCS_MAX_PROFILES];
41    
 /* Lock for protecting "struct ccs_profile"->comment  */  
 static DEFINE_SPINLOCK(ccs_profile_comment_lock);  
   
42  /* String table for functionality that takes 4 modes. */  /* String table for functionality that takes 4 modes. */
43  static const char *ccs_mode_4[4] = {  static const char *ccs_mode_4[4] = {
44          "disabled", "learning", "permissive", "enforcing"          "disabled", "learning", "permissive", "enforcing"
# Line 94  static const char *ccs_mac_keywords[CCS_ Line 94  static const char *ccs_mac_keywords[CCS_
94          = "file::umount",          = "file::umount",
95          [CCS_MAC_FILE_PIVOT_ROOT]          [CCS_MAC_FILE_PIVOT_ROOT]
96          = "file::pivot_root",          = "file::pivot_root",
97            [CCS_MAC_FILE_TRANSIT]
98            = "file::transit",
99          [CCS_MAC_ENVIRON]          [CCS_MAC_ENVIRON]
100          = "misc::env",          = "misc::env",
101          [CCS_MAC_NETWORK_UDP_BIND]          [CCS_MAC_NETWORK_UDP_BIND]
# Line 244  bool ccs_io_printf(struct ccs_io_buffer Line 246  bool ccs_io_printf(struct ccs_io_buffer
246  }  }
247    
248  /**  /**
249   * ccs_find_or_assign_new_profile - Create a new profile.   * ccs_assign_profile - Create a new profile.
250   *   *
251   * @profile: Profile number to create.   * @profile: Profile number to create.
252   *   *
253   * Returns pointer to "struct ccs_profile" on success, NULL otherwise.   * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
254   */   */
255  static struct ccs_profile *ccs_find_or_assign_new_profile(const unsigned int  static struct ccs_profile *ccs_assign_profile(const unsigned int profile)
                                                           profile)  
256  {  {
257          struct ccs_profile *ptr;          struct ccs_profile *ptr;
258          struct ccs_profile *entry;          struct ccs_profile *entry;
# Line 260  static struct ccs_profile *ccs_find_or_a Line 261  static struct ccs_profile *ccs_find_or_a
261          ptr = ccs_profile_ptr[profile];          ptr = ccs_profile_ptr[profile];
262          if (ptr)          if (ptr)
263                  return ptr;                  return ptr;
264          entry = kzalloc(sizeof(*entry), GFP_KERNEL);          entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);
265          mutex_lock(&ccs_policy_lock);          if (mutex_lock_interruptible(&ccs_policy_lock))
266                    goto out;
267          ptr = ccs_profile_ptr[profile];          ptr = ccs_profile_ptr[profile];
268          if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {          if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {
269                  ptr = entry;                  ptr = entry;
# Line 278  static struct ccs_profile *ccs_find_or_a Line 280  static struct ccs_profile *ccs_find_or_a
280                  entry = NULL;                  entry = NULL;
281          }          }
282          mutex_unlock(&ccs_policy_lock);          mutex_unlock(&ccs_policy_lock);
283     out:
284          kfree(entry);          kfree(entry);
285          return ptr;          return ptr;
286  }  }
# Line 285  static struct ccs_profile *ccs_find_or_a Line 288  static struct ccs_profile *ccs_find_or_a
288  /**  /**
289   * ccs_check_profile - Check all profiles currently assigned to domains are defined.   * ccs_check_profile - Check all profiles currently assigned to domains are defined.
290   */   */
291  void ccs_check_profile(void)  static void ccs_check_profile(void)
292  {  {
293          struct ccs_domain_info *domain;          struct ccs_domain_info *domain;
294            const int idx = ccs_read_lock();
295          ccs_policy_loaded = true;          ccs_policy_loaded = true;
296          list_for_each_entry_rcu(domain, &ccs_domain_list, list) {          list_for_each_entry_rcu(domain, &ccs_domain_list, list) {
297                  const u8 profile = domain->profile;                  const u8 profile = domain->profile;
# Line 296  void ccs_check_profile(void) Line 300  void ccs_check_profile(void)
300                  panic("Profile %u (used by '%s') not defined.\n",                  panic("Profile %u (used by '%s') not defined.\n",
301                        profile, domain->domainname->name);                        profile, domain->domainname->name);
302          }          }
303            ccs_read_unlock(idx);
304            if (ccs_profile_version != 20090903)
305                    panic("Profile version %u is not supported.\n",
306                          ccs_profile_version);
307            printk(KERN_INFO "CCSecurity: 1.7.2   2010/04/01\n");
308            printk(KERN_INFO "Mandatory Access Control activated.\n");
309  }  }
310    
311  /**  /**
# Line 331  static int ccs_write_profile(struct ccs_ Line 341  static int ccs_write_profile(struct ccs_
341          bool use_default = false;          bool use_default = false;
342          char *cp;          char *cp;
343          struct ccs_profile *profile;          struct ccs_profile *profile;
344            if (sscanf(data, "PROFILE_VERSION=%u", &ccs_profile_version) == 1)
345                    return 0;
346          i = simple_strtoul(data, &cp, 10);          i = simple_strtoul(data, &cp, 10);
347          if (data == cp) {          if (data == cp) {
348                  profile = &ccs_default_profile;                  profile = &ccs_default_profile;
# Line 338  static int ccs_write_profile(struct ccs_ Line 350  static int ccs_write_profile(struct ccs_
350                  if (*cp != '-')                  if (*cp != '-')
351                          return -EINVAL;                          return -EINVAL;
352                  data = cp + 1;                  data = cp + 1;
353                  profile = ccs_find_or_assign_new_profile(i);                  profile = ccs_assign_profile(i);
354                  if (!profile)                  if (!profile)
355                          return -EINVAL;                          return -EINVAL;
356          }          }
# Line 354  static int ccs_write_profile(struct ccs_ Line 366  static int ccs_write_profile(struct ccs_
366                  value = 0;                  value = 0;
367          else          else
368                  value = -1;                  value = -1;
369          if (!strcmp(data, "PREFERENCE::audit")) {          if (!strcmp(data, CCS_KEYWORD_PREFERENCE_AUDIT)) {
370  #ifdef CONFIG_CCSECURITY_AUDIT  #ifdef CONFIG_CCSECURITY_AUDIT
371                  char *cp2;                  char *cp2;
372  #endif  #endif
# Line 383  static int ccs_write_profile(struct ccs_ Line 395  static int ccs_write_profile(struct ccs_
395                          profile->preference.audit_path_info = false;                          profile->preference.audit_path_info = false;
396                  return 0;                  return 0;
397          }          }
398          if (!strcmp(data, "PREFERENCE::enforcing")) {          if (!strcmp(data, CCS_KEYWORD_PREFERENCE_ENFORCING)) {
399                  char *cp2;                  char *cp2;
400                  if (use_default) {                  if (use_default) {
401                          profile->enforcing = &ccs_default_profile.preference;                          profile->enforcing = &ccs_default_profile.preference;
# Line 398  static int ccs_write_profile(struct ccs_ Line 410  static int ccs_write_profile(struct ccs_
410                                 &profile->preference.enforcing_penalty);                                 &profile->preference.enforcing_penalty);
411                  return 0;                  return 0;
412          }          }
413          if (!strcmp(data, "PREFERENCE::permissive")) {          if (!strcmp(data, CCS_KEYWORD_PREFERENCE_PERMISSIVE)) {
414                  if (use_default) {                  if (use_default) {
415                          profile->permissive = &ccs_default_profile.preference;                          profile->permissive = &ccs_default_profile.preference;
416                          return 0;                          return 0;
# Line 408  static int ccs_write_profile(struct ccs_ Line 420  static int ccs_write_profile(struct ccs_
420                          profile->preference.permissive_verbose = value;                          profile->preference.permissive_verbose = value;
421                  return 0;                  return 0;
422          }          }
423          if (!strcmp(data, "PREFERENCE::learning")) {          if (!strcmp(data, CCS_KEYWORD_PREFERENCE_LEARNING)) {
424                  char *cp2;                  char *cp2;
425                  if (use_default) {                  if (use_default) {
426                          profile->learning = &ccs_default_profile.preference;                          profile->learning = &ccs_default_profile.preference;
# Line 438  static int ccs_write_profile(struct ccs_ Line 450  static int ccs_write_profile(struct ccs_
450          if (profile == &ccs_default_profile)          if (profile == &ccs_default_profile)
451                  return -EINVAL;                  return -EINVAL;
452          if (!strcmp(data, "COMMENT")) {          if (!strcmp(data, "COMMENT")) {
453                  const struct ccs_path_info *new_comment = ccs_get_name(cp);                  const struct ccs_path_info *old_comment = profile->comment;
454                  const struct ccs_path_info *old_comment;                  profile->comment = ccs_get_name(cp);
                 /* Protect reader from ccs_put_name(). */  
                 spin_lock(&ccs_profile_comment_lock);  
                 old_comment = profile->comment;  
                 profile->comment = new_comment;  
                 spin_unlock(&ccs_profile_comment_lock);  
455                  ccs_put_name(old_comment);                  ccs_put_name(old_comment);
456                  return 0;                  return 0;
457          }          }
# Line 498  static int ccs_write_profile(struct ccs_ Line 505  static int ccs_write_profile(struct ccs_
505          return 0;          return 0;
506  }  }
507    
508    static bool ccs_print_preference(struct ccs_io_buffer *head, const int idx)
509    {
510            struct ccs_preference *pref = &ccs_default_profile.preference;
511            const struct ccs_profile *profile = idx >= 0 ?
512                    ccs_profile_ptr[idx] : NULL;
513            char buffer[16] = "";
514            if (profile) {
515                    buffer[sizeof(buffer) - 1] = '\0';
516                    snprintf(buffer, sizeof(buffer) - 1, "%u-", idx);
517            }
518            if (profile) {
519                    pref = profile->audit;
520                    if (pref == &ccs_default_profile.preference)
521                            pref = NULL;
522            }
523            if (pref && !ccs_io_printf(head, "%s%s={ "
524    #ifdef CONFIG_CCSECURITY_AUDIT
525                                       "max_grant_log=%u max_reject_log=%u "
526    #endif
527                                       "task_info=%s path_info=%s }\n", buffer,
528                                       CCS_KEYWORD_PREFERENCE_AUDIT,
529    #ifdef CONFIG_CCSECURITY_AUDIT
530                                       pref->audit_max_grant_log,
531                                       pref->audit_max_reject_log,
532    #endif
533                                       ccs_yesno(pref->audit_task_info),
534                                       ccs_yesno(pref->audit_path_info)))
535                    return false;
536            if (profile) {
537                    pref = profile->learning;
538                    if (pref == &ccs_default_profile.preference)
539                            pref = NULL;
540            }
541            if (pref && !ccs_io_printf(head, "%s%s={ "
542                                       "verbose=%s max_entry=%u exec.realpath=%s "
543                                       "exec.argv0=%s symlink.target=%s }\n",
544                                       buffer, CCS_KEYWORD_PREFERENCE_LEARNING,
545                                       ccs_yesno(pref->learning_verbose),
546                                       pref->learning_max_entry,
547                                       ccs_yesno(pref->learning_exec_realpath),
548                                       ccs_yesno(pref->learning_exec_argv0),
549                                       ccs_yesno(pref->learning_symlink_target)))
550                    return false;
551            if (profile) {
552                    pref = profile->permissive;
553                    if (pref == &ccs_default_profile.preference)
554                            pref = NULL;
555            }
556            if (pref && !ccs_io_printf(head, "%s%s={ verbose=%s }\n", buffer,
557                                       CCS_KEYWORD_PREFERENCE_PERMISSIVE,
558                                       ccs_yesno(pref->permissive_verbose)))
559                    return false;
560            if (profile) {
561                    pref = profile->enforcing;
562                    if (pref == &ccs_default_profile.preference)
563                            pref = NULL;
564            }
565            return !pref || ccs_io_printf(head, "%s%s={ verbose=%s penalty=%u }\n",
566                                          buffer, CCS_KEYWORD_PREFERENCE_ENFORCING,
567                                          ccs_yesno(pref->enforcing_verbose),
568                                          pref->enforcing_penalty);
569    }
570    
571  /**  /**
572   * ccs_read_profile - Read profile table.   * ccs_read_profile - Read profile table.
573   *   *
# Line 511  static void ccs_read_profile(struct ccs_ Line 581  static void ccs_read_profile(struct ccs_
581          if (head->read_bit)          if (head->read_bit)
582                  goto body;                  goto body;
583          ccs_io_printf(head, "PROFILE_VERSION=%s\n", "20090903");          ccs_io_printf(head, "PROFILE_VERSION=%s\n", "20090903");
584          ccs_io_printf(head, "PREFERENCE::audit={ "          ccs_print_preference(head, -1);
 #ifdef CONFIG_CCSECURITY_AUDIT  
                       "max_grant_log=%u max_reject_log=%u "  
 #endif  
                       "task_info=%s path_info=%s }\n",  
 #ifdef CONFIG_CCSECURITY_AUDIT  
                       ccs_default_profile.preference.audit_max_grant_log,  
                       ccs_default_profile.preference.audit_max_reject_log,  
 #endif  
                       ccs_yesno(ccs_default_profile.preference.  
                                 audit_task_info),  
                       ccs_yesno(ccs_default_profile.preference.  
                                 audit_path_info));  
         ccs_io_printf(head, "PREFERENCE::learning={ verbose=%s max_entry=%u "  
                       "exec.realpath=%s exec.argv0=%s symlink.target=%s }\n",  
                       ccs_yesno(ccs_default_profile.preference.  
                                 learning_verbose),  
                       ccs_default_profile.preference.learning_max_entry,  
                       ccs_yesno(ccs_default_profile.preference.  
                                 learning_exec_realpath),  
                       ccs_yesno(ccs_default_profile.preference.  
                                 learning_exec_argv0),  
                       ccs_yesno(ccs_default_profile.preference.  
                                 learning_symlink_target));  
         ccs_io_printf(head, "PREFERENCE::permissive={ verbose=%s }\n",  
                       ccs_yesno(ccs_default_profile.preference.  
                                 permissive_verbose));  
         ccs_io_printf(head, "PREFERENCE::enforcing={ verbose=%s penalty=%u "  
                       "}\n",  
                       ccs_yesno(ccs_default_profile.preference.  
                                 enforcing_verbose),  
                       ccs_default_profile.preference.enforcing_penalty);  
585          head->read_bit = 1;          head->read_bit = 1;
586   body:   body:
587          for (index = head->read_step; index < CCS_MAX_PROFILES; index++) {          for (index = head->read_step; index < CCS_MAX_PROFILES; index++) {
# Line 551  static void ccs_read_profile(struct ccs_ Line 590  static void ccs_read_profile(struct ccs_
590                  int i;                  int i;
591                  int pos;                  int pos;
592                  const struct ccs_profile *profile = ccs_profile_ptr[index];                  const struct ccs_profile *profile = ccs_profile_ptr[index];
593                    const struct ccs_path_info *comment;
594                  head->read_step = index;                  head->read_step = index;
595                  if (!profile)                  if (!profile)
596                          continue;                          continue;
597                  pos = head->read_avail;                  pos = head->read_avail;
598                  spin_lock(&ccs_profile_comment_lock);                  comment = profile->comment;
599                  done = ccs_io_printf(head, "%u-COMMENT=%s\n", index,                  done = ccs_io_printf(head, "%u-COMMENT=%s\n", index,
600                                       profile->comment ? profile->comment->name                                       comment ? comment->name : "");
                                      : "");  
                 spin_unlock(&ccs_profile_comment_lock);  
601                  if (!done)                  if (!done)
602                          goto out;                          goto out;
603                  config = profile->default_config;                  config = profile->default_config;
604  #ifdef CONFIG_CCSECURITY_AUDIT  #ifdef CONFIG_CCSECURITY_AUDIT
605                  if (!ccs_io_printf(head, "%u-CONFIG={ mode=%s grant_log=%s "                  if (!ccs_io_printf(head, "%u-%s%s={ mode=%s "
606                                     "reject_log=%s }\n", index,                                     "grant_log=%s reject_log=%s }\n", index,
607                                     ccs_mode_4[config & 3],                                     "CONFIG", "", ccs_mode_4[config & 3],
608                                     ccs_yesno(config &                                     ccs_yesno(config &
609                                               CCS_CONFIG_WANT_GRANT_LOG),                                               CCS_CONFIG_WANT_GRANT_LOG),
610                                     ccs_yesno(config &                                     ccs_yesno(config &
611                                               CCS_CONFIG_WANT_REJECT_LOG)))                                               CCS_CONFIG_WANT_REJECT_LOG)))
612                          goto out;                          goto out;
613  #else  #else
614                  if (!ccs_io_printf(head, "%u-CONFIG={ mode=%s }\n", index,                  if (!ccs_io_printf(head, "%u-%s%s={ mode=%s }\n", index,
615                                     ccs_mode_4[config & 3]))                                     "CONFIG", "", ccs_mode_4[config & 3]))
616                          goto out;                          goto out;
617  #endif  #endif
618                  for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX                  for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
# Line 589  static void ccs_read_profile(struct ccs_ Line 627  static void ccs_read_profile(struct ccs_
627  #ifdef CONFIG_CCSECURITY_AUDIT  #ifdef CONFIG_CCSECURITY_AUDIT
628                          g = ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG);                          g = ccs_yesno(config & CCS_CONFIG_WANT_GRANT_LOG);
629                          r = ccs_yesno(config & CCS_CONFIG_WANT_REJECT_LOG);                          r = ccs_yesno(config & CCS_CONFIG_WANT_REJECT_LOG);
630                          if (!ccs_io_printf(head, "%u-CONFIG::%s={ mode=%s "                          if (!ccs_io_printf(head, "%u-%s%s={ mode=%s "
631                                             "grant_log=%s reject_log=%s }\n",                                             "grant_log=%s reject_log=%s }\n",
632                                             index, ccs_mac_keywords[i],                                             index, "CONFIG::",
633                                               ccs_mac_keywords[i],
634                                             ccs_mode_4[config & 3], g, r))                                             ccs_mode_4[config & 3], g, r))
635                                  goto out;                                  goto out;
636  #else  #else
637                          if (!ccs_io_printf(head, "%u-CONFIG::%s={ mode=%s }\n",                          if (!ccs_io_printf(head, "%u-%s%s={ mode=%s }\n",
638                                             index, ccs_mac_keywords[i],                                             index, "CONFIG::",
639                                               ccs_mac_keywords[i],
640                                             ccs_mode_4[config & 3]))                                             ccs_mode_4[config & 3]))
641                                  goto out;                                  goto out;
642  #endif  #endif
643                  }                  }
644                  if (profile->audit != &ccs_default_profile.preference &&                  if (!ccs_print_preference(head, index))
                     !ccs_io_printf(head, "%u-PREFERENCE::audit={ "  
 #ifdef CONFIG_CCSECURITY_AUDIT  
                                    "max_grant_log=%u max_reject_log=%u "  
 #endif  
                                    "task_info=%s path_info=%s }\n", index,  
 #ifdef CONFIG_CCSECURITY_AUDIT  
                                    profile->preference.audit_max_grant_log,  
                                    profile->preference.audit_max_reject_log,  
 #endif  
                                    ccs_yesno(profile->preference.  
                                              audit_task_info),  
                                    ccs_yesno(profile->preference.  
                                              audit_path_info)))  
                         goto out;  
                 if (profile->learning != &ccs_default_profile.preference &&  
                     !ccs_io_printf(head, "%u-PREFERENCE::learning={ "  
                                    "verbose=%s max_entry=%u exec.realpath=%s "  
                                    "exec.argv0=%s symlink.target=%s }\n",  
                                    index,  
                                    ccs_yesno(profile->preference.  
                                              learning_verbose),  
                                    profile->preference.learning_max_entry,  
                                    ccs_yesno(profile->preference.  
                                              learning_exec_realpath),  
                                    ccs_yesno(profile->preference.  
                                              learning_exec_argv0),  
                                    ccs_yesno(profile->preference.  
                                              learning_symlink_target)))  
                         goto out;  
                 if (profile->permissive != &ccs_default_profile.preference &&  
                     !ccs_io_printf(head, "%u-PREFERENCE::permissive={ "  
                                    "verbose=%s }\n", index,  
                                    ccs_yesno(profile->preference.  
                                              permissive_verbose)))  
                         goto out;  
                 if (profile->enforcing != &ccs_default_profile.preference &&  
                     !ccs_io_printf(head, "%u-PREFERENCE::enforcing={ "  
                                    "verbose=%s penalty=%u }\n", index,  
                                    ccs_yesno(profile->preference.  
                                              enforcing_verbose),  
                                    profile->preference.enforcing_penalty))  
645                          goto out;                          goto out;
646                  continue;                  continue;
647   out:   out:
# Line 653  static void ccs_read_profile(struct ccs_ Line 652  static void ccs_read_profile(struct ccs_
652                  head->read_eof = true;                  head->read_eof = true;
653  }  }
654    
655  /* The list for "struct ccs_policy_manager_entry". */  static bool ccs_same_manager_entry(const struct ccs_acl_head *a,
656  LIST_HEAD(ccs_policy_manager_list);                                     const struct ccs_acl_head *b)
657    {
658            return container_of(a, struct ccs_manager, head)->manager
659                    == container_of(b, struct ccs_manager, head)->manager;
660    }
661    
662  /**  /**
663   * ccs_update_manager_entry - Add a manager entry.   * ccs_update_manager_entry - Add a manager entry.
# Line 666  LIST_HEAD(ccs_policy_manager_list); Line 669  LIST_HEAD(ccs_policy_manager_list);
669   */   */
670  static int ccs_update_manager_entry(const char *manager, const bool is_delete)  static int ccs_update_manager_entry(const char *manager, const bool is_delete)
671  {  {
672          struct ccs_policy_manager_entry *entry = NULL;          struct ccs_manager e = { };
         struct ccs_policy_manager_entry *ptr;  
         struct ccs_policy_manager_entry e = { };  
673          int error = is_delete ? -ENOENT : -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
674          if (ccs_is_domain_def(manager)) {          if (ccs_domain_def(manager)) {
675                  if (!ccs_is_correct_domain(manager))                  if (!ccs_correct_domain(manager))
676                          return -EINVAL;                          return -EINVAL;
677                  e.is_domain = true;                  e.is_domain = true;
678          } else {          } else {
679                  if (!ccs_is_correct_path(manager, 1, -1, -1))                  if (!ccs_correct_path(manager, 1, -1, -1))
680                          return -EINVAL;                          return -EINVAL;
681          }          }
682          e.manager = ccs_get_name(manager);          e.manager = ccs_get_name(manager);
683          if (!e.manager)          if (!e.manager)
684                  return -ENOMEM;                  return error;
685          if (!is_delete)          error = ccs_update_policy(&e.head, sizeof(e), is_delete,
686                  entry = kmalloc(sizeof(e), GFP_KERNEL);                                    CCS_ID_MANAGER, ccs_same_manager_entry);
         mutex_lock(&ccs_policy_lock);  
         list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {  
                 if (ptr->manager != e.manager)  
                         continue;  
                 ptr->is_deleted = is_delete;  
                 error = 0;  
                 break;  
         }  
         if (!is_delete && error && ccs_commit_ok(entry, &e, sizeof(e))) {  
                 list_add_tail_rcu(&entry->list, &ccs_policy_manager_list);  
                 entry = NULL;  
                 error = 0;  
         }  
         mutex_unlock(&ccs_policy_lock);  
687          ccs_put_name(e.manager);          ccs_put_name(e.manager);
         kfree(entry);  
688          return error;          return error;
689  }  }
690    
691  /**  /**
692   * ccs_write_manager_policy - Write manager policy.   * ccs_write_manager - Write manager policy.
693   *   *
694   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
695   *   *
696   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
697   */   */
698  static int ccs_write_manager_policy(struct ccs_io_buffer *head)  static int ccs_write_manager(struct ccs_io_buffer *head)
699  {  {
700          char *data = head->write_buf;          char *data = head->write_buf;
701          bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE);          bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE);
# Line 721  static int ccs_write_manager_policy(stru Line 707  static int ccs_write_manager_policy(stru
707  }  }
708    
709  /**  /**
710   * ccs_read_manager_policy - Read manager policy.   * ccs_read_manager - Read manager policy.
711   *   *
712   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
713   *   *
714   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
715   */   */
716  static void ccs_read_manager_policy(struct ccs_io_buffer *head)  static void ccs_read_manager(struct ccs_io_buffer *head)
717  {  {
718          struct list_head *pos;          struct list_head *pos;
719          if (head->read_eof)          if (head->read_eof)
720                  return;                  return;
721          list_for_each_cookie(pos, head->read_var2, &ccs_policy_manager_list) {          list_for_each_cookie(pos, head->read_var2,
722                  struct ccs_policy_manager_entry *ptr;                               &ccs_policy_list[CCS_ID_MANAGER]) {
723                  ptr = list_entry(pos, struct ccs_policy_manager_entry, list);                  struct ccs_manager *ptr
724                  if (ptr->is_deleted)                          = list_entry(pos, typeof(*ptr), head.list);
725                    if (ptr->head.is_deleted)
726                          continue;                          continue;
727                  if (!ccs_io_printf(head, "%s\n", ptr->manager->name))                  if (!ccs_io_printf(head, "%s\n", ptr->manager->name))
728                          return;                          return;
# Line 744  static void ccs_read_manager_policy(stru Line 731  static void ccs_read_manager_policy(stru
731  }  }
732    
733  /**  /**
734   * ccs_is_policy_manager - Check whether the current process is a policy manager.   * ccs_manager - Check whether the current process is a policy manager.
735   *   *
736   * Returns true if the current process is permitted to modify policy   * Returns true if the current process is permitted to modify policy
737   * via /proc/ccs/ interface.   * via /proc/ccs/ interface.
738   *   *
739   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
740   */   */
741  static bool ccs_is_policy_manager(void)  static bool ccs_manager(void)
742  {  {
743          struct ccs_policy_manager_entry *ptr;          struct ccs_manager *ptr;
744          const char *exe;          const char *exe;
745          struct task_struct *task = current;          struct task_struct *task = current;
746          const struct ccs_path_info *domainname          const struct ccs_path_info *domainname
# Line 761  static bool ccs_is_policy_manager(void) Line 748  static bool ccs_is_policy_manager(void)
748          bool found = false;          bool found = false;
749          if (!ccs_policy_loaded)          if (!ccs_policy_loaded)
750                  return true;                  return true;
751          if (task->ccs_flags & CCS_TASK_IS_POLICY_MANAGER)          if (task->ccs_flags & CCS_TASK_IS_MANAGER)
752                  return true;                  return true;
753          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))
754                  return false;                  return false;
755          list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {          list_for_each_entry_rcu(ptr, &ccs_policy_list[CCS_ID_MANAGER],
756                  if (!ptr->is_deleted && ptr->is_domain                                  head.list) {
757                    if (!ptr->head.is_deleted && ptr->is_domain
758                      && !ccs_pathcmp(domainname, ptr->manager)) {                      && !ccs_pathcmp(domainname, ptr->manager)) {
759                          /* Set manager flag. */                          /* Set manager flag. */
760                          task->ccs_flags |= CCS_TASK_IS_POLICY_MANAGER;                          task->ccs_flags |= CCS_TASK_IS_MANAGER;
761                          return true;                          return true;
762                  }                  }
763          }          }
764          exe = ccs_get_exe();          exe = ccs_get_exe();
765          if (!exe)          if (!exe)
766                  return false;                  return false;
767          list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {          list_for_each_entry_rcu(ptr, &ccs_policy_list[CCS_ID_MANAGER],
768                  if (!ptr->is_deleted && !ptr->is_domain                                  head.list) {
769                    if (!ptr->head.is_deleted && !ptr->is_domain
770                      && !strcmp(exe, ptr->manager->name)) {                      && !strcmp(exe, ptr->manager->name)) {
771                          found = true;                          found = true;
772                          /* Set manager flag. */                          /* Set manager flag. */
773                          task->ccs_flags |= CCS_TASK_IS_POLICY_MANAGER;                          task->ccs_flags |= CCS_TASK_IS_MANAGER;
774                          break;                          break;
775                  }                  }
776          }          }
# Line 826  static char *ccs_find_condition_part(cha Line 815  static char *ccs_find_condition_part(cha
815  }  }
816    
817  /**  /**
818   * ccs_is_select_one - Parse select command.   * ccs_select_one - Parse select command.
819   *   *
820   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
821   * @data: String to parse.   * @data: String to parse.
# Line 835  static char *ccs_find_condition_part(cha Line 824  static char *ccs_find_condition_part(cha
824   *   *
825   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
826   */   */
827  static bool ccs_is_select_one(struct ccs_io_buffer *head, const char *data)  static bool ccs_select_one(struct ccs_io_buffer *head, const char *data)
828  {  {
829          unsigned int pid;          unsigned int pid;
830          struct ccs_domain_info *domain = NULL;          struct ccs_domain_info *domain = NULL;
# Line 847  static bool ccs_is_select_one(struct ccs Line 836  static bool ccs_is_select_one(struct ccs
836          if (sscanf(data, "pid=%u", &pid) == 1 ||          if (sscanf(data, "pid=%u", &pid) == 1 ||
837              (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {              (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
838                  struct task_struct *p;                  struct task_struct *p;
839                  read_lock(&tasklist_lock);                  ccs_tasklist_lock();
840  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
841                  if (global_pid)                  if (global_pid)
842                          p = find_task_by_pid_ns(pid, &init_pid_ns);                          p = ccsecurity_exports.find_task_by_pid_ns(pid,
843                                                                   &init_pid_ns);
844                  else                  else
845                          p = find_task_by_vpid(pid);                          p = ccsecurity_exports.find_task_by_vpid(pid);
846  #else  #else
847                  p = find_task_by_pid(pid);                  p = find_task_by_pid(pid);
848  #endif  #endif
849                  if (p)                  if (p)
850                          domain = ccs_task_domain(p);                          domain = ccs_task_domain(p);
851                  read_unlock(&tasklist_lock);                  ccs_tasklist_unlock();
852          } else if (!strncmp(data, "domain=", 7)) {          } else if (!strncmp(data, "domain=", 7)) {
853                  if (ccs_is_domain_def(data + 7))                  if (ccs_domain_def(data + 7))
854                          domain = ccs_find_domain(data + 7);                          domain = ccs_find_domain(data + 7);
855          } else          } else
856                  return false;                  return false;
# Line 889  static bool ccs_is_select_one(struct ccs Line 879  static bool ccs_is_select_one(struct ccs
879          return true;          return true;
880  }  }
881    
882  static int ccs_write_domain_policy2(char *data, struct ccs_domain_info *domain,  static int ccs_write_domain2(char *data, struct ccs_domain_info *domain,
883                                      struct ccs_condition *cond,                               struct ccs_condition *cond, const bool is_delete)
884                                      const bool is_delete)  {
885  {          u8 i;
886          if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_CAPABILITY))          static const struct {
887                  return ccs_write_capability_policy(data, domain, cond,                  const char *keyword;
888                                                     is_delete);                  int (*write) (char *, struct ccs_domain_info *,
889          if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_NETWORK))                                struct ccs_condition *, const bool);
890                  return ccs_write_network_policy(data, domain, cond, is_delete);          } ccs_callback[5] = {
891          if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_SIGNAL))                  { CCS_KEYWORD_ALLOW_NETWORK, ccs_write_network },
892                  return ccs_write_signal_policy(data, domain, cond, is_delete);                  { CCS_KEYWORD_ALLOW_ENV, ccs_write_env },
893          if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_ENV))                  { CCS_KEYWORD_ALLOW_CAPABILITY, ccs_write_capability },
894                  return ccs_write_env_policy(data, domain, cond, is_delete);                  { CCS_KEYWORD_ALLOW_SIGNAL, ccs_write_signal },
895          if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_MOUNT))                  { CCS_KEYWORD_ALLOW_MOUNT, ccs_write_mount }
896                  return ccs_write_mount_policy(data, domain, cond, is_delete);          };
897          return ccs_write_file_policy(data, domain, cond, is_delete);          int (*write) (char *, struct ccs_domain_info *, struct ccs_condition *,
898                          const bool) = ccs_write_file;
899            for (i = 0; i < 5; i++) {
900                    if (!ccs_str_starts(&data, ccs_callback[i].keyword))
901                            continue;
902                    write = ccs_callback[i].write;
903                    break;
904            }
905            return write(data, domain, cond, is_delete);
906  }  }
907    
908  /**  /**
909   * ccs_write_domain_policy - Write domain policy.   * ccs_write_domain - Write domain policy.
910   *   *
911   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
912   *   *
913   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
914   */   */
915  static int ccs_write_domain_policy(struct ccs_io_buffer *head)  static int ccs_write_domain(struct ccs_io_buffer *head)
916  {  {
917          char *data = head->write_buf;          char *data = head->write_buf;
918          struct ccs_domain_info *domain = head->write_var1;          struct ccs_domain_info *domain = head->write_var1;
# Line 928  static int ccs_write_domain_policy(struc Line 926  static int ccs_write_domain_policy(struc
926                  is_delete = true;                  is_delete = true;
927          else if (ccs_str_starts(&data, CCS_KEYWORD_SELECT))          else if (ccs_str_starts(&data, CCS_KEYWORD_SELECT))
928                  is_select = true;                  is_select = true;
929          if (is_select && ccs_is_select_one(head, data))          if (is_select && ccs_select_one(head, data))
930                  return 0;                  return 0;
931          /* Don't allow updating policies by non manager programs. */          /* Don't allow updating policies by non manager programs. */
932          if (!ccs_is_policy_manager())          if (!ccs_manager())
933                  return -EPERM;                  return -EPERM;
934          if (ccs_is_domain_def(data)) {          if (ccs_domain_def(data)) {
935                  domain = NULL;                  domain = NULL;
936                  if (is_delete)                  if (is_delete)
937                          ccs_delete_domain(data);                          ccs_delete_domain(data);
938                  else if (is_select)                  else if (is_select)
939                          domain = ccs_find_domain(data);                          domain = ccs_find_domain(data);
940                  else                  else
941                          domain = ccs_find_or_assign_new_domain(data, 0);                          domain = ccs_assign_domain(data, 0);
942                  head->write_var1 = domain;                  head->write_var1 = domain;
943                  return 0;                  return 0;
944          }          }
# Line 961  static int ccs_write_domain_policy(struc Line 959  static int ccs_write_domain_policy(struc
959                  domain->ignore_global_allow_env = !is_delete;                  domain->ignore_global_allow_env = !is_delete;
960                  return 0;                  return 0;
961          }          }
962            if (!strcmp(data, CCS_KEYWORD_QUOTA_EXCEEDED)) {
963                    domain->quota_warned = !is_delete;
964                    return 0;
965            }
966            if (!strcmp(data, CCS_KEYWORD_TRANSITION_FAILED)) {
967                    domain->domain_transition_failed = !is_delete;
968                    return 0;
969            }
970          cp = ccs_find_condition_part(data);          cp = ccs_find_condition_part(data);
971          if (cp) {          if (cp) {
972                  cond = ccs_get_condition(cp);                  cond = ccs_get_condition(cp);
973                  if (!cond)                  if (!cond)
974                          return -EINVAL;                          return -EINVAL;
975          }          }
976          error = ccs_write_domain_policy2(data, domain, cond, is_delete);          error = ccs_write_domain2(data, domain, cond, is_delete);
977          if (cond)          if (cond)
978                  ccs_put_condition(cond);                  ccs_put_condition(cond);
979          return error;          return error;
# Line 1010  static bool ccs_print_name_union_quoted( Line 1016  static bool ccs_print_name_union_quoted(
1016          return ccs_io_printf(head, "\"%s\"", ptr->filename->name);          return ccs_io_printf(head, "\"%s\"", ptr->filename->name);
1017  }  }
1018    
1019    static void ccs_print_number(char *buffer, int buffer_len,
1020                                 const struct ccs_number_union *ptr)
1021    {
1022            int i;
1023            unsigned long min = ptr->values[0];
1024            const unsigned long max = ptr->values[1];
1025            u8 min_type = ptr->value_type[0];
1026            const u8 max_type = ptr->value_type[1];
1027            memset(buffer, 0, buffer_len);
1028            buffer_len -= 2;
1029            for (i = 0; i < 2; i++) {
1030                    int len;
1031                    switch (min_type) {
1032                    case CCS_VALUE_TYPE_HEXADECIMAL:
1033                            snprintf(buffer, buffer_len, "0x%lX", min);
1034                            break;
1035                    case CCS_VALUE_TYPE_OCTAL:
1036                            snprintf(buffer, buffer_len, "0%lo", min);
1037                            break;
1038                    default:
1039                            snprintf(buffer, buffer_len, "%lu", min);
1040                            break;
1041                    }
1042                    if (min == max && min_type == max_type)
1043                            break;
1044                    len = strlen(buffer);
1045                    buffer[len++] = '-';
1046                    buffer += len;
1047                    buffer_len -= len;
1048                    min_type = max_type;
1049                    min = max;
1050            }
1051    }
1052    
1053  /**  /**
1054   * ccs_print_number_union_common - Print a ccs_number_union.   * ccs_print_number_union_common - Print a ccs_number_union.
1055   *   *
# Line 1023  static bool ccs_print_number_union_commo Line 1063  static bool ccs_print_number_union_commo
1063                                            const struct ccs_number_union *ptr,                                            const struct ccs_number_union *ptr,
1064                                            const bool need_space)                                            const bool need_space)
1065  {  {
1066          unsigned long min;          char buffer[128];
         unsigned long max;  
         u8 min_type;  
         u8 max_type;  
1067          if (need_space && !ccs_io_printf(head, " "))          if (need_space && !ccs_io_printf(head, " "))
1068                  return false;                  return false;
1069          if (ptr->is_group)          if (ptr->is_group)
1070                  return ccs_io_printf(head, "@%s",                  return ccs_io_printf(head, "@%s",
1071                                       ptr->group->group_name->name);                                       ptr->group->group_name->name);
1072          min_type = ptr->min_type;          ccs_print_number(buffer, sizeof(buffer), ptr);
1073          max_type = ptr->max_type;          return ccs_io_printf(head, "%s", buffer);
         min = ptr->values[0];  
         max = ptr->values[1];  
         switch (min_type) {  
         case CCS_VALUE_TYPE_HEXADECIMAL:  
                 if (!ccs_io_printf(head, "0x%lX", min))  
                         return false;  
                 break;  
         case CCS_VALUE_TYPE_OCTAL:  
                 if (!ccs_io_printf(head, "0%lo", min))  
                         return false;  
                 break;  
         default:  
                 if (!ccs_io_printf(head, "%lu", min))  
                         return false;  
                 break;  
         }  
         if (min == max && min_type == max_type)  
                 return true;  
         switch (max_type) {  
         case CCS_VALUE_TYPE_HEXADECIMAL:  
                 return ccs_io_printf(head, "-0x%lX", max);  
         case CCS_VALUE_TYPE_OCTAL:  
                 return ccs_io_printf(head, "-0%lo", max);  
         default:  
                 return ccs_io_printf(head, "-%lu", max);  
         }  
1074  }  }
1075    
1076  /**  /**
# Line 1070  static bool ccs_print_number_union_commo Line 1081  static bool ccs_print_number_union_commo
1081   *   *
1082   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1083   */   */
1084  bool ccs_print_number_union(struct ccs_io_buffer *head,  static bool ccs_print_number_union(struct ccs_io_buffer *head,
1085                              const struct ccs_number_union *ptr)                                     const struct ccs_number_union *ptr)
1086  {  {
1087          return ccs_print_number_union_common(head, ptr, true);          return ccs_print_number_union_common(head, ptr, true);
1088  }  }
# Line 1104  static bool ccs_print_condition(struct c Line 1115  static bool ccs_print_condition(struct c
1115          const struct ccs_condition_element *condp;          const struct ccs_condition_element *condp;
1116          const struct ccs_number_union *numbers_p;          const struct ccs_number_union *numbers_p;
1117          const struct ccs_name_union *names_p;          const struct ccs_name_union *names_p;
1118          const struct ccs_argv_entry *argv;          const struct ccs_argv *argv;
1119          const struct ccs_envp_entry *envp;          const struct ccs_envp *envp;
1120          u16 condc;          u16 condc;
1121          u16 i;          u16 i;
1122          u16 j;          u16 j;
# Line 1117  static bool ccs_print_condition(struct c Line 1128  static bool ccs_print_condition(struct c
1128          numbers_p = (const struct ccs_number_union *) (condp + condc);          numbers_p = (const struct ccs_number_union *) (condp + condc);
1129          names_p = (const struct ccs_name_union *)          names_p = (const struct ccs_name_union *)
1130                  (numbers_p + cond->numbers_count);                  (numbers_p + cond->numbers_count);
1131          argv = (const struct ccs_argv_entry *) (names_p + cond->names_count);          argv = (const struct ccs_argv *) (names_p + cond->names_count);
1132          envp = (const struct ccs_envp_entry *) (argv + cond->argc);          envp = (const struct ccs_envp *) (argv + cond->argc);
1133          memset(buffer, 0, sizeof(buffer));          memset(buffer, 0, sizeof(buffer));
1134          if (condc && !ccs_io_printf(head, "%s", " if"))          if (condc && !ccs_io_printf(head, "%s", " if"))
1135                  goto out;                  goto out;
# Line 1202  static bool ccs_print_condition(struct c Line 1213  static bool ccs_print_condition(struct c
1213  }  }
1214    
1215  /**  /**
1216   * ccs_print_path_acl - Print a single path ACL entry.   * ccs_print_path_acl - Print a path ACL entry.
1217   *   *
1218   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1219   * @ptr:  Pointer to "struct ccs_path_acl".   * @ptr:  Pointer to "struct ccs_path_acl".
# Line 1220  static bool ccs_print_path_acl(struct cc Line 1231  static bool ccs_print_path_acl(struct cc
1231          for (bit = head->read_bit; bit < CCS_MAX_PATH_OPERATION; bit++) {          for (bit = head->read_bit; bit < CCS_MAX_PATH_OPERATION; bit++) {
1232                  if (!(perm & (1 << bit)))                  if (!(perm & (1 << bit)))
1233                          continue;                          continue;
1234                  if (head->read_execute_only && bit != CCS_TYPE_EXECUTE)                  if (head->read_execute_only && bit != CCS_TYPE_EXECUTE
1235                        && bit != CCS_TYPE_TRANSIT)
1236                          continue;                          continue;
1237                  /* Print "read/write" instead of "read" and "write". */                  /* Print "read/write" instead of "read" and "write". */
1238                  if ((bit == CCS_TYPE_READ || bit == CCS_TYPE_WRITE)                  if ((bit == CCS_TYPE_READ || bit == CCS_TYPE_WRITE)
# Line 1391  static bool ccs_print_capability_acl(str Line 1403  static bool ccs_print_capability_acl(str
1403  }  }
1404    
1405  /**  /**
  * ccs_print_ipv4_entry - Print IPv4 address of a network ACL entry.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  * @ptr:  Pointer to "struct ccs_ip_network_acl".  
  *  
  * Returns true on success, false otherwise.  
  */  
 static bool ccs_print_ipv4_entry(struct ccs_io_buffer *head,  
                                  struct ccs_ip_network_acl *ptr)  
 {  
         const u32 min_address = ptr->address.ipv4.min;  
         const u32 max_address = ptr->address.ipv4.max;  
         if (!ccs_io_printf(head, "%u.%u.%u.%u", HIPQUAD(min_address)))  
                 return false;  
         if (min_address != max_address  
             && !ccs_io_printf(head, "-%u.%u.%u.%u", HIPQUAD(max_address)))  
                 return false;  
         return true;  
 }  
   
 /**  
  * ccs_print_ipv6_entry - Print IPv6 address of a network ACL entry.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  * @ptr:  Pointer to "struct ccs_ip_network_acl".  
  *  
  * Returns true on success, false otherwise.  
  */  
 static bool ccs_print_ipv6_entry(struct ccs_io_buffer *head,  
                                  struct ccs_ip_network_acl *ptr)  
 {  
         char buf[64];  
         const struct in6_addr *min_address = ptr->address.ipv6.min;  
         const struct in6_addr *max_address = ptr->address.ipv6.max;  
         ccs_print_ipv6(buf, sizeof(buf), min_address);  
         if (!ccs_io_printf(head, "%s", buf))  
                 return false;  
         if (min_address != max_address) {  
                 ccs_print_ipv6(buf, sizeof(buf), max_address);  
                 if (!ccs_io_printf(head, "-%s", buf))  
                         return false;  
         }  
         return true;  
 }  
   
 /**  
1406   * ccs_print_network_acl - Print a network ACL entry.   * ccs_print_network_acl - Print a network ACL entry.
1407   *   *
1408   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
# Line 1451  static bool ccs_print_network_acl(struct Line 1417  static bool ccs_print_network_acl(struct
1417  {  {
1418          int pos;          int pos;
1419          u8 bit;          u8 bit;
1420          const u16 perm = ptr->perm;          const u8 perm = ptr->perm;
1421            char buf[128];
1422          for (bit = head->read_bit; bit < CCS_MAX_NETWORK_OPERATION; bit++) {          for (bit = head->read_bit; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
1423                    const char *w[2] = { "", "" };
1424                  if (!(perm & (1 << bit)))                  if (!(perm & (1 << bit)))
1425                          continue;                          continue;
1426                  pos = head->read_avail;                  pos = head->read_avail;
                 if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s ",  
                                    ccs_net2keyword(bit)))  
                         goto out;  
1427                  switch (ptr->address_type) {                  switch (ptr->address_type) {
1428                  case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP:                  case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP:
1429                          if (!ccs_io_printf(head, "@%s", ptr->address.group->                          w[0] = "@";
1430                                             group_name->name))                          w[1] = ptr->address.group->group_name->name;
                                 goto out;  
1431                          break;                          break;
1432                  case CCS_IP_ADDRESS_TYPE_IPv4:                  case CCS_IP_ADDRESS_TYPE_IPv4:
1433                          if (!ccs_print_ipv4_entry(head, ptr))                          ccs_print_ipv4(buf, sizeof(buf), ptr->address.ipv4.min,
1434                                  goto out;                                         ptr->address.ipv4.max);
1435                            w[0] = buf;
1436                          break;                          break;
1437                  case CCS_IP_ADDRESS_TYPE_IPv6:                  case CCS_IP_ADDRESS_TYPE_IPv6:
1438                          if (!ccs_print_ipv6_entry(head, ptr))                          ccs_print_ipv6(buf, sizeof(buf), ptr->address.ipv6.min,
1439                                  goto out;                                         ptr->address.ipv6.max);
1440                            w[0] = buf;
1441                          break;                          break;
1442                  }                  }
1443                  if (!ccs_print_number_union(head, &ptr->port) ||                  if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s %s%s",
1444                                       ccs_net2keyword(bit), w[0], w[1]) ||
1445                        !ccs_print_number_union(head, &ptr->port) ||
1446                      !ccs_print_condition(head, cond))                      !ccs_print_condition(head, cond))
1447                          goto out;                          goto out;
1448          }          }
# Line 1520  static bool ccs_print_signal_acl(struct Line 1488  static bool ccs_print_signal_acl(struct
1488   */   */
1489  static bool ccs_print_execute_handler_record(struct ccs_io_buffer *head,  static bool ccs_print_execute_handler_record(struct ccs_io_buffer *head,
1490                                               const char *keyword,                                               const char *keyword,
1491                                               struct ccs_execute_handler_record *                                               struct ccs_execute_handler_record
1492                                               ptr)                                               *ptr)
1493  {  {
1494          return ccs_io_printf(head, "%s %s\n", keyword, ptr->handler->name);          return ccs_io_printf(head, "%s %s\n", keyword, ptr->handler->name);
1495  }  }
# Line 1595  static bool ccs_print_entry(struct ccs_i Line 1563  static bool ccs_print_entry(struct ccs_i
1563          }          }
1564          if (acl_type == CCS_TYPE_PATH2_ACL) {          if (acl_type == CCS_TYPE_PATH2_ACL) {
1565                  struct ccs_path2_acl *acl                  struct ccs_path2_acl *acl
1566                          = container_of(ptr, struct ccs_path2_acl,                          = container_of(ptr, struct ccs_path2_acl, head);
                                        head);  
1567                  return ccs_print_path2_acl(head, acl, cond);                  return ccs_print_path2_acl(head, acl, cond);
1568          }          }
1569          if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {          if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
1570                  struct ccs_path_number_acl *acl                  struct ccs_path_number_acl *acl
1571                          = container_of(ptr, struct ccs_path_number_acl,                          = container_of(ptr, struct ccs_path_number_acl, head);
                                        head);  
1572                  return ccs_print_path_number_acl(head, acl, cond);                  return ccs_print_path_number_acl(head, acl, cond);
1573          }          }
1574          if (acl_type == CCS_TYPE_ENV_ACL) {          if (acl_type == CCS_TYPE_ENV_ACL) {
# Line 1612  static bool ccs_print_entry(struct ccs_i Line 1578  static bool ccs_print_entry(struct ccs_i
1578          }          }
1579          if (acl_type == CCS_TYPE_CAPABILITY_ACL) {          if (acl_type == CCS_TYPE_CAPABILITY_ACL) {
1580                  struct ccs_capability_acl *acl                  struct ccs_capability_acl *acl
1581                          = container_of(ptr, struct ccs_capability_acl,                          = container_of(ptr, struct ccs_capability_acl, head);
                                        head);  
1582                  return ccs_print_capability_acl(head, acl, cond);                  return ccs_print_capability_acl(head, acl, cond);
1583          }          }
1584          if (acl_type == CCS_TYPE_IP_NETWORK_ACL) {          if (acl_type == CCS_TYPE_IP_NETWORK_ACL) {
1585                  struct ccs_ip_network_acl *acl                  struct ccs_ip_network_acl *acl
1586                          = container_of(ptr, struct ccs_ip_network_acl,                          = container_of(ptr, struct ccs_ip_network_acl, head);
                                        head);  
1587                  return ccs_print_network_acl(head, acl, cond);                  return ccs_print_network_acl(head, acl, cond);
1588          }          }
1589          if (acl_type == CCS_TYPE_SIGNAL_ACL) {          if (acl_type == CCS_TYPE_SIGNAL_ACL) {
# Line 1637  static bool ccs_print_entry(struct ccs_i Line 1601  static bool ccs_print_entry(struct ccs_i
1601  }  }
1602    
1603  /**  /**
1604   * ccs_read_domain_policy - Read domain policy.   * ccs_read_domain - Read domain policy.
1605   *   *
1606   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1607   *   *
1608   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1609   */   */
1610  static void ccs_read_domain_policy(struct ccs_io_buffer *head)  static void ccs_read_domain(struct ccs_io_buffer *head)
1611  {  {
1612          struct list_head *dpos;          struct list_head *dpos;
1613          struct list_head *apos;          struct list_head *apos;
# Line 1664  static void ccs_read_domain_policy(struc Line 1628  static void ccs_read_domain_policy(struc
1628                          continue;                          continue;
1629                  /* Print domainname and flags. */                  /* Print domainname and flags. */
1630                  if (domain->quota_warned)                  if (domain->quota_warned)
1631                          quota_exceeded = "quota_exceeded\n";                          quota_exceeded = CCS_KEYWORD_QUOTA_EXCEEDED "\n";
1632                  if (domain->domain_transition_failed)                  if (domain->domain_transition_failed)
1633                          transition_failed = "transition_failed\n";                          transition_failed = CCS_KEYWORD_TRANSITION_FAILED "\n";
1634                  if (domain->ignore_global_allow_read)                  if (domain->ignore_global_allow_read)
1635                          ignore_global_allow_read                          ignore_global_allow_read
1636                                  = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";                                  = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";
# Line 1800  static void ccs_read_pid(struct ccs_io_b Line 1764  static void ccs_read_pid(struct ccs_io_b
1764          struct ccs_domain_info *domain = NULL;          struct ccs_domain_info *domain = NULL;
1765          u32 ccs_flags = 0;          u32 ccs_flags = 0;
1766          /* Accessing write_buf is safe because head->io_sem is held. */          /* Accessing write_buf is safe because head->io_sem is held. */
1767          if (!buf)          if (!buf) {
1768                    head->read_eof = true;
1769                  return; /* Do nothing if open(O_RDONLY). */                  return; /* Do nothing if open(O_RDONLY). */
1770            }
1771          if (head->read_avail || head->read_eof)          if (head->read_avail || head->read_eof)
1772                  return;                  return;
1773          head->read_eof = true;          head->read_eof = true;
# Line 1810  static void ccs_read_pid(struct ccs_io_b Line 1776  static void ccs_read_pid(struct ccs_io_b
1776          if (ccs_str_starts(&buf, "global-pid "))          if (ccs_str_starts(&buf, "global-pid "))
1777                  global_pid = true;                  global_pid = true;
1778          pid = (unsigned int) simple_strtoul(buf, NULL, 10);          pid = (unsigned int) simple_strtoul(buf, NULL, 10);
1779          read_lock(&tasklist_lock);          ccs_tasklist_lock();
1780  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
1781          if (global_pid)          if (global_pid)
1782                  p = find_task_by_pid_ns(pid, &init_pid_ns);                  p = ccsecurity_exports.find_task_by_pid_ns(pid, &init_pid_ns);
1783          else          else
1784                  p = find_task_by_vpid(pid);                  p = ccsecurity_exports.find_task_by_vpid(pid);
1785  #else  #else
1786          p = find_task_by_pid(pid);          p = find_task_by_pid(pid);
1787  #endif  #endif
# Line 1823  static void ccs_read_pid(struct ccs_io_b Line 1789  static void ccs_read_pid(struct ccs_io_b
1789                  domain = ccs_task_domain(p);                  domain = ccs_task_domain(p);
1790                  ccs_flags = p->ccs_flags;                  ccs_flags = p->ccs_flags;
1791          }          }
1792          read_unlock(&tasklist_lock);          ccs_tasklist_unlock();
1793          if (!domain)          if (!domain)
1794                  return;                  return;
1795          if (!task_info)          if (!task_info)
# Line 1833  static void ccs_read_pid(struct ccs_io_b Line 1799  static void ccs_read_pid(struct ccs_io_b
1799                  ccs_io_printf(head, "%u manager=%s execute_handler=%s "                  ccs_io_printf(head, "%u manager=%s execute_handler=%s "
1800                                "state[0]=%u state[1]=%u state[2]=%u", pid,                                "state[0]=%u state[1]=%u state[2]=%u", pid,
1801                                ccs_yesno(ccs_flags &                                ccs_yesno(ccs_flags &
1802                                          CCS_TASK_IS_POLICY_MANAGER),                                          CCS_TASK_IS_MANAGER),
1803                                ccs_yesno(ccs_flags &                                ccs_yesno(ccs_flags &
1804                                          CCS_TASK_IS_EXECUTE_HANDLER),                                          CCS_TASK_IS_EXECUTE_HANDLER),
1805                                (u8) (ccs_flags >> 24),                                (u8) (ccs_flags >> 24),
# Line 1842  static void ccs_read_pid(struct ccs_io_b Line 1808  static void ccs_read_pid(struct ccs_io_b
1808  }  }
1809    
1810  /**  /**
1811   * ccs_write_exception_policy - Write exception policy.   * ccs_write_exception - Write exception policy.
1812   *   *
1813   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1814   *   *
1815   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1816   */   */
1817  static int ccs_write_exception_policy(struct ccs_io_buffer *head)  static int ccs_write_exception(struct ccs_io_buffer *head)
1818  {  {
1819          char *data = head->write_buf;          char *data = head->write_buf;
1820          bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE);          const bool is_delete = ccs_str_starts(&data, CCS_KEYWORD_DELETE);
1821          if (ccs_str_starts(&data, CCS_KEYWORD_KEEP_DOMAIN))          u8 i;
1822                  return ccs_write_domain_keeper_policy(data, false, is_delete);          static const struct {
1823          if (ccs_str_starts(&data, CCS_KEYWORD_NO_KEEP_DOMAIN))                  const char *keyword;
1824                  return ccs_write_domain_keeper_policy(data, true, is_delete);                  int (*write) (char *, const bool, const u8);
1825          if (ccs_str_starts(&data, CCS_KEYWORD_INITIALIZE_DOMAIN))          } ccs_callback[10] = {
1826                  return ccs_write_domain_initializer_policy(data, false,                  { CCS_KEYWORD_NO_KEEP_DOMAIN, ccs_write_domain_keeper },
1827                                                             is_delete);                  { CCS_KEYWORD_NO_INITIALIZE_DOMAIN,
1828          if (ccs_str_starts(&data, CCS_KEYWORD_NO_INITIALIZE_DOMAIN))                    ccs_write_domain_initializer },
1829                  return ccs_write_domain_initializer_policy(data, true,                  { CCS_KEYWORD_KEEP_DOMAIN, ccs_write_domain_keeper },
1830                                                             is_delete);                  { CCS_KEYWORD_INITIALIZE_DOMAIN,
1831          if (ccs_str_starts(&data, CCS_KEYWORD_AGGREGATOR))                    ccs_write_domain_initializer },
1832                  return ccs_write_aggregator_policy(data, is_delete);                  { CCS_KEYWORD_AGGREGATOR, ccs_write_aggregator },
1833          if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_READ))                  { CCS_KEYWORD_ALLOW_READ, ccs_write_global_read },
1834                  return ccs_write_globally_readable_policy(data, is_delete);                  { CCS_KEYWORD_ALLOW_ENV, ccs_write_global_env },
1835          if (ccs_str_starts(&data, CCS_KEYWORD_ALLOW_ENV))                  { CCS_KEYWORD_FILE_PATTERN, ccs_write_pattern },
1836                  return ccs_write_globally_usable_env_policy(data, is_delete);                  { CCS_KEYWORD_DENY_REWRITE, ccs_write_no_rewrite },
1837          if (ccs_str_starts(&data, CCS_KEYWORD_FILE_PATTERN))                  { CCS_KEYWORD_DENY_AUTOBIND, ccs_write_reserved_port }
1838                  return ccs_write_pattern_policy(data, is_delete);          };
1839          if (ccs_str_starts(&data, CCS_KEYWORD_PATH_GROUP))          static const char *ccs_name[CCS_MAX_GROUP] = {
1840                  return ccs_write_path_group_policy(data, is_delete);                  [CCS_PATH_GROUP] = CCS_KEYWORD_PATH_GROUP,
1841          if (ccs_str_starts(&data, CCS_KEYWORD_NUMBER_GROUP))                  [CCS_NUMBER_GROUP] = CCS_KEYWORD_NUMBER_GROUP,
1842                  return ccs_write_number_group_policy(data, is_delete);                  [CCS_ADDRESS_GROUP] = CCS_KEYWORD_ADDRESS_GROUP
1843          if (ccs_str_starts(&data, CCS_KEYWORD_DENY_REWRITE))          };
1844                  return ccs_write_no_rewrite_policy(data, is_delete);          for (i = 0; i < 10; i++) {
1845          if (ccs_str_starts(&data, CCS_KEYWORD_ADDRESS_GROUP))                  if (ccs_str_starts(&data, ccs_callback[i].keyword))
1846                  return ccs_write_address_group_policy(data, is_delete);                          return ccs_callback[i].write(data, is_delete, i < 2);
1847          if (ccs_str_starts(&data, CCS_KEYWORD_DENY_AUTOBIND))          }
1848                  return ccs_write_reserved_port_policy(data, is_delete);          for (i = 0; i < CCS_MAX_GROUP; i++) {
1849                    if (ccs_str_starts(&data, ccs_name[i]))
1850                            return ccs_write_group(data, is_delete, i);
1851            }
1852          return -EINVAL;          return -EINVAL;
1853  }  }
1854    
1855  /**  /**
1856   * ccs_read_exception_policy - Read exception policy.   * ccs_read_group - Read "struct ccs_path_group"/"struct ccs_number_group"/"struct ccs_address_group" list.
1857   *   *
1858   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1859     * @idx:  Index number.
1860     *
1861     * Returns true on success, false otherwise.
1862   *   *
1863   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1864   */   */
1865  static void ccs_read_exception_policy(struct ccs_io_buffer *head)  static bool ccs_read_group(struct ccs_io_buffer *head, const int idx)
1866  {  {
1867          if (head->read_eof)          struct list_head *gpos;
1868                  return;          struct list_head *mpos;
1869          switch (head->read_step) {          const char *w[3] = { "", "", "" };
1870          case 0:          if (idx == CCS_PATH_GROUP)
1871                  head->read_var2 = NULL;                  w[0] = CCS_KEYWORD_PATH_GROUP;
1872                  head->read_step = 1;          else if (idx == CCS_NUMBER_GROUP)
1873          case 1:                  w[0] = CCS_KEYWORD_NUMBER_GROUP;
1874                  if (!ccs_read_domain_keeper_policy(head))          else if (idx == CCS_ADDRESS_GROUP)
1875                          break;                  w[0] = CCS_KEYWORD_ADDRESS_GROUP;
1876                  head->read_var2 = NULL;          list_for_each_cookie(gpos, head->read_var1, &ccs_group_list[idx]) {
1877                  head->read_step = 2;                  struct ccs_group *group =
1878          case 2:                          list_entry(gpos, struct ccs_group, head.list);
1879                  if (!ccs_read_globally_readable_policy(head))                  w[1] = group->group_name->name;
1880                          break;                  list_for_each_cookie(mpos, head->read_var2,
1881                  head->read_var2 = NULL;                                       &group->member_list) {
1882                  head->read_step = 3;                          char buffer[128];
1883          case 3:                          struct ccs_acl_head *ptr =
1884                  if (!ccs_read_globally_usable_env_policy(head))                                  list_entry(mpos, struct ccs_acl_head, list);
1885                          break;                          if (ptr->is_deleted)
1886                  head->read_var2 = NULL;                                  continue;
1887                  head->read_step = 4;                          if (idx == CCS_PATH_GROUP) {
1888          case 4:                                  w[2] = container_of(ptr, struct ccs_path_group,
1889                  if (!ccs_read_domain_initializer_policy(head))                                                      head)->member_name->name;
1890                            } else if (idx == CCS_NUMBER_GROUP) {
1891                                    w[2] = buffer;
1892                                    ccs_print_number(buffer, sizeof(buffer),
1893                                                     &container_of
1894                                                     (ptr, struct ccs_number_group,
1895                                                      head)->number);
1896                            } else if (idx == CCS_ADDRESS_GROUP) {
1897                                    struct ccs_address_group *member =
1898                                            container_of(ptr, typeof(*member),
1899                                                         head);
1900                                    w[2] = buffer;
1901                                    if (member->is_ipv6)
1902                                            ccs_print_ipv6(buffer, sizeof(buffer),
1903                                                           member->min.ipv6,
1904                                                           member->max.ipv6);
1905                                    else
1906                                            ccs_print_ipv4(buffer, sizeof(buffer),
1907                                                           member->min.ipv4,
1908                                                           member->max.ipv4);
1909                            }
1910                            if (!ccs_io_printf(head, "%s%s %s\n", w[0], w[1],
1911                                               w[2]))
1912                                    return false;
1913                    }
1914            }
1915            return true;
1916    }
1917    
1918    /**
1919     * ccs_read_policy - Read "struct ccs_..._entry" list.
1920     *
1921     * @head: Pointer to "struct ccs_io_buffer".
1922     * @idx:  Index number.
1923     *
1924     * Returns true on success, false otherwise.
1925     *
1926     * Caller holds ccs_read_lock().
1927     */
1928    static bool ccs_read_policy(struct ccs_io_buffer *head, const int idx)
1929    {
1930            struct list_head *pos;
1931            list_for_each_cookie(pos, head->read_var2, &ccs_policy_list[idx]) {
1932                    const char *w[4] = { "", "", "", "" };
1933                    char buffer[16];
1934                    struct ccs_acl_head *acl = container_of(pos, typeof(*acl),
1935                                                            list);
1936                    if (acl->is_deleted)
1937                            continue;
1938                    switch (idx) {
1939                    case CCS_ID_DOMAIN_KEEPER:
1940                            {
1941                                    struct ccs_domain_keeper *ptr =
1942                                            container_of(acl, typeof(*ptr), head);
1943                                    w[0] = ptr->is_not ?
1944                                            CCS_KEYWORD_NO_KEEP_DOMAIN :
1945                                            CCS_KEYWORD_KEEP_DOMAIN;
1946                                    if (ptr->program) {
1947                                            w[1] = ptr->program->name;
1948                                            w[2] = " from ";
1949                                    }
1950                                    w[3] = ptr->domainname->name;
1951                            }
1952                          break;                          break;
1953                  head->read_var2 = NULL;                  case CCS_ID_DOMAIN_INITIALIZER:
1954                  head->read_step = 6;                          {
1955          case 6:                                  struct ccs_domain_initializer *ptr =
1956                  if (!ccs_read_aggregator_policy(head))                                          container_of(acl, typeof(*ptr), head);
1957                                    w[0] = ptr->is_not ?
1958                                            CCS_KEYWORD_NO_INITIALIZE_DOMAIN :
1959                                            CCS_KEYWORD_INITIALIZE_DOMAIN;
1960                                    w[1] = ptr->program->name;
1961                                    if (ptr->domainname) {
1962                                            w[2] = " from ";
1963                                            w[3] = ptr->domainname->name;
1964                                    }
1965                            }
1966                          break;                          break;
1967                  head->read_var2 = NULL;                  case CCS_ID_AGGREGATOR:
1968                  head->read_step = 7;                          {
1969          case 7:                                  struct ccs_aggregator *ptr =
1970                  if (!ccs_read_file_pattern(head))                                          container_of(acl, typeof(*ptr), head);
1971                                    w[0] = CCS_KEYWORD_AGGREGATOR;
1972                                    w[1] = ptr->original_name->name;
1973                                    w[2] = " ";
1974                                    w[3] = ptr->aggregated_name->name;
1975                            }
1976                          break;                          break;
1977                  head->read_var2 = NULL;                  case CCS_ID_GLOBAL_READ:
1978                  head->read_step = 8;                          {
1979          case 8:                                  struct ccs_global_read *ptr =
1980                  if (!ccs_read_no_rewrite_policy(head))                                          container_of(acl, typeof(*ptr), head);
1981                                    w[0] = CCS_KEYWORD_ALLOW_READ;
1982                                    w[1] = ptr->filename->name;
1983                            }
1984                          break;                          break;
1985                  head->read_var2 = NULL;                  case CCS_ID_PATTERN:
1986                  head->read_step = 9;                          {
1987          case 9:                                  struct ccs_pattern *ptr =
1988                  if (!ccs_read_path_group_policy(head))                                          container_of(acl, typeof(*ptr), head);
1989                                    w[0] = CCS_KEYWORD_FILE_PATTERN;
1990                                    w[1] = ptr->pattern->name;
1991                            }
1992                          break;                          break;
1993                  head->read_var1 = NULL;                  case CCS_ID_NO_REWRITE:
1994                  head->read_var2 = NULL;                          {
1995                  head->read_step = 10;                                  struct ccs_no_rewrite *ptr =
1996          case 10:                                          container_of(acl, typeof(*ptr), head);
1997                  if (!ccs_read_number_group_policy(head))                                  w[0] = CCS_KEYWORD_DENY_REWRITE;
1998                                    w[1] = ptr->pattern->name;
1999                            }
2000                          break;                          break;
2001                  head->read_var1 = NULL;                  case CCS_ID_GLOBAL_ENV:
2002                  head->read_var2 = NULL;                          {
2003                  head->read_step = 11;                                  struct ccs_global_env *ptr =
2004          case 11:                                          container_of(acl, typeof(*ptr), head);
2005                  if (!ccs_read_address_group_policy(head))                                  w[0] = CCS_KEYWORD_ALLOW_ENV;
2006                                    w[1] = ptr->env->name;
2007                            }
2008                          break;                          break;
2009                  head->read_var2 = NULL;                  case CCS_ID_RESERVEDPORT:
2010                  head->read_step = 12;                          {
2011          case 12:                                  struct ccs_reserved *ptr =
2012                  if (!ccs_read_reserved_port_policy(head))                                          container_of(acl, typeof(*ptr), head);
2013                                    const u16 min_port = ptr->min_port;
2014                                    const u16 max_port = ptr->max_port;
2015                                    w[0] = CCS_KEYWORD_DENY_AUTOBIND;
2016                                    snprintf(buffer, sizeof(buffer) - 1, "%u%c%u",
2017                                             min_port, min_port != max_port ?
2018                                             '-' : '\0', max_port);
2019                                    buffer[sizeof(buffer) - 1] = '\0';
2020                                    w[1] = buffer;
2021                            }
2022                          break;                          break;
2023                  head->read_eof = true;                  }
2024                    if (!ccs_io_printf(head, "%s%s%s%s\n", w[0], w[1], w[2], w[3]))
2025                            return false;
2026          }          }
2027            return true;
2028    }
2029    
2030    /**
2031     * ccs_read_exception - Read exception policy.
2032     *
2033     * @head: Pointer to "struct ccs_io_buffer".
2034     *
2035     * Caller holds ccs_read_lock().
2036     */
2037    static void ccs_read_exception(struct ccs_io_buffer *head)
2038    {
2039            if (head->read_eof)
2040                    return;
2041            while (head->read_step < CCS_MAX_POLICY &&
2042                   ccs_read_policy(head, head->read_step))
2043                    head->read_step++;
2044            if (head->read_step < CCS_MAX_POLICY)
2045                    return;
2046            while (head->read_step < CCS_MAX_POLICY + CCS_MAX_GROUP &&
2047                   ccs_read_group(head, head->read_step - CCS_MAX_POLICY))
2048                    head->read_step++;
2049            head->read_eof = head->read_step == CCS_MAX_POLICY + CCS_MAX_GROUP;
2050  }  }
2051    
2052  /**  /**
2053   * ccs_get_argv0 - Get argv[0].   * ccs_get_argv0 - Get argv[0].
2054   *   *
2055   * @ee: Pointer to "struct ccs_execve_entry".   * @ee: Pointer to "struct ccs_execve".
2056   *   *
2057   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
2058   */   */
2059  static bool ccs_get_argv0(struct ccs_execve_entry *ee)  static bool ccs_get_argv0(struct ccs_execve *ee)
2060  {  {
2061          struct linux_binprm *bprm = ee->bprm;          struct linux_binprm *bprm = ee->bprm;
2062          char *arg_ptr = ee->tmp;          char *arg_ptr = ee->tmp;
# Line 2013  static bool ccs_get_argv0(struct ccs_exe Line 2105  static bool ccs_get_argv0(struct ccs_exe
2105  /**  /**
2106   * ccs_get_execute_condition - Get condition part for execute requests.   * ccs_get_execute_condition - Get condition part for execute requests.
2107   *   *
2108   * @ee: Pointer to "struct ccs_execve_entry".   * @ee: Pointer to "struct ccs_execve".
2109   *   *
2110   * Returns pointer to "struct ccs_condition" on success, NULL otherwise.   * Returns pointer to "struct ccs_condition" on success, NULL otherwise.
2111   */   */
2112  static struct ccs_condition *ccs_get_execute_condition(struct ccs_execve_entry  static struct ccs_condition *ccs_get_execute_condition(struct ccs_execve
2113                                                         *ee)                                                         *ee)
2114  {  {
2115          struct ccs_condition *cond;          struct ccs_condition *cond;
# Line 2025  static struct ccs_condition *ccs_get_exe Line 2117  static struct ccs_condition *ccs_get_exe
2117          int len = 256;          int len = 256;
2118          char *realpath = NULL;          char *realpath = NULL;
2119          char *argv0 = NULL;          char *argv0 = NULL;
2120          const struct ccs_profile *profile = ccs_profile(ee->r.domain->profile);          const struct ccs_profile *profile = ccs_profile(ccs_current_domain()->
2121                                                            profile);
2122          if (profile->learning->learning_exec_realpath) {          if (profile->learning->learning_exec_realpath) {
2123                  struct file *file = ee->bprm->file;                  struct file *file = ee->bprm->file;
2124  #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)  #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
# Line 2043  static struct ccs_condition *ccs_get_exe Line 2136  static struct ccs_condition *ccs_get_exe
2136                          len += strlen(argv0) + 16;                          len += strlen(argv0) + 16;
2137                  }                  }
2138          }          }
2139          buf = kmalloc(len, GFP_KERNEL);          buf = kmalloc(len, CCS_GFP_FLAGS);
2140          if (!buf) {          if (!buf) {
2141                  kfree(realpath);                  kfree(realpath);
2142                  return NULL;                  return NULL;
# Line 2089  static struct ccs_condition *ccs_get_sym Line 2182  static struct ccs_condition *ccs_get_sym
2182                  symlink = r->obj->symlink_target->name;                  symlink = r->obj->symlink_target->name;
2183                  len += strlen(symlink) + 18;                  len += strlen(symlink) + 18;
2184          }          }
2185          buf = kmalloc(len, GFP_KERNEL);          buf = kmalloc(len, CCS_GFP_FLAGS);
2186          if (!buf)          if (!buf)
2187                  return NULL;                  return NULL;
2188          snprintf(buf, len - 1, "if");          snprintf(buf, len - 1, "if");
# Line 2137  static atomic_t ccs_query_observers = AT Line 2230  static atomic_t ccs_query_observers = AT
2230   * @fmt:     The printf()'s format string, followed by parameters.   * @fmt:     The printf()'s format string, followed by parameters.
2231   *   *
2232   * Returns 0 if the supervisor decided to permit the access request which   * Returns 0 if the supervisor decided to permit the access request which
2233   * violated the policy in enforcing mode, 1 if the supervisor decided to   * violated the policy in enforcing mode, CCS_RETRY_REQUEST if the supervisor
2234   * retry the access request which violated the policy in enforcing mode,   * decided to retry the access request which violated the policy in enforcing
2235   * 0 if it is not in enforcing mode, -EPERM otherwise.   * mode, 0 if it is not in enforcing mode, -EPERM otherwise.
2236   */   */
2237  int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...)  int ccs_supervisor(struct ccs_request_info *r, const char *fmt, ...)
2238  {  {
# Line 2151  int ccs_supervisor(struct ccs_request_in Line 2244  int ccs_supervisor(struct ccs_request_in
2244          struct ccs_query_entry *ccs_query_entry = NULL;          struct ccs_query_entry *ccs_query_entry = NULL;
2245          bool quota_exceeded = false;          bool quota_exceeded = false;
2246          char *header;          char *header;
2247          if (!r->domain)          struct ccs_domain_info * const domain = ccs_current_domain();
                 r->domain = ccs_current_domain();  
2248          switch (r->mode) {          switch (r->mode) {
2249                  char *buffer;                  char *buffer;
2250                  struct ccs_condition *cond;                  struct ccs_condition *cond;
# Line 2162  int ccs_supervisor(struct ccs_request_in Line 2254  int ccs_supervisor(struct ccs_request_in
2254                  va_start(args, fmt);                  va_start(args, fmt);
2255                  len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 4;                  len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 4;
2256                  va_end(args);                  va_end(args);
2257                  buffer = kmalloc(len, GFP_KERNEL);                  buffer = kmalloc(len, CCS_GFP_FLAGS);
2258                  if (!buffer)                  if (!buffer)
2259                          return 0;                          return 0;
2260                  va_start(args, fmt);                  va_start(args, fmt);
# Line 2178  int ccs_supervisor(struct ccs_request_in Line 2270  int ccs_supervisor(struct ccs_request_in
2270                          cond = ccs_get_condition(str);                          cond = ccs_get_condition(str);
2271                  } else                  } else
2272                          cond = NULL;                          cond = NULL;
2273                  ccs_write_domain_policy2(buffer, r->domain, cond, false);                  ccs_write_domain2(buffer, domain, cond, false);
2274                  ccs_put_condition(cond);                  ccs_put_condition(cond);
2275                  kfree(buffer);                  kfree(buffer);
2276                  /* fall through */                  /* fall through */
# Line 2189  int ccs_supervisor(struct ccs_request_in Line 2281  int ccs_supervisor(struct ccs_request_in
2281                  int i;                  int i;
2282                  if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)                  if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)
2283                          return -EPERM;                          return -EPERM;
2284                  for (i = 0; i < ccs_profile(r->domain->profile)->enforcing->                  for (i = 0; i < ccs_profile(domain->profile)->enforcing->
2285                               enforcing_penalty; i++) {                               enforcing_penalty; i++) {
2286                          set_current_state(TASK_INTERRUPTIBLE);                          set_current_state(TASK_INTERRUPTIBLE);
2287                          schedule_timeout(HZ / 10);                          schedule_timeout(HZ / 10);
# Line 2199  int ccs_supervisor(struct ccs_request_in Line 2291  int ccs_supervisor(struct ccs_request_in
2291          va_start(args, fmt);          va_start(args, fmt);
2292          len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32;          len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32;
2293          va_end(args);          va_end(args);
2294          header = ccs_init_audit_log(&len, r);          header = ccs_init_log(&len, r);
2295          if (!header)          if (!header)
2296                  goto out;                  goto out;
2297          ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), GFP_KERNEL);          ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), CCS_GFP_FLAGS);
2298          if (!ccs_query_entry)          if (!ccs_query_entry)
2299                  goto out;                  goto out;
2300          len = ccs_round2(len);          len = ccs_round2(len);
2301          ccs_query_entry->query = kzalloc(len, GFP_KERNEL);          ccs_query_entry->query = kzalloc(len, CCS_GFP_FLAGS);
2302          if (!ccs_query_entry->query)          if (!ccs_query_entry->query)
2303                  goto out;                  goto out;
2304          INIT_LIST_HEAD(&ccs_query_entry->list);          INIT_LIST_HEAD(&ccs_query_entry->list);
# Line 2248  int ccs_supervisor(struct ccs_request_in Line 2340  int ccs_supervisor(struct ccs_request_in
2340          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
2341          switch (ccs_query_entry->answer) {          switch (ccs_query_entry->answer) {
2342          case 3: /* Asked to retry by administrator. */          case 3: /* Asked to retry by administrator. */
2343                  error = 1;                  error = CCS_RETRY_REQUEST;
2344                  r->retry++;                  r->retry++;
2345                  break;                  break;
2346          case 1:          case 1:
# Line 2288  static int ccs_poll_query(struct file *f Line 2380  static int ccs_poll_query(struct file *f
2380          for (i = 0; i < 2; i++) {          for (i = 0; i < 2; i++) {
2381                  spin_lock(&ccs_query_list_lock);                  spin_lock(&ccs_query_list_lock);
2382                  list_for_each(tmp, &ccs_query_list) {                  list_for_each(tmp, &ccs_query_list) {
2383                          struct ccs_query_entry *ptr                          struct ccs_query_entry *ptr =
2384                                  = list_entry(tmp, struct ccs_query_entry, list);                                  list_entry(tmp, struct ccs_query_entry, list);
2385                          if (ptr->answer)                          if (ptr->answer)
2386                                  continue;                                  continue;
2387                          found = true;                          found = true;
# Line 2339  static void ccs_read_query(struct ccs_io Line 2431  static void ccs_read_query(struct ccs_io
2431                  head->read_step = 0;                  head->read_step = 0;
2432                  return;                  return;
2433          }          }
2434          buf = kzalloc(len, GFP_KERNEL);          buf = kzalloc(len, CCS_GFP_FLAGS);
2435          if (!buf)          if (!buf)
2436                  return;                  return;
2437          pos = 0;          pos = 0;
# Line 2415  static void ccs_read_version(struct ccs_ Line 2507  static void ccs_read_version(struct ccs_
2507  {  {
2508          if (head->read_eof)          if (head->read_eof)
2509                  return;                  return;
2510          ccs_io_printf(head, "1.7.0");          ccs_io_printf(head, "1.7.2");
2511          head->read_eof = true;          head->read_eof = true;
2512  }  }
2513    
# Line 2446  static void ccs_read_self_domain(struct Line 2538  static void ccs_read_self_domain(struct
2538   */   */
2539  int ccs_open_control(const u8 type, struct file *file)  int ccs_open_control(const u8 type, struct file *file)
2540  {  {
2541          struct ccs_io_buffer *head = kzalloc(sizeof(*head), GFP_KERNEL);          struct ccs_io_buffer *head = kzalloc(sizeof(*head), CCS_GFP_FLAGS);
2542          if (!head)          if (!head)
2543                  return -ENOMEM;                  return -ENOMEM;
2544          mutex_init(&head->io_sem);          mutex_init(&head->io_sem);
2545          head->type = type;          head->type = type;
2546          switch (type) {          switch (type) {
2547          case CCS_DOMAINPOLICY: /* /proc/ccs/domain_policy */          case CCS_DOMAINPOLICY: /* /proc/ccs/domain_policy */
2548                  head->write = ccs_write_domain_policy;                  head->write = ccs_write_domain;
2549                  head->read = ccs_read_domain_policy;                  head->read = ccs_read_domain;
2550                  break;                  break;
2551          case CCS_EXCEPTIONPOLICY: /* /proc/ccs/exception_policy */          case CCS_EXCEPTIONPOLICY: /* /proc/ccs/exception_policy */
2552                  head->write = ccs_write_exception_policy;                  head->write = ccs_write_exception;
2553                  head->read = ccs_read_exception_policy;                  head->read = ccs_read_exception;
2554                  break;                  break;
2555  #ifdef CONFIG_CCSECURITY_AUDIT  #ifdef CONFIG_CCSECURITY_AUDIT
2556          case CCS_GRANTLOG: /* /proc/ccs/grant_log */          case CCS_GRANTLOG: /* /proc/ccs/grant_log */
                 head->poll = ccs_poll_grant_log;  
                 head->read = ccs_read_grant_log;  
                 break;  
2557          case CCS_REJECTLOG: /* /proc/ccs/reject_log */          case CCS_REJECTLOG: /* /proc/ccs/reject_log */
2558                  head->poll = ccs_poll_reject_log;                  head->poll = ccs_poll_log;
2559                  head->read = ccs_read_reject_log;                  head->read = ccs_read_log;
2560                  break;                  break;
2561  #endif  #endif
2562          case CCS_SELFDOMAIN: /* /proc/ccs/self_domain */          case CCS_SELFDOMAIN: /* /proc/ccs/self_domain */
# Line 2507  int ccs_open_control(const u8 type, stru Line 2596  int ccs_open_control(const u8 type, stru
2596                  head->read = ccs_read_query;                  head->read = ccs_read_query;
2597                  break;                  break;
2598          case CCS_MANAGER: /* /proc/ccs/manager */          case CCS_MANAGER: /* /proc/ccs/manager */
2599                  head->write = ccs_write_manager_policy;                  head->write = ccs_write_manager;
2600                  head->read = ccs_read_manager_policy;                  head->read = ccs_read_manager;
2601                  break;                  break;
2602          }          }
2603          if (!(file->f_mode & FMODE_READ)) {          if (!(file->f_mode & FMODE_READ)) {
# Line 2522  int ccs_open_control(const u8 type, stru Line 2611  int ccs_open_control(const u8 type, stru
2611                  /* Don't allocate read_buf for poll() access. */                  /* Don't allocate read_buf for poll() access. */
2612                  if (!head->readbuf_size)                  if (!head->readbuf_size)
2613                          head->readbuf_size = 4096;                          head->readbuf_size = 4096;
2614                  head->read_buf = kzalloc(head->readbuf_size, GFP_KERNEL);                  head->read_buf = kzalloc(head->readbuf_size, CCS_GFP_FLAGS);
2615                  if (!head->read_buf) {                  if (!head->read_buf) {
2616                          kfree(head);                          kfree(head);
2617                          return -ENOMEM;                          return -ENOMEM;
# Line 2536  int ccs_open_control(const u8 type, stru Line 2625  int ccs_open_control(const u8 type, stru
2625                  head->write = NULL;                  head->write = NULL;
2626          } else if (head->write) {          } else if (head->write) {
2627                  head->writebuf_size = 4096;                  head->writebuf_size = 4096;
2628                  head->write_buf = kzalloc(head->writebuf_size, GFP_KERNEL);                  head->write_buf = kzalloc(head->writebuf_size, CCS_GFP_FLAGS);
2629                  if (!head->write_buf) {                  if (!head->write_buf) {
2630                          kfree(head->read_buf);                          kfree(head->read_buf);
2631                          kfree(head);                          kfree(head);
# Line 2545  int ccs_open_control(const u8 type, stru Line 2634  int ccs_open_control(const u8 type, stru
2634          }          }
2635          if (type != CCS_QUERY &&          if (type != CCS_QUERY &&
2636              type != CCS_GRANTLOG && type != CCS_REJECTLOG)              type != CCS_GRANTLOG && type != CCS_REJECTLOG)
2637                  head->reader_idx = ccs_read_lock();                  head->reader_idx = ccs_lock();
2638          file->private_data = head;          file->private_data = head;
2639          /*          /*
2640           * Call the handler now if the file is /proc/ccs/self_domain           * Call the handler now if the file is /proc/ccs/self_domain
# Line 2598  int ccs_read_control(struct file *file, Line 2687  int ccs_read_control(struct file *file,
2687          int len = 0;          int len = 0;
2688          struct ccs_io_buffer *head = file->private_data;          struct ccs_io_buffer *head = file->private_data;
2689          char *cp;          char *cp;
2690            int idx;
2691          if (!head->read)          if (!head->read)
2692                  return -ENOSYS;                  return -ENOSYS;
2693          if (!access_ok(VERIFY_WRITE, buffer, buffer_len))          if (!access_ok(VERIFY_WRITE, buffer, buffer_len))
2694                  return -EFAULT;                  return -EFAULT;
2695          if (mutex_lock_interruptible(&head->io_sem))          if (mutex_lock_interruptible(&head->io_sem))
2696                  return -EINTR;                  return -EINTR;
2697            idx = ccs_read_lock();
2698          while (1) {          while (1) {
2699                  /* Call the policy handler. */                  /* Call the policy handler. */
2700                  head->read(head);                  head->read(head);
# Line 2612  int ccs_read_control(struct file *file, Line 2703  int ccs_read_control(struct file *file,
2703                  if (len || head->poll || head->read_eof)                  if (len || head->poll || head->read_eof)
2704                          break;                          break;
2705                  len = head->readbuf_size * 2;                  len = head->readbuf_size * 2;
2706                  cp = kzalloc(len, GFP_KERNEL);                  cp = kzalloc(len, CCS_GFP_FLAGS);
2707                  if (!cp) {                  if (!cp) {
2708                          len = -ENOMEM;                          len = -ENOMEM;
2709                          goto out;                          goto out;
# Line 2634  int ccs_read_control(struct file *file, Line 2725  int ccs_read_control(struct file *file,
2725          head->read_avail -= len;          head->read_avail -= len;
2726          memmove(cp, cp + len, head->read_avail);          memmove(cp, cp + len, head->read_avail);
2727   out:   out:
2728            ccs_read_unlock(idx);
2729          mutex_unlock(&head->io_sem);          mutex_unlock(&head->io_sem);
2730          return len;          return len;
2731  }  }
# Line 2654  int ccs_write_control(struct file *file, Line 2746  int ccs_write_control(struct file *file,
2746          int error = buffer_len;          int error = buffer_len;
2747          int avail_len = buffer_len;          int avail_len = buffer_len;
2748          char *cp0 = head->write_buf;          char *cp0 = head->write_buf;
2749            int idx;
2750          if (!head->write)          if (!head->write)
2751                  return -ENOSYS;                  return -ENOSYS;
2752          if (!access_ok(VERIFY_READ, buffer, buffer_len))          if (!access_ok(VERIFY_READ, buffer, buffer_len))
2753                  return -EFAULT;                  return -EFAULT;
         /* Don't allow updating policies by non manager programs. */  
         if (head->write != ccs_write_pid &&  
             head->write != ccs_write_domain_policy &&  
             !ccs_is_policy_manager())  
                 return -EPERM;  
2754          if (mutex_lock_interruptible(&head->io_sem))          if (mutex_lock_interruptible(&head->io_sem))
2755                  return -EINTR;                  return -EINTR;
2756            idx = ccs_read_lock();
2757            /* Don't allow updating policies by non manager programs. */
2758            if (head->write != ccs_write_pid && head->write != ccs_write_domain &&
2759                !ccs_manager()) {
2760                    ccs_read_unlock(idx);
2761                    mutex_unlock(&head->io_sem);
2762                    return -EPERM;
2763            }
2764          /* Read a line and dispatch it to the policy handler. */          /* Read a line and dispatch it to the policy handler. */
2765          while (avail_len > 0) {          while (avail_len > 0) {
2766                  char c;                  char c;
2767                  if (head->write_avail >= head->writebuf_size - 1) {                  if (head->write_avail >= head->writebuf_size - 1) {
2768                          const int len = head->writebuf_size * 2;                          const int len = head->writebuf_size * 2;
2769                          char *cp = kzalloc(len, GFP_KERNEL);                          char *cp = kzalloc(len, CCS_GFP_FLAGS);
2770                          if (!cp) {                          if (!cp) {
2771                                  error = -ENOMEM;                                  error = -ENOMEM;
2772                                  break;                                  break;
# Line 2695  int ccs_write_control(struct file *file, Line 2791  int ccs_write_control(struct file *file,
2791                  ccs_normalize_line(cp0);                  ccs_normalize_line(cp0);
2792                  head->write(head);                  head->write(head);
2793          }          }
2794            ccs_read_unlock(idx);
2795          mutex_unlock(&head->io_sem);          mutex_unlock(&head->io_sem);
2796          return error;          return error;
2797  }  }
# Line 2718  int ccs_close_control(struct file *file) Line 2815  int ccs_close_control(struct file *file)
2815                  atomic_dec(&ccs_query_observers);                  atomic_dec(&ccs_query_observers);
2816          if (type != CCS_QUERY &&          if (type != CCS_QUERY &&
2817              type != CCS_GRANTLOG && type != CCS_REJECTLOG)              type != CCS_GRANTLOG && type != CCS_REJECTLOG)
2818                  ccs_read_unlock(head->reader_idx);                  ccs_unlock(head->reader_idx);
2819          /* Release memory used for policy I/O. */          /* Release memory used for policy I/O. */
2820          kfree(head->read_buf);          kfree(head->read_buf);
2821          head->read_buf = NULL;          head->read_buf = NULL;
# Line 2731  int ccs_close_control(struct file *file) Line 2828  int ccs_close_control(struct file *file)
2828                  ccs_run_gc();                  ccs_run_gc();
2829          return 0;          return 0;
2830  }  }
2831    
2832    void __init ccs_policy_io_init(void)
2833    {
2834            ccsecurity_ops.check_profile = ccs_check_profile;
2835    }

Legend:
Removed from v.3079  
changed lines
  Added in v.3695

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