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

Subversion リポジトリの参照

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

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

revision 4806 by kumaneko, Sat Apr 2 16:32:44 2011 UTC revision 5526 by kumaneko, Mon Oct 3 07:12:14 2011 UTC
# Line 3  Line 3 
3   *   *
4   * Copyright (C) 2005-2011  NTT DATA CORPORATION   * Copyright (C) 2005-2011  NTT DATA CORPORATION
5   *   *
6   * Version: 1.8.1   2011/04/01   * Version: 1.8.3   2011/09/29
7   */   */
8    
9  #include "internal.h"  #include "internal.h"
# Line 79  do {                                                                   \ Line 79  do {                                                                   \
79          for (pos = pos ? pos : srcu_dereference((head)->next, &ccs_ss); \          for (pos = pos ? pos : srcu_dereference((head)->next, &ccs_ss); \
80               pos != (head); pos = srcu_dereference(pos->next, &ccs_ss))               pos != (head); pos = srcu_dereference(pos->next, &ccs_ss))
81    
   
 /* Profile version. Currently only 20100903 is defined. */  
 static unsigned int ccs_profile_version;  
   
 /* Profile table. Memory is allocated as needed. */  
 static struct ccs_profile *ccs_profile_ptr[CCS_MAX_PROFILES];  
   
82  /* String table for operation mode. */  /* String table for operation mode. */
83  const char * const ccs_mode[CCS_CONFIG_MAX_MODE] = {  const char * const ccs_mode[CCS_CONFIG_MAX_MODE] = {
84          [CCS_CONFIG_DISABLED]   = "disabled",          [CCS_CONFIG_DISABLED]   = "disabled",
# Line 181  const char * const ccs_path_keyword[CCS_ Line 174  const char * const ccs_path_keyword[CCS_
174          [CCS_TYPE_UMOUNT]     = "unmount",          [CCS_TYPE_UMOUNT]     = "unmount",
175  };  };
176    
177    /* String table for socket's operation. */
178    const char * const ccs_socket_keyword[CCS_MAX_NETWORK_OPERATION] = {
179            [CCS_NETWORK_BIND]    = "bind",
180            [CCS_NETWORK_LISTEN]  = "listen",
181            [CCS_NETWORK_CONNECT] = "connect",
182            [CCS_NETWORK_ACCEPT]  = "accept",
183            [CCS_NETWORK_SEND]    = "send",
184            [CCS_NETWORK_RECV]    = "recv",
185    };
186    
187  /* String table for categories. */  /* String table for categories. */
188  static const char * const ccs_category_keywords[CCS_MAX_MAC_CATEGORY_INDEX] = {  static const char * const ccs_category_keywords[CCS_MAX_MAC_CATEGORY_INDEX] = {
189          [CCS_MAC_CATEGORY_FILE]       = "file",          [CCS_MAC_CATEGORY_FILE]       = "file",
# Line 326  static bool ccs_flush(struct ccs_io_buff Line 329  static bool ccs_flush(struct ccs_io_buff
329                  if (*w)                  if (*w)
330                          return false;                          return false;
331                  /* Add '\0' for audit logs and query. */                  /* Add '\0' for audit logs and query. */
332                  if (head->poll) {                  if (head->type == CCS_AUDIT || head->type == CCS_QUERY) {
333                          if (!head->read_user_buf_avail ||                          if (!head->read_user_buf_avail ||
334                              copy_to_user(head->read_user_buf, "", 1))                              copy_to_user(head->read_user_buf, "", 1))
335                                  return false;                                  return false;
# Line 430  static void ccs_set_slash(struct ccs_io_ Line 433  static void ccs_set_slash(struct ccs_io_
433          ccs_set_string(head, "/");          ccs_set_string(head, "/");
434  }  }
435    
436    /* List of namespaces. */
437    LIST_HEAD(ccs_namespace_list);
438    /* True if namespace other than ccs_kernel_namespace is defined. */
439    static bool ccs_namespace_enabled;
440    
441    /**
442     * ccs_init_policy_namespace - Initialize namespace.
443     *
444     * @ns: Pointer to "struct ccs_policy_namespace".
445     *
446     * Returns nothing.
447     */
448    void ccs_init_policy_namespace(struct ccs_policy_namespace *ns)
449    {
450            unsigned int idx;
451            for (idx = 0; idx < CCS_MAX_ACL_GROUPS; idx++)
452                    INIT_LIST_HEAD(&ns->acl_group[idx]);
453            for (idx = 0; idx < CCS_MAX_GROUP; idx++)
454                    INIT_LIST_HEAD(&ns->group_list[idx]);
455            for (idx = 0; idx < CCS_MAX_POLICY; idx++)
456                    INIT_LIST_HEAD(&ns->policy_list[idx]);
457            ns->profile_version = 20100903;
458            ccs_namespace_enabled = !list_empty(&ccs_namespace_list);
459            list_add_tail_rcu(&ns->namespace_list, &ccs_namespace_list);
460    }
461    
462    /**
463     * ccs_print_namespace - Print namespace header.
464     *
465     * @head: Pointer to "struct ccs_io_buffer".
466     *
467     * Returns nothing.
468     */
469    static void ccs_print_namespace(struct ccs_io_buffer *head)
470    {
471            if (!ccs_namespace_enabled)
472                    return;
473            ccs_set_string(head,
474                           container_of(head->r.ns, struct ccs_policy_namespace,
475                                        namespace_list)->name);
476            ccs_set_space(head);
477    }
478    
479  /**  /**
480   * ccs_assign_profile - Create a new profile.   * ccs_assign_profile - Create a new profile.
481   *   *
482     * @ns:      Pointer to "struct ccs_policy_namespace".
483   * @profile: Profile number to create.   * @profile: Profile number to create.
484   *   *
485   * Returns pointer to "struct ccs_profile" on success, NULL otherwise.   * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
486   */   */
487  static struct ccs_profile *ccs_assign_profile(const unsigned int profile)  static struct ccs_profile *ccs_assign_profile(struct ccs_policy_namespace *ns,
488                                                  const unsigned int profile)
489  {  {
490          struct ccs_profile *ptr;          struct ccs_profile *ptr;
491          struct ccs_profile *entry;          struct ccs_profile *entry;
492          if (profile >= CCS_MAX_PROFILES)          if (profile >= CCS_MAX_PROFILES)
493                  return NULL;                  return NULL;
494          ptr = ccs_profile_ptr[profile];          ptr = ns->profile_ptr[profile];
495          if (ptr)          if (ptr)
496                  return ptr;                  return ptr;
497          entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);          entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);
498          if (mutex_lock_interruptible(&ccs_policy_lock))          if (mutex_lock_interruptible(&ccs_policy_lock))
499                  goto out;                  goto out;
500          ptr = ccs_profile_ptr[profile];          ptr = ns->profile_ptr[profile];
501          if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {          if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {
502                  ptr = entry;                  ptr = entry;
503                  ptr->default_config = CCS_CONFIG_DISABLED |                  ptr->default_config = CCS_CONFIG_DISABLED |
# Line 461  static struct ccs_profile *ccs_assign_pr Line 509  static struct ccs_profile *ccs_assign_pr
509                  ptr->pref[CCS_PREF_MAX_LEARNING_ENTRY] =                  ptr->pref[CCS_PREF_MAX_LEARNING_ENTRY] =
510                          CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY;                          CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY;
511                  mb(); /* Avoid out-of-order execution. */                  mb(); /* Avoid out-of-order execution. */
512                  ccs_profile_ptr[profile] = ptr;                  ns->profile_ptr[profile] = ptr;
513                  entry = NULL;                  entry = NULL;
514          }          }
515          mutex_unlock(&ccs_policy_lock);          mutex_unlock(&ccs_policy_lock);
# Line 480  static void ccs_check_profile(void) Line 528  static void ccs_check_profile(void)
528          struct ccs_domain_info *domain;          struct ccs_domain_info *domain;
529          const int idx = ccs_read_lock();          const int idx = ccs_read_lock();
530          ccs_policy_loaded = true;          ccs_policy_loaded = true;
531            printk(KERN_INFO "CCSecurity: 1.8.3   2011/09/29\n");
532          list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {          list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
533                  const u8 profile = domain->profile;                  const u8 profile = domain->profile;
534                  if (ccs_profile_ptr[profile])                  const struct ccs_policy_namespace *ns = domain->ns;
535                    if (ns->profile_version != 20100903)
536                            printk(KERN_ERR
537                                   "Profile version %u is not supported.\n",
538                                   ns->profile_version);
539                    else if (!ns->profile_ptr[profile])
540                            printk(KERN_ERR
541                                   "Profile %u (used by '%s') is not defined.\n",
542                                   profile, domain->domainname->name);
543                    else
544                          continue;                          continue;
545                  printk(KERN_ERR "Profile %u must be defined before using it.\n",                  printk(KERN_ERR
546                         profile);                         "Userland tools for TOMOYO 1.8 must be installed and "
547                           "policy must be initialized.\n");
548                  printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/1.8/ "                  printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/1.8/ "
549                         "for more information.\n");                         "for more information.\n");
550                  panic("Profile %u (used by '%s') not defined.\n",                  panic("STOP!");
                       profile, domain->domainname->name);  
551          }          }
552          ccs_read_unlock(idx);          ccs_read_unlock(idx);
         if (ccs_profile_version != 20100903) {  
                 printk(KERN_ERR "Userland tools must be installed for "  
                        "TOMOYO 1.8, and policy must be initialized.\n");  
                 printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/1.8/ "  
                        "for more information.\n");  
                 panic("Profile version %u is not supported.\n",  
                       ccs_profile_version);  
         }  
         printk(KERN_INFO "CCSecurity: 1.8.1   2011/04/01\n");  
553          printk(KERN_INFO "Mandatory Access Control activated.\n");          printk(KERN_INFO "Mandatory Access Control activated.\n");
554  }  }
555    
# Line 514  static void ccs_check_profile(void) Line 563  static void ccs_check_profile(void)
563  struct ccs_profile *ccs_profile(const u8 profile)  struct ccs_profile *ccs_profile(const u8 profile)
564  {  {
565          static struct ccs_profile ccs_null_profile;          static struct ccs_profile ccs_null_profile;
566          struct ccs_profile *ptr = ccs_profile_ptr[profile];          struct ccs_profile *ptr = ccs_current_namespace()->
567                    profile_ptr[profile];
568          if (!ptr)          if (!ptr)
569                  ptr = &ccs_null_profile;                  ptr = &ccs_null_profile;
570          return ptr;          return ptr;
# Line 648  static int ccs_write_profile(struct ccs_ Line 698  static int ccs_write_profile(struct ccs_
698          unsigned int i;          unsigned int i;
699          char *cp;          char *cp;
700          struct ccs_profile *profile;          struct ccs_profile *profile;
701          if (sscanf(data, "PROFILE_VERSION=%u", &ccs_profile_version) == 1)          if (sscanf(data, "PROFILE_VERSION=%u", &head->w.ns->profile_version)
702                == 1)
703                  return 0;                  return 0;
704          i = simple_strtoul(data, &cp, 10);          i = simple_strtoul(data, &cp, 10);
705          if (*cp != '-')          if (*cp != '-')
706                  return -EINVAL;                  return -EINVAL;
707          data = cp + 1;          data = cp + 1;
708          profile = ccs_assign_profile(i);          profile = ccs_assign_profile(head->w.ns, i);
709          if (!profile)          if (!profile)
710                  return -EINVAL;                  return -EINVAL;
711          cp = strchr(data, '=');          cp = strchr(data, '=');
# Line 711  static void ccs_print_config(struct ccs_ Line 762  static void ccs_print_config(struct ccs_
762  static void ccs_read_profile(struct ccs_io_buffer *head)  static void ccs_read_profile(struct ccs_io_buffer *head)
763  {  {
764          u8 index;          u8 index;
765            struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
766                                                           namespace_list);
767          const struct ccs_profile *profile;          const struct ccs_profile *profile;
768            if (head->r.eof)
769                    return;
770  next:  next:
771          index = head->r.index;          index = head->r.index;
772          profile = ccs_profile_ptr[index];          profile = ns->profile_ptr[index];
773          switch (head->r.step) {          switch (head->r.step) {
774          case 0:          case 0:
775                  ccs_io_printf(head, "PROFILE_VERSION=%u\n", 20100903);                  ccs_print_namespace(head);
776                    ccs_io_printf(head, "PROFILE_VERSION=%u\n",
777                                  ns->profile_version);
778                  head->r.step++;                  head->r.step++;
779                  break;                  break;
780          case 1:          case 1:
781                  for ( ; head->r.index < CCS_MAX_PROFILES;                  for ( ; head->r.index < CCS_MAX_PROFILES; head->r.index++)
782                        head->r.index++)                          if (ns->profile_ptr[head->r.index])
                         if (ccs_profile_ptr[head->r.index])  
783                                  break;                                  break;
784                  if (head->r.index == CCS_MAX_PROFILES)                  if (head->r.index == CCS_MAX_PROFILES) {
785                            head->r.eof = true;
786                          return;                          return;
787                    }
788                  head->r.step++;                  head->r.step++;
789                  break;                  break;
790          case 2:          case 2:
791                  {                  {
792                          u8 i;                          u8 i;
793                          const struct ccs_path_info *comment = profile->comment;                          const struct ccs_path_info *comment = profile->comment;
794                            ccs_print_namespace(head);
795                          ccs_io_printf(head, "%u-COMMENT=", index);                          ccs_io_printf(head, "%u-COMMENT=", index);
796                          ccs_set_string(head, comment ? comment->name : "");                          ccs_set_string(head, comment ? comment->name : "");
797                          ccs_set_lf(head);                          ccs_set_lf(head);
798                            ccs_print_namespace(head);
799                          ccs_io_printf(head, "%u-PREFERENCE={ ", index);                          ccs_io_printf(head, "%u-PREFERENCE={ ", index);
800                          for (i = 0; i < CCS_MAX_PREF; i++)                          for (i = 0; i < CCS_MAX_PREF; i++)
801                                  ccs_io_printf(head, "%s=%u ",                                  ccs_io_printf(head, "%s=%u ",
802                                                ccs_pref_keywords[i],                                                ccs_pref_keywords[i],
803                                                profile->pref[i]);                                                profile->pref[i]);
804                          ccs_set_string(head, " }\n");                          ccs_set_string(head, "}\n");
805                          head->r.step++;                          head->r.step++;
806                  }                  }
807                  break;                  break;
808          case 3:          case 3:
809                  {                  {
810                            ccs_print_namespace(head);
811                          ccs_io_printf(head, "%u-%s", index, "CONFIG");                          ccs_io_printf(head, "%u-%s", index, "CONFIG");
812                          ccs_print_config(head, profile->default_config);                          ccs_print_config(head, profile->default_config);
813                          head->r.bit = 0;                          head->r.bit = 0;
# Line 760  next: Line 821  next:
821                          const u8 config = profile->config[i];                          const u8 config = profile->config[i];
822                          if (config == CCS_CONFIG_USE_DEFAULT)                          if (config == CCS_CONFIG_USE_DEFAULT)
823                                  continue;                                  continue;
824                            ccs_print_namespace(head);
825                          if (i < CCS_MAX_MAC_INDEX)                          if (i < CCS_MAX_MAC_INDEX)
826                                  ccs_io_printf(head, "%u-CONFIG::%s::%s", index,                                  ccs_io_printf(head, "%u-CONFIG::%s::%s", index,
827                                                ccs_category_keywords                                                ccs_category_keywords
# Line 806  static bool ccs_same_manager(const struc Line 868  static bool ccs_same_manager(const struc
868   *   *
869   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
870   */   */
871  static int ccs_update_manager_entry(const char *manager, const bool is_delete)  static inline int ccs_update_manager_entry(const char *manager,
872                                               const bool is_delete)
873  {  {
874          struct ccs_manager e = { };          struct ccs_manager e = { };
875            struct ccs_acl_param param = {
876                    /* .ns = &ccs_kernel_namespace, */
877                    .is_delete = is_delete,
878                    .list = &ccs_kernel_namespace.policy_list[CCS_ID_MANAGER],
879            };
880          int error = is_delete ? -ENOENT : -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
881          if (ccs_domain_def(manager)) {          if (ccs_domain_def(manager)) {
882                  if (!ccs_correct_domain(manager))                  if (!ccs_correct_domain(manager))
# Line 819  static int ccs_update_manager_entry(cons Line 887  static int ccs_update_manager_entry(cons
887                          return -EINVAL;                          return -EINVAL;
888          }          }
889          e.manager = ccs_get_name(manager);          e.manager = ccs_get_name(manager);
890          if (!e.manager)          if (e.manager) {
891                  return error;                  error = ccs_update_policy(&e.head, sizeof(e), &param,
892          error = ccs_update_policy(&e.head, sizeof(e), is_delete,                                            ccs_same_manager);
893                                    &ccs_policy_list[CCS_ID_MANAGER],                  ccs_put_name(e.manager);
894                                    ccs_same_manager);          }
         ccs_put_name(e.manager);  
895          return error;          return error;
896  }  }
897    
# Line 837  static int ccs_update_manager_entry(cons Line 904  static int ccs_update_manager_entry(cons
904   */   */
905  static int ccs_write_manager(struct ccs_io_buffer *head)  static int ccs_write_manager(struct ccs_io_buffer *head)
906  {  {
907          char *data = head->write_buf;          const char *data = head->write_buf;
         bool is_delete = ccs_str_starts(&data, "delete ");  
908          if (!strcmp(data, "manage_by_non_root")) {          if (!strcmp(data, "manage_by_non_root")) {
909                  ccs_manage_by_non_root = !is_delete;                  ccs_manage_by_non_root = !head->w.is_delete;
910                  return 0;                  return 0;
911          }          }
912          return ccs_update_manager_entry(data, is_delete);          return ccs_update_manager_entry(data, head->w.is_delete);
913  }  }
914    
915  /**  /**
# Line 859  static void ccs_read_manager(struct ccs_ Line 925  static void ccs_read_manager(struct ccs_
925  {  {
926          if (head->r.eof)          if (head->r.eof)
927                  return;                  return;
928          list_for_each_cookie(head->r.acl, &ccs_policy_list[CCS_ID_MANAGER]) {          list_for_each_cookie(head->r.acl, &ccs_kernel_namespace.
929                                 policy_list[CCS_ID_MANAGER]) {
930                  struct ccs_manager *ptr =                  struct ccs_manager *ptr =
931                          list_entry(head->r.acl, typeof(*ptr), head.list);                          list_entry(head->r.acl, typeof(*ptr), head.list);
932                  if (ptr->head.is_deleted)                  if (ptr->head.is_deleted)
# Line 895  static bool ccs_manager(void) Line 962  static bool ccs_manager(void)
962          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))
963                  return false;                  return false;
964          exe = ccs_get_exe();          exe = ccs_get_exe();
965          list_for_each_entry_srcu(ptr, &ccs_policy_list[CCS_ID_MANAGER],          list_for_each_entry_srcu(ptr, &ccs_kernel_namespace.
966                                   head.list, &ccs_ss) {                                   policy_list[CCS_ID_MANAGER], head.list,
967                                     &ccs_ss) {
968                  if (ptr->head.is_deleted)                  if (ptr->head.is_deleted)
969                          continue;                          continue;
970                  if (ptr->is_domain) {                  if (ptr->is_domain) {
# Line 925  static bool ccs_manager(void) Line 993  static bool ccs_manager(void)
993  }  }
994    
995  /**  /**
996   * ccs_select_one - Parse select command.   * ccs_select_domain - Parse select command.
997   *   *
998   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
999   * @data: String to parse.   * @data: String to parse.
# Line 934  static bool ccs_manager(void) Line 1002  static bool ccs_manager(void)
1002   *   *
1003   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1004   */   */
1005  static bool ccs_select_one(struct ccs_io_buffer *head, const char *data)  static bool ccs_select_domain(struct ccs_io_buffer *head, const char *data)
1006  {  {
1007          unsigned int pid;          unsigned int pid;
1008          struct ccs_domain_info *domain = NULL;          struct ccs_domain_info *domain = NULL;
1009          bool global_pid = false;          bool global_pid = false;
1010          if (!strcmp(data, "transition_only")) {          if (strncmp(data, "select ", 7))
1011                  head->r.print_transition_related_only = true;                  return false;
1012                  return true;          data += 7;
         }  
1013          if (sscanf(data, "pid=%u", &pid) == 1 ||          if (sscanf(data, "pid=%u", &pid) == 1 ||
1014              (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {              (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
1015                  struct task_struct *p;                  struct task_struct *p;
# Line 960  static bool ccs_select_one(struct ccs_io Line 1027  static bool ccs_select_one(struct ccs_io
1027                          domain = ccs_task_domain(p);                          domain = ccs_task_domain(p);
1028                  ccs_tasklist_unlock();                  ccs_tasklist_unlock();
1029          } else if (!strncmp(data, "domain=", 7)) {          } else if (!strncmp(data, "domain=", 7)) {
1030                  if (ccs_domain_def(data + 7))                  if (*(data + 7) == '<')
1031                          domain = ccs_find_domain(data + 7);                          domain = ccs_find_domain(data + 7);
1032          } else          } else
1033                  return false;                  return false;
# Line 1018  static bool ccs_same_task_acl(const stru Line 1085  static bool ccs_same_task_acl(const stru
1085   * @param: Pointer to "struct ccs_acl_param".   * @param: Pointer to "struct ccs_acl_param".
1086   *   *
1087   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1088     *
1089     * Caller holds ccs_read_lock().
1090   */   */
1091  static int ccs_write_task(struct ccs_acl_param *param)  static int ccs_write_task(struct ccs_acl_param *param)
1092  {  {
# Line 1066  static int ccs_write_task(struct ccs_acl Line 1135  static int ccs_write_task(struct ccs_acl
1135  /**  /**
1136   * ccs_write_domain2 - Write domain policy.   * ccs_write_domain2 - Write domain policy.
1137   *   *
1138     * @ns:        Pointer to "struct ccs_policy_namespace".
1139     * @list:      Pointer to "struct list_head".
1140   * @data:      Policy to be interpreted.   * @data:      Policy to be interpreted.
  * @domain:    Pointer to "struct ccs_domain_info".  
1141   * @is_delete: True if it is a delete request.   * @is_delete: True if it is a delete request.
1142   *   *
1143   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1144     *
1145     * Caller holds ccs_read_lock().
1146   */   */
1147  static int ccs_write_domain2(char *data, struct ccs_domain_info *domain,  static int ccs_write_domain2(struct ccs_policy_namespace *ns,
1148                                 struct list_head *list, char *data,
1149                               const bool is_delete)                               const bool is_delete)
1150  {  {
1151          struct ccs_acl_param param = {          struct ccs_acl_param param = {
1152                    .ns = ns,
1153                    .list = list,
1154                  .data = data,                  .data = data,
                 .domain = domain,  
1155                  .is_delete = is_delete,                  .is_delete = is_delete,
1156          };          };
1157          static const struct {          static const struct {
# Line 1089  static int ccs_write_domain2(char *data, Line 1163  static int ccs_write_domain2(char *data,
1163                  { "network unix ", ccs_write_unix_network },                  { "network unix ", ccs_write_unix_network },
1164                  { "misc ", ccs_write_misc },                  { "misc ", ccs_write_misc },
1165                  { "capability ", ccs_write_capability },                  { "capability ", ccs_write_capability },
1166                  { "ipc ", ccs_write_ipc },                  { "ipc signal ", ccs_write_ipc },
1167                  { "task ", ccs_write_task },                  { "task ", ccs_write_task },
1168          };          };
1169          u8 i;          u8 i;
1170          for (i = 0; i < 7; i++) {          for (i = 0; i < ARRAY_SIZE(ccs_callback); i++) {
1171                  if (!ccs_str_starts(&param.data, ccs_callback[i].keyword))                  if (!ccs_str_starts(&param.data, ccs_callback[i].keyword))
1172                          continue;                          continue;
1173                  return ccs_callback[i].write(&param);                  return ccs_callback[i].write(&param);
# Line 1101  static int ccs_write_domain2(char *data, Line 1175  static int ccs_write_domain2(char *data,
1175          return -EINVAL;          return -EINVAL;
1176  }  }
1177    
1178    /**
1179     * ccs_delete_domain - Delete a domain.
1180     *
1181     * @domainname: The name of domain.
1182     *
1183     * Returns 0.
1184     */
1185    static int ccs_delete_domain(char *domainname)
1186    {
1187            struct ccs_domain_info *domain;
1188            struct ccs_path_info name;
1189            name.name = domainname;
1190            ccs_fill_path_info(&name);
1191            if (mutex_lock_interruptible(&ccs_policy_lock))
1192                    return 0;
1193            /* Is there an active domain? */
1194            list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
1195                    /* Never delete ccs_kernel_domain. */
1196                    if (domain == &ccs_kernel_domain)
1197                            continue;
1198                    if (domain->is_deleted ||
1199                        ccs_pathcmp(domain->domainname, &name))
1200                            continue;
1201                    domain->is_deleted = true;
1202                    break;
1203            }
1204            mutex_unlock(&ccs_policy_lock);
1205            return 0;
1206    }
1207    
1208  /* String table for domain flags. */  /* String table for domain flags. */
1209  const char * const ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = {  const char * const ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = {
1210          [CCS_DIF_QUOTA_WARNED]      = "quota_exceeded\n",          [CCS_DIF_QUOTA_WARNED]      = "quota_exceeded\n",
# Line 1113  const char * const ccs_dif[CCS_MAX_DOMAI Line 1217  const char * const ccs_dif[CCS_MAX_DOMAI
1217   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1218   *   *
1219   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1220     *
1221     * Caller holds ccs_read_lock().
1222   */   */
1223  static int ccs_write_domain(struct ccs_io_buffer *head)  static int ccs_write_domain(struct ccs_io_buffer *head)
1224  {  {
1225          char *data = head->write_buf;          char *data = head->write_buf;
1226            struct ccs_policy_namespace *ns;
1227          struct ccs_domain_info *domain = head->w.domain;          struct ccs_domain_info *domain = head->w.domain;
1228          bool is_delete = false;          const bool is_delete = head->w.is_delete;
1229          bool is_select = false;          const bool is_select = !is_delete && ccs_str_starts(&data, "select ");
1230          unsigned int profile;          unsigned int profile;
1231          if (ccs_str_starts(&data, "delete "))          if (*data == '<') {
                 is_delete = true;  
         else if (ccs_str_starts(&data, "select "))  
                 is_select = true;  
         if (is_select && ccs_select_one(head, data))  
                 return -EAGAIN;  
         /* Don't allow updating policies by non manager programs. */  
         if (!ccs_manager())  
                 return -EPERM;  
         if (ccs_domain_def(data)) {  
1232                  domain = NULL;                  domain = NULL;
1233                  if (is_delete)                  if (is_delete)
1234                          ccs_delete_domain(data);                          ccs_delete_domain(data);
1235                  else if (is_select)                  else if (is_select)
1236                          domain = ccs_find_domain(data);                          domain = ccs_find_domain(data);
1237                  else                  else
1238                          domain = ccs_assign_domain(data, 0, 0, false);                          domain = ccs_assign_domain(data, false);
1239                  head->w.domain = domain;                  head->w.domain = domain;
1240                  return 0;                  return 0;
1241          }          }
1242          if (!domain)          if (!domain)
1243                  return -EINVAL;                  return -EINVAL;
1244            ns = domain->ns;
1245          if (sscanf(data, "use_profile %u\n", &profile) == 1          if (sscanf(data, "use_profile %u\n", &profile) == 1
1246              && profile < CCS_MAX_PROFILES) {              && profile < CCS_MAX_PROFILES) {
1247                  if (!ccs_policy_loaded || ccs_profile_ptr[(u8) profile])                  if (!ccs_policy_loaded || ns->profile_ptr[(u8) profile])
1248                          if (!is_delete)                          if (!is_delete)
1249                                  domain->profile = (u8) profile;                                  domain->profile = (u8) profile;
1250                  return 0;                  return 0;
# Line 1164  static int ccs_write_domain(struct ccs_i Line 1262  static int ccs_write_domain(struct ccs_i
1262                  domain->flags[profile] = !is_delete;                  domain->flags[profile] = !is_delete;
1263                  return 0;                  return 0;
1264          }          }
1265          return ccs_write_domain2(data, domain, is_delete);          return ccs_write_domain2(ns, &domain->acl_info_list, data, is_delete);
1266  }  }
1267    
1268  /**  /**
# Line 1178  static int ccs_write_domain(struct ccs_i Line 1276  static int ccs_write_domain(struct ccs_i
1276  static void ccs_print_name_union(struct ccs_io_buffer *head,  static void ccs_print_name_union(struct ccs_io_buffer *head,
1277                                   const struct ccs_name_union *ptr)                                   const struct ccs_name_union *ptr)
1278  {  {
1279          const bool cond = head->r.print_cond_part;          ccs_set_space(head);
1280          if (!cond)          if (ptr->group) {
                 ccs_set_space(head);  
         if (ptr->is_group) {  
1281                  ccs_set_string(head, "@");                  ccs_set_string(head, "@");
1282                  ccs_set_string(head, ptr->group->group_name->name);                  ccs_set_string(head, ptr->group->group_name->name);
1283          } else {          } else {
                 if (cond)  
                         ccs_set_string(head, "\"");  
1284                  ccs_set_string(head, ptr->filename->name);                  ccs_set_string(head, ptr->filename->name);
                 if (cond)  
                         ccs_set_string(head, "\"");  
1285          }          }
1286  }  }
1287    
1288  /**  /**
1289   * ccs_print_number_union - Print a ccs_number_union.   * ccs_print_name_union_quoted - Print a ccs_name_union with a quote.
1290     *
1291     * @head: Pointer to "struct ccs_io_buffer".
1292     * @ptr:  Pointer to "struct ccs_name_union".
1293     *
1294     * Returns nothing.
1295     */
1296    static void ccs_print_name_union_quoted(struct ccs_io_buffer *head,
1297                                            const struct ccs_name_union *ptr)
1298    {
1299            if (ptr->group) {
1300                    ccs_set_string(head, "@");
1301                    ccs_set_string(head, ptr->group->group_name->name);
1302            } else {
1303                    ccs_set_string(head, "\"");
1304                    ccs_set_string(head, ptr->filename->name);
1305                    ccs_set_string(head, "\"");
1306            }
1307    }
1308    
1309    /**
1310     * ccs_print_number_union_nospace - Print a ccs_number_union without a space.
1311   *   *
1312   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1313   * @ptr:  Pointer to "struct ccs_number_union".   * @ptr:  Pointer to "struct ccs_number_union".
1314   *   *
1315   * Returns nothing.   * Returns nothing.
1316   */   */
1317  static void ccs_print_number_union(struct ccs_io_buffer *head,  static void ccs_print_number_union_nospace(struct ccs_io_buffer *head,
1318                                     const struct ccs_number_union *ptr)                                             const struct ccs_number_union *ptr)
1319  {  {
1320          if (!head->r.print_cond_part)          if (ptr->group) {
                 ccs_set_space(head);  
         if (ptr->is_group) {  
1321                  ccs_set_string(head, "@");                  ccs_set_string(head, "@");
1322                  ccs_set_string(head, ptr->group->group_name->name);                  ccs_set_string(head, ptr->group->group_name->name);
1323          } else {          } else {
# Line 1243  static void ccs_print_number_union(struc Line 1354  static void ccs_print_number_union(struc
1354  }  }
1355    
1356  /**  /**
1357     * ccs_print_number_union - Print a ccs_number_union.
1358     *
1359     * @head: Pointer to "struct ccs_io_buffer".
1360     * @ptr:  Pointer to "struct ccs_number_union".
1361     *
1362     * Returns nothing.
1363     */
1364    static void ccs_print_number_union(struct ccs_io_buffer *head,
1365                                       const struct ccs_number_union *ptr)
1366    {
1367            ccs_set_space(head);
1368            ccs_print_number_union_nospace(head, ptr);
1369    }
1370    
1371    /**
1372   * ccs_print_condition - Print condition part.   * ccs_print_condition - Print condition part.
1373   *   *
1374   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
# Line 1257  static bool ccs_print_condition(struct c Line 1383  static bool ccs_print_condition(struct c
1383          case 0:          case 0:
1384                  head->r.cond_index = 0;                  head->r.cond_index = 0;
1385                  head->r.cond_step++;                  head->r.cond_step++;
1386                    if (cond->transit && cond->exec_transit) {
1387                            ccs_set_space(head);
1388                            ccs_set_string(head, cond->transit->name);
1389                    }
1390                  /* fall through */                  /* fall through */
1391          case 1:          case 1:
1392                  {                  {
# Line 1309  static bool ccs_print_condition(struct c Line 1439  static bool ccs_print_condition(struct c
1439                                  switch (left) {                                  switch (left) {
1440                                  case CCS_ARGV_ENTRY:                                  case CCS_ARGV_ENTRY:
1441                                          ccs_io_printf(head,                                          ccs_io_printf(head,
1442                                                        "exec.argv[%u]%s\"%s\"",                                                        "exec.argv[%lu]%s=\"",
1443                                                        argv->index,                                                        argv->index,
1444                                                        argv->is_not ?                                                        argv->is_not ? "!" : "");
1445                                                        "!=" : "=",                                          ccs_set_string(head,
1446                                                        argv->value->name);                                                         argv->value->name);
1447                                            ccs_set_string(head, "\"");
1448                                          argv++;                                          argv++;
1449                                          continue;                                          continue;
1450                                  case CCS_ENVP_ENTRY:                                  case CCS_ENVP_ENTRY:
1451                                          ccs_io_printf(head,                                          ccs_set_string(head, "exec.envp[\"");
1452                                                        "exec.envp[\"%s\"]%s",                                          ccs_set_string(head, envp->name->name);
1453                                                        envp->name->name,                                          ccs_io_printf(head, "\"]%s=",
1454                                                        envp->is_not ?                                                        envp->is_not ? "!" : "");
                                                       "!=" : "=");  
1455                                          if (envp->value) {                                          if (envp->value) {
1456                                                  ccs_set_string(head, "\"");                                                  ccs_set_string(head, "\"");
1457                                                  ccs_set_string(head, envp->                                                  ccs_set_string(head, envp->
# Line 1333  static bool ccs_print_condition(struct c Line 1463  static bool ccs_print_condition(struct c
1463                                          envp++;                                          envp++;
1464                                          continue;                                          continue;
1465                                  case CCS_NUMBER_UNION:                                  case CCS_NUMBER_UNION:
1466                                          ccs_print_number_union(head,                                          ccs_print_number_union_nospace
1467                                                                 numbers_p++);                                                  (head, numbers_p++);
1468                                          break;                                          break;
1469                                  default:                                  default:
1470                                          ccs_set_string(head,                                          ccs_set_string(head,
# Line 1344  static bool ccs_print_condition(struct c Line 1474  static bool ccs_print_condition(struct c
1474                                  ccs_set_string(head, match ? "=" : "!=");                                  ccs_set_string(head, match ? "=" : "!=");
1475                                  switch (right) {                                  switch (right) {
1476                                  case CCS_NAME_UNION:                                  case CCS_NAME_UNION:
1477                                          ccs_print_name_union(head, names_p++);                                          ccs_print_name_union_quoted
1478                                                    (head, names_p++);
1479                                          break;                                          break;
1480                                  case CCS_NUMBER_UNION:                                  case CCS_NUMBER_UNION:
1481                                          ccs_print_number_union(head,                                          ccs_print_number_union_nospace
1482                                                                 numbers_p++);                                                  (head, numbers_p++);
1483                                          break;                                          break;
1484                                  default:                                  default:
1485                                          ccs_set_string(head,                                          ccs_set_string(head,
# Line 1369  static bool ccs_print_condition(struct c Line 1500  static bool ccs_print_condition(struct c
1500                          ccs_io_printf(head, " grant_log=%s",                          ccs_io_printf(head, " grant_log=%s",
1501                                        ccs_yesno(cond->grant_log ==                                        ccs_yesno(cond->grant_log ==
1502                                                  CCS_GRANTLOG_YES));                                                  CCS_GRANTLOG_YES));
1503                  if (cond->transit) {                  if (cond->transit && !cond->exec_transit) {
1504                            const char *name = cond->transit->name;
1505                          ccs_set_string(head, " auto_domain_transition=\"");                          ccs_set_string(head, " auto_domain_transition=\"");
1506                          ccs_set_string(head, cond->transit->name);                          ccs_set_string(head, name);
1507                          ccs_set_string(head, "\"");                          ccs_set_string(head, "\"");
1508                  }                  }
1509                  ccs_set_lf(head);                  ccs_set_lf(head);
# Line 1390  static bool ccs_print_condition(struct c Line 1522  static bool ccs_print_condition(struct c
1522   */   */
1523  static void ccs_set_group(struct ccs_io_buffer *head, const char *category)  static void ccs_set_group(struct ccs_io_buffer *head, const char *category)
1524  {  {
1525          if (head->type == CCS_EXCEPTIONPOLICY)          if (head->type == CCS_EXCEPTIONPOLICY) {
1526                    ccs_print_namespace(head);
1527                  ccs_io_printf(head, "acl_group %u ", head->r.acl_group_index);                  ccs_io_printf(head, "acl_group %u ", head->r.acl_group_index);
1528            }
1529          ccs_set_string(head, category);          ccs_set_string(head, category);
1530  }  }
1531    
# Line 1552  static bool ccs_print_entry(struct ccs_i Line 1686  static bool ccs_print_entry(struct ccs_i
1686                  if (first)                  if (first)
1687                          return true;                          return true;
1688                  ccs_set_space(head);                  ccs_set_space(head);
1689                  switch (ptr->address_type) {                  if (ptr->address.group) {
                         char buf[128];  
                 case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP:  
1690                          ccs_set_string(head, "@");                          ccs_set_string(head, "@");
1691                          ccs_set_string(head,                          ccs_set_string(head,
1692                                         ptr->address.group->group_name->name);                                         ptr->address.group->group_name->name);
1693                          break;                  } else {
1694                  case CCS_IP_ADDRESS_TYPE_IPv4:                          char buf[128];
1695                          ccs_print_ipv4(buf, sizeof(buf), ptr->address.ipv4.min,                          ccs_print_ip(buf, sizeof(buf), &ptr->address);
                                        ptr->address.ipv4.max);  
                         ccs_io_printf(head, "%s", buf);  
                         break;  
                 case CCS_IP_ADDRESS_TYPE_IPv6:  
                         ccs_print_ipv6(buf, sizeof(buf), ptr->address.ipv6.min,  
                                        ptr->address.ipv6.max);  
1696                          ccs_io_printf(head, "%s", buf);                          ccs_io_printf(head, "%s", buf);
                         break;  
1697                  }                  }
1698                  ccs_print_number_union(head, &ptr->port);                  ccs_print_number_union(head, &ptr->port);
1699          } else if (acl_type == CCS_TYPE_UNIX_ACL) {          } else if (acl_type == CCS_TYPE_UNIX_ACL) {
# Line 1596  static bool ccs_print_entry(struct ccs_i Line 1721  static bool ccs_print_entry(struct ccs_i
1721                  struct ccs_signal_acl *ptr =                  struct ccs_signal_acl *ptr =
1722                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1723                  ccs_set_group(head, "ipc signal ");                  ccs_set_group(head, "ipc signal ");
1724                  ccs_io_printf(head, "%u ", ptr->sig);                  ccs_print_number_union_nospace(head, &ptr->sig);
1725                    ccs_set_space(head);
1726                  ccs_set_string(head, ptr->domainname->name);                  ccs_set_string(head, ptr->domainname->name);
1727          } else if (acl_type == CCS_TYPE_MOUNT_ACL) {          } else if (acl_type == CCS_TYPE_MOUNT_ACL) {
1728                  struct ccs_mount_acl *ptr =                  struct ccs_mount_acl *ptr =
# Line 1625  print_cond_part: Line 1751  print_cond_part:
1751  /**  /**
1752   * ccs_read_domain2 - Read domain policy.   * ccs_read_domain2 - Read domain policy.
1753   *   *
1754   * @head:   Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1755   * @domain: Pointer to "struct ccs_domain_info".   * @list: Pointer to "struct list_head".
  * @index:  Index number.  
1756   *   *
1757   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1758   *   *
1759   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1760   */   */
1761  static bool ccs_read_domain2(struct ccs_io_buffer *head,  static bool ccs_read_domain2(struct ccs_io_buffer *head,
1762                               struct ccs_domain_info *domain,                               struct list_head *list)
                              const u8 index)  
1763  {  {
1764          list_for_each_cookie(head->r.acl, &domain->acl_info_list[index]) {          list_for_each_cookie(head->r.acl, list) {
1765                  struct ccs_acl_info *ptr =                  struct ccs_acl_info *ptr =
1766                          list_entry(head->r.acl, typeof(*ptr), list);                          list_entry(head->r.acl, typeof(*ptr), list);
1767                  if (!ccs_print_entry(head, ptr))                  if (!ccs_print_entry(head, ptr))
# Line 1682  static void ccs_read_domain(struct ccs_i Line 1806  static void ccs_read_domain(struct ccs_i
1806                          ccs_set_lf(head);                          ccs_set_lf(head);
1807                          /* fall through */                          /* fall through */
1808                  case 1:                  case 1:
1809                          if (!ccs_read_domain2(head, domain, 0))                          if (!ccs_read_domain2(head, &domain->acl_info_list))
                                 return;  
                         head->r.step++;  
                         /* fall through */  
                 case 2:  
                         if (!ccs_read_domain2(head, domain, 1))  
1810                                  return;                                  return;
1811                          head->r.step++;                          head->r.step++;
1812                          if (!ccs_set_lf(head))                          if (!ccs_set_lf(head))
1813                                  return;                                  return;
1814                          /* fall through */                          /* fall through */
1815                  case 3:                  case 2:
1816                          head->r.step = 0;                          head->r.step = 0;
1817                          if (head->r.print_this_domain_only)                          if (head->r.print_this_domain_only)
1818                                  goto done;                                  goto done;
# Line 1704  done: Line 1823  done:
1823  }  }
1824    
1825  /**  /**
  * ccs_write_domain_profile - Assign profile for specified domain.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  *  
  * Returns 0 on success, -EINVAL otherwise.  
  *  
  * This is equivalent to doing  
  *  
  *     ( echo "select " $domainname; echo "use_profile " $profile ) |  
  *     /usr/sbin/ccs-loadpolicy -d  
  *  
  * Caller holds ccs_read_lock().  
  */  
 static int ccs_write_domain_profile(struct ccs_io_buffer *head)  
 {  
         char *data = head->write_buf;  
         char *cp = strchr(data, ' ');  
         struct ccs_domain_info *domain;  
         unsigned int profile;  
         if (!cp)  
                 return -EINVAL;  
         *cp = '\0';  
         profile = simple_strtoul(data, NULL, 10);  
         if (profile >= CCS_MAX_PROFILES)  
                 return -EINVAL;  
         domain = ccs_find_domain(cp + 1);  
         if (domain && (!ccs_policy_loaded || ccs_profile_ptr[(u8) profile]))  
                 domain->profile = (u8) profile;  
         return 0;  
 }  
   
 /**  
  * ccs_read_domain_profile - Read only domainname and profile.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  *  
  * Returns nothing.  
  *  
  * This is equivalent to doing  
  *  
  *     grep -A 1 '^<kernel>' /proc/ccs/domain_policy |  
  *     awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )  
  *     domainname = $0; } else if ( $1 == "use_profile" ) {  
  *     print $2 " " domainname; domainname = ""; } } ; '  
  *  
  * Caller holds ccs_read_lock().  
  */  
 static void ccs_read_domain_profile(struct ccs_io_buffer *head)  
 {  
         if (head->r.eof)  
                 return;  
         list_for_each_cookie(head->r.domain, &ccs_domain_list) {  
                 struct ccs_domain_info *domain =  
                         list_entry(head->r.domain, typeof(*domain), list);  
                 if (domain->is_deleted)  
                         continue;  
                 if (!ccs_flush(head))  
                         return;  
                 ccs_io_printf(head, "%u ", domain->profile);  
                 ccs_set_string(head, domain->domainname->name);  
                 ccs_set_lf(head);  
         }  
         head->r.eof = true;  
 }  
   
 /**  
1826   * ccs_write_pid - Specify PID to obtain domainname.   * ccs_write_pid - Specify PID to obtain domainname.
1827   *   *
1828   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
# Line 1845  static void ccs_read_pid(struct ccs_io_b Line 1898  static void ccs_read_pid(struct ccs_io_b
1898    
1899  /* String table for domain transition control keywords. */  /* String table for domain transition control keywords. */
1900  static const char * const ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {  static const char * const ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {
1901            [CCS_TRANSITION_CONTROL_NO_RESET]      = "no_reset_domain ",
1902            [CCS_TRANSITION_CONTROL_RESET]         = "reset_domain ",
1903          [CCS_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ",          [CCS_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ",
1904          [CCS_TRANSITION_CONTROL_INITIALIZE]    = "initialize_domain ",          [CCS_TRANSITION_CONTROL_INITIALIZE]    = "initialize_domain ",
1905          [CCS_TRANSITION_CONTROL_NO_KEEP]       = "no_keep_domain ",          [CCS_TRANSITION_CONTROL_NO_KEEP]       = "no_keep_domain ",
# Line 1867  static const char * const ccs_group_name Line 1922  static const char * const ccs_group_name
1922   */   */
1923  static int ccs_write_exception(struct ccs_io_buffer *head)  static int ccs_write_exception(struct ccs_io_buffer *head)
1924  {  {
1925          char *data = head->write_buf;          const bool is_delete = head->w.is_delete;
1926          const bool is_delete = ccs_str_starts(&data, "delete ");          struct ccs_acl_param param = {
1927          u8 i;                  .ns = head->w.ns,
1928          static const struct {                  .is_delete = is_delete,
1929                  const char *keyword;                  .data = head->write_buf,
                 int (*write) (char *, const bool);  
         } ccs_callback[2] = {  
                 { "aggregator ",    ccs_write_aggregator },  
                 { "deny_autobind ", ccs_write_reserved_port },  
1930          };          };
1931          if (!is_delete && ccs_str_starts(&data, "select ") &&          u8 i;
1932              !strcmp(data, "transition_only")) {          if (ccs_str_starts(&param.data, "aggregator "))
1933                  head->r.print_transition_related_only = true;                  return ccs_write_aggregator(&param);
1934                  return -EAGAIN;          if (ccs_str_starts(&param.data, "deny_autobind "))
1935          }                  return ccs_write_reserved_port(&param);
         /* Don't allow updating policies by non manager programs. */  
         if (!ccs_manager())  
                 return -EPERM;  
         for (i = 0; i < 2; i++)  
                 if (ccs_str_starts(&data, ccs_callback[i].keyword))  
                         return ccs_callback[i].write(data, is_delete);  
1936          for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)          for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)
1937                  if (ccs_str_starts(&data, ccs_transition_type[i]))                  if (ccs_str_starts(&param.data, ccs_transition_type[i]))
1938                          return ccs_write_transition_control(data, is_delete,                          return ccs_write_transition_control(&param, i);
                                                             i);  
1939          for (i = 0; i < CCS_MAX_GROUP; i++)          for (i = 0; i < CCS_MAX_GROUP; i++)
1940                  if (ccs_str_starts(&data, ccs_group_name[i]))                  if (ccs_str_starts(&param.data, ccs_group_name[i]))
1941                          return ccs_write_group(data, is_delete, i);                          return ccs_write_group(&param, i);
1942          if (ccs_str_starts(&data, "acl_group ")) {          if (ccs_str_starts(&param.data, "acl_group ")) {
1943                  unsigned int group;                  unsigned int group;
1944                  if (sscanf(data, "%u", &group) == 1 &&                  char *data;
1945                      group < CCS_MAX_ACL_GROUPS) {                  group = simple_strtoul(param.data, &data, 10);
1946                          data = strchr(data, ' ');                  if (group < CCS_MAX_ACL_GROUPS && *data++ == ' ')
1947                          if (data)                          return ccs_write_domain2(head->w.ns,
1948                                  return ccs_write_domain2(data + 1,                                                   &head->w.ns->acl_group[group],
1949                                                           &ccs_acl_group[group],                                                   data, is_delete);
                                                          is_delete);  
                 }  
1950          }          }
1951          return -EINVAL;          return -EINVAL;
1952  }  }
# Line 1921  static int ccs_write_exception(struct cc Line 1963  static int ccs_write_exception(struct cc
1963   */   */
1964  static bool ccs_read_group(struct ccs_io_buffer *head, const int idx)  static bool ccs_read_group(struct ccs_io_buffer *head, const int idx)
1965  {  {
1966          list_for_each_cookie(head->r.group, &ccs_group_list[idx]) {          struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
1967                                                           namespace_list);
1968            struct list_head *list = &ns->group_list[idx];
1969            list_for_each_cookie(head->r.group, list) {
1970                  struct ccs_group *group =                  struct ccs_group *group =
1971                          list_entry(head->r.group, typeof(*group), head.list);                          list_entry(head->r.group, typeof(*group), head.list);
1972                  list_for_each_cookie(head->r.acl, &group->member_list) {                  list_for_each_cookie(head->r.acl, &group->member_list) {
# Line 1931  static bool ccs_read_group(struct ccs_io Line 1976  static bool ccs_read_group(struct ccs_io
1976                                  continue;                                  continue;
1977                          if (!ccs_flush(head))                          if (!ccs_flush(head))
1978                                  return false;                                  return false;
1979                            ccs_print_namespace(head);
1980                          ccs_set_string(head, ccs_group_name[idx]);                          ccs_set_string(head, ccs_group_name[idx]);
1981                          ccs_set_string(head, group->group_name->name);                          ccs_set_string(head, group->group_name->name);
1982                          if (idx == CCS_PATH_GROUP) {                          if (idx == CCS_PATH_GROUP) {
# Line 1947  static bool ccs_read_group(struct ccs_io Line 1993  static bool ccs_read_group(struct ccs_io
1993                                  struct ccs_address_group *member =                                  struct ccs_address_group *member =
1994                                          container_of(ptr, typeof(*member),                                          container_of(ptr, typeof(*member),
1995                                                       head);                                                       head);
1996                                  if (member->is_ipv6)                                  ccs_print_ip(buffer, sizeof(buffer),
1997                                          ccs_print_ipv6(buffer, sizeof(buffer),                                               &member->address);
                                                        member->min.ipv6,  
                                                        member->max.ipv6);  
                                 else  
                                         ccs_print_ipv4(buffer, sizeof(buffer),  
                                                        member->min.ipv4,  
                                                        member->max.ipv4);  
1998                                  ccs_io_printf(head, " %s", buffer);                                  ccs_io_printf(head, " %s", buffer);
1999                          }                          }
2000                          ccs_set_lf(head);                          ccs_set_lf(head);
# Line 1977  static bool ccs_read_group(struct ccs_io Line 2017  static bool ccs_read_group(struct ccs_io
2017   */   */
2018  static bool ccs_read_policy(struct ccs_io_buffer *head, const int idx)  static bool ccs_read_policy(struct ccs_io_buffer *head, const int idx)
2019  {  {
2020          list_for_each_cookie(head->r.acl, &ccs_policy_list[idx]) {          struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
2021                                                           namespace_list);
2022            struct list_head *list = &ns->policy_list[idx];
2023            list_for_each_cookie(head->r.acl, list) {
2024                  struct ccs_acl_head *acl =                  struct ccs_acl_head *acl =
2025                          container_of(head->r.acl, typeof(*acl), list);                          container_of(head->r.acl, typeof(*acl), list);
2026                  if (acl->is_deleted)                  if (acl->is_deleted)
# Line 1992  static bool ccs_read_policy(struct ccs_i Line 2035  static bool ccs_read_policy(struct ccs_i
2035                          {                          {
2036                                  struct ccs_transition_control *ptr =                                  struct ccs_transition_control *ptr =
2037                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
2038                                    ccs_print_namespace(head);
2039                                  ccs_set_string(head,                                  ccs_set_string(head,
2040                                                 ccs_transition_type[ptr->type]);                                                 ccs_transition_type[ptr->type]);
2041                                  ccs_set_string(head, ptr->program ?                                  ccs_set_string(head, ptr->program ?
# Line 2005  static bool ccs_read_policy(struct ccs_i Line 2049  static bool ccs_read_policy(struct ccs_i
2049                          {                          {
2050                                  struct ccs_aggregator *ptr =                                  struct ccs_aggregator *ptr =
2051                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
2052                                    ccs_print_namespace(head);
2053                                  ccs_set_string(head, "aggregator ");                                  ccs_set_string(head, "aggregator ");
2054                                  ccs_set_string(head, ptr->original_name->name);                                  ccs_set_string(head, ptr->original_name->name);
2055                                  ccs_set_space(head);                                  ccs_set_space(head);
# Line 2016  static bool ccs_read_policy(struct ccs_i Line 2061  static bool ccs_read_policy(struct ccs_i
2061                          {                          {
2062                                  struct ccs_reserved *ptr =                                  struct ccs_reserved *ptr =
2063                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
2064                                  const u16 min_port = ptr->min_port;                                  ccs_print_namespace(head);
                                 const u16 max_port = ptr->max_port;  
2065                                  ccs_set_string(head, "deny_autobind ");                                  ccs_set_string(head, "deny_autobind ");
2066                                  ccs_io_printf(head, "%u", min_port);                                  ccs_print_number_union_nospace(head,
2067                                  if (min_port != max_port)                                                                 &ptr->port);
                                         ccs_io_printf(head, "-%u", max_port);  
2068                          }                          }
2069                          break;                          break;
2070                  default:                  default:
# Line 2044  static bool ccs_read_policy(struct ccs_i Line 2087  static bool ccs_read_policy(struct ccs_i
2087   */   */
2088  static void ccs_read_exception(struct ccs_io_buffer *head)  static void ccs_read_exception(struct ccs_io_buffer *head)
2089  {  {
2090            struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
2091                                                           namespace_list);
2092          if (head->r.eof)          if (head->r.eof)
2093                  return;                  return;
2094          while (head->r.step < CCS_MAX_POLICY &&          while (head->r.step < CCS_MAX_POLICY &&
# Line 2057  static void ccs_read_exception(struct cc Line 2102  static void ccs_read_exception(struct cc
2102          if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP)          if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP)
2103                  return;                  return;
2104          while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP          while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP
2105                 + CCS_MAX_ACL_GROUPS * 2) {                 + CCS_MAX_ACL_GROUPS) {
2106                  head->r.acl_group_index = (head->r.step - CCS_MAX_POLICY                  head->r.acl_group_index =
2107                                             - CCS_MAX_GROUP) / 2;                          head->r.step - CCS_MAX_POLICY - CCS_MAX_GROUP;
2108                  if (!ccs_read_domain2(head,                  if (!ccs_read_domain2(head, &ns->acl_group
2109                                        &ccs_acl_group[head->r.acl_group_index],                                        [head->r.acl_group_index]))
                                       head->r.step & 1))  
2110                          return;                          return;
2111                  head->r.step++;                  head->r.step++;
2112          }          }
# Line 2165  static void ccs_add_entry(char *header) Line 2209  static void ccs_add_entry(char *header)
2209          if (symlink)          if (symlink)
2210                  ccs_addprintf(buffer, len, "%s", symlink);                  ccs_addprintf(buffer, len, "%s", symlink);
2211          ccs_normalize_line(buffer);          ccs_normalize_line(buffer);
2212          if (!ccs_write_domain2(buffer, ccs_current_domain(), false))          {
2213                  ccs_update_stat(CCS_STAT_POLICY_UPDATES);                  struct ccs_domain_info *domain = ccs_current_domain();
2214                    if (!ccs_write_domain2(domain->ns, &domain->acl_info_list,
2215                                           buffer, false))
2216                            ccs_update_stat(CCS_STAT_POLICY_UPDATES);
2217            }
2218          kfree(buffer);          kfree(buffer);
2219  }  }
2220    
# Line 2367  static void ccs_read_query(struct ccs_io Line 2415  static void ccs_read_query(struct ccs_io
2415                   * can change, but I don't care.                   * can change, but I don't care.
2416                   */                   */
2417                  if (len == ptr->query_len)                  if (len == ptr->query_len)
2418                          snprintf(buf, len + 32, "Q%u-%hu\n%s", ptr->serial,                          snprintf(buf, len + 31, "Q%u-%hu\n%s", ptr->serial,
2419                                   ptr->retry, ptr->query);                                   ptr->retry, ptr->query);
2420                  break;                  break;
2421          }          }
# Line 2427  static void ccs_read_version(struct ccs_ Line 2475  static void ccs_read_version(struct ccs_
2475  {  {
2476          if (head->r.eof)          if (head->r.eof)
2477                  return;                  return;
2478          ccs_set_string(head, "1.8.1");          ccs_set_string(head, "1.8.3");
2479          head->r.eof = true;          head->r.eof = true;
2480  }  }
2481    
# Line 2441  static const char * const ccs_policy_hea Line 2489  static const char * const ccs_policy_hea
2489    
2490  /* String table for /proc/ccs/stat interface. */  /* String table for /proc/ccs/stat interface. */
2491  static const char * const ccs_memory_headers[CCS_MAX_MEMORY_STAT] = {  static const char * const ccs_memory_headers[CCS_MAX_MEMORY_STAT] = {
2492          [CCS_MEMORY_POLICY] = "policy:",          [CCS_MEMORY_POLICY]     = "policy:",
2493          [CCS_MEMORY_AUDIT]  = "audit log:",          [CCS_MEMORY_AUDIT]      = "audit log:",
2494          [CCS_MEMORY_QUERY]  = "query message:",          [CCS_MEMORY_QUERY]      = "query message:",
2495  };  };
2496    
2497  /* Timestamp counter for last updated. */  /* Timestamp counter for last updated. */
# Line 2523  static int ccs_write_stat(struct ccs_io_ Line 2571  static int ccs_write_stat(struct ccs_io_
2571          u8 i;          u8 i;
2572          if (ccs_str_starts(&data, "Memory used by "))          if (ccs_str_starts(&data, "Memory used by "))
2573                  for (i = 0; i < CCS_MAX_MEMORY_STAT; i++)                  for (i = 0; i < CCS_MAX_MEMORY_STAT; i++)
2574                          if (ccs_str_starts(&data, ccs_memory_headers[i]))                          if (ccs_str_starts(&data, ccs_memory_headers[i])) {
2575                                  sscanf(data, "%u", &ccs_memory_quota[i]);                                  if (*data == ' ')
2576                                            data++;
2577                                    ccs_memory_quota[i] =
2578                                            simple_strtoul(data, NULL, 10);
2579                            }
2580          return 0;          return 0;
2581  }  }
2582    
# Line 2543  int ccs_open_control(const u8 type, stru Line 2595  int ccs_open_control(const u8 type, stru
2595                  return -ENOMEM;                  return -ENOMEM;
2596          mutex_init(&head->io_sem);          mutex_init(&head->io_sem);
2597          head->type = type;          head->type = type;
2598          switch (type) {          if (type == CCS_EXECUTE_HANDLER) {
         case CCS_DOMAINPOLICY: /* /proc/ccs/domain_policy */  
                 head->write = ccs_write_domain;  
                 head->read = ccs_read_domain;  
                 break;  
         case CCS_EXCEPTIONPOLICY: /* /proc/ccs/exception_policy */  
                 head->write = ccs_write_exception;  
                 head->read = ccs_read_exception;  
                 break;  
         case CCS_AUDIT: /* /proc/ccs/audit */  
                 head->poll = ccs_poll_log;  
                 head->read = ccs_read_log;  
                 break;  
         case CCS_DOMAIN_STATUS: /* /proc/ccs/.domain_status */  
                 head->write = ccs_write_domain_profile;  
                 head->read = ccs_read_domain_profile;  
                 break;  
         case CCS_EXECUTE_HANDLER: /* /proc/ccs/.execute_handler */  
2599                  /* Allow execute_handler to read process's status. */                  /* Allow execute_handler to read process's status. */
2600                  if (!(ccs_current_flags() & CCS_TASK_IS_EXECUTE_HANDLER)) {                  if (!(ccs_current_flags() & CCS_TASK_IS_EXECUTE_HANDLER)) {
2601                          kfree(head);                          kfree(head);
2602                          return -EPERM;                          return -EPERM;
2603                  }                  }
                 /* fall through */  
         case CCS_PROCESS_STATUS: /* /proc/ccs/.process_status */  
                 head->write = ccs_write_pid;  
                 head->read = ccs_read_pid;  
                 break;  
         case CCS_VERSION: /* /proc/ccs/version */  
                 head->read = ccs_read_version;  
                 head->readbuf_size = 128;  
                 break;  
         case CCS_STAT: /* /proc/ccs/stat */  
                 head->write = ccs_write_stat;  
                 head->read = ccs_read_stat;  
                 head->readbuf_size = 1024;  
                 break;  
         case CCS_PROFILE: /* /proc/ccs/profile */  
                 head->write = ccs_write_profile;  
                 head->read = ccs_read_profile;  
                 break;  
         case CCS_QUERY: /* /proc/ccs/query */  
                 head->poll = ccs_poll_query;  
                 head->write = ccs_write_answer;  
                 head->read = ccs_read_query;  
                 break;  
         case CCS_MANAGER: /* /proc/ccs/manager */  
                 head->write = ccs_write_manager;  
                 head->read = ccs_read_manager;  
                 break;  
2604          }          }
2605          if (!(file->f_mode & FMODE_READ)) {          if ((file->f_mode & FMODE_READ) && type != CCS_AUDIT &&
2606                  /*              type != CCS_QUERY) {
                  * No need to allocate read_buf since it is not opened  
                  * for reading.  
                  */  
                 head->read = NULL;  
                 head->poll = NULL;  
         } else if (!head->poll) {  
2607                  /* Don't allocate read_buf for poll() access. */                  /* Don't allocate read_buf for poll() access. */
2608                  if (!head->readbuf_size)                  head->readbuf_size = 4096;
                         head->readbuf_size = 4096;  
2609                  head->read_buf = kzalloc(head->readbuf_size, CCS_GFP_FLAGS);                  head->read_buf = kzalloc(head->readbuf_size, CCS_GFP_FLAGS);
2610                  if (!head->read_buf) {                  if (!head->read_buf) {
2611                          kfree(head);                          kfree(head);
2612                          return -ENOMEM;                          return -ENOMEM;
2613                  }                  }
2614          }          }
2615          if (!(file->f_mode & FMODE_WRITE)) {          if (file->f_mode & FMODE_WRITE) {
                 /*  
                  * No need to allocate write_buf since it is not opened  
                  * for writing.  
                  */  
                 head->write = NULL;  
         } else if (head->write) {  
2616                  head->writebuf_size = 4096;                  head->writebuf_size = 4096;
2617                  head->write_buf = kzalloc(head->writebuf_size, CCS_GFP_FLAGS);                  head->write_buf = kzalloc(head->writebuf_size, CCS_GFP_FLAGS);
2618                  if (!head->write_buf) {                  if (!head->write_buf) {
# Line 2653  int ccs_open_control(const u8 type, stru Line 2648  int ccs_open_control(const u8 type, stru
2648  int ccs_poll_control(struct file *file, poll_table *wait)  int ccs_poll_control(struct file *file, poll_table *wait)
2649  {  {
2650          struct ccs_io_buffer *head = file->private_data;          struct ccs_io_buffer *head = file->private_data;
2651          if (!head->poll)          switch (head->type) {
2652            case CCS_AUDIT:
2653                    return ccs_poll_log(file, wait);
2654            case CCS_QUERY:
2655                    return ccs_poll_query(file, wait);
2656            default:
2657                  return -ENOSYS;                  return -ENOSYS;
2658          return head->poll(file, wait);          }
2659    }
2660    
2661    /**
2662     * ccs_set_namespace_cursor - Set namespace to read.
2663     *
2664     * @head: Pointer to "struct ccs_io_buffer".
2665     *
2666     * Returns nothing.
2667     */
2668    static inline void ccs_set_namespace_cursor(struct ccs_io_buffer *head)
2669    {
2670            struct list_head *ns;
2671            if (head->type != CCS_EXCEPTIONPOLICY && head->type != CCS_PROFILE)
2672                    return;
2673            /*
2674             * If this is the first read, or reading previous namespace finished
2675             * and has more namespaces to read, update the namespace cursor.
2676             */
2677            ns = head->r.ns;
2678            if (!ns || (head->r.eof && ns->next != &ccs_namespace_list)) {
2679                    /* Clearing is OK because ccs_flush() returned true. */
2680                    memset(&head->r, 0, sizeof(head->r));
2681                    head->r.ns = ns ? ns->next : ccs_namespace_list.next;
2682            }
2683    }
2684    
2685    /**
2686     * ccs_has_more_namespace - Check for unread namespaces.
2687     *
2688     * @head: Pointer to "struct ccs_io_buffer".
2689     *
2690     * Returns true if we have more entries to print, false otherwise.
2691     */
2692    static inline bool ccs_has_more_namespace(struct ccs_io_buffer *head)
2693    {
2694            return (head->type == CCS_EXCEPTIONPOLICY ||
2695                    head->type == CCS_PROFILE) && head->r.eof &&
2696                    head->r.ns->next != &ccs_namespace_list;
2697  }  }
2698    
2699  /**  /**
2700   * ccs_read_control - read() for /proc/ccs/ interface.   * ccs_read_control - read() for /proc/ccs/ interface.
2701   *   *
2702   * @file:       Pointer to "struct file".   * @head:       Pointer to "struct ccs_io_buffer".
2703   * @buffer:     Poiner to buffer to write to.   * @buffer:     Poiner to buffer to write to.
2704   * @buffer_len: Size of @buffer.   * @buffer_len: Size of @buffer.
2705   *   *
2706   * Returns bytes read on success, negative value otherwise.   * Returns bytes read on success, negative value otherwise.
2707   */   */
2708  ssize_t ccs_read_control(struct file *file, char __user *buffer,  ssize_t ccs_read_control(struct ccs_io_buffer *head, char __user *buffer,
2709                           const size_t buffer_len)                           const size_t buffer_len)
2710  {  {
2711          int len;          int len;
         struct ccs_io_buffer *head = file->private_data;  
2712          int idx;          int idx;
         if (!head->read)  
                 return -ENOSYS;  
2713          if (!access_ok(VERIFY_WRITE, buffer, buffer_len))          if (!access_ok(VERIFY_WRITE, buffer, buffer_len))
2714                  return -EFAULT;                  return -EFAULT;
2715          if (mutex_lock_interruptible(&head->io_sem))          if (mutex_lock_interruptible(&head->io_sem))
# Line 2684  ssize_t ccs_read_control(struct file *fi Line 2719  ssize_t ccs_read_control(struct file *fi
2719          idx = ccs_read_lock();          idx = ccs_read_lock();
2720          if (ccs_flush(head))          if (ccs_flush(head))
2721                  /* Call the policy handler. */                  /* Call the policy handler. */
2722                  head->read(head);                  do {
2723          ccs_flush(head);                          ccs_set_namespace_cursor(head);
2724                            switch (head->type) {
2725                            case CCS_DOMAINPOLICY:
2726                                    ccs_read_domain(head);
2727                                    break;
2728                            case CCS_EXCEPTIONPOLICY:
2729                                    ccs_read_exception(head);
2730                                    break;
2731                            case CCS_AUDIT:
2732                                    ccs_read_log(head);
2733                                    break;
2734                            case CCS_EXECUTE_HANDLER:
2735                            case CCS_PROCESS_STATUS:
2736                                    ccs_read_pid(head);
2737                                    break;
2738                            case CCS_VERSION:
2739                                    ccs_read_version(head);
2740                                    break;
2741                            case CCS_STAT:
2742                                    ccs_read_stat(head);
2743                                    break;
2744                            case CCS_PROFILE:
2745                                    ccs_read_profile(head);
2746                                    break;
2747                            case CCS_QUERY:
2748                                    ccs_read_query(head);
2749                                    break;
2750                            case CCS_MANAGER:
2751                                    ccs_read_manager(head);
2752                                    break;
2753                            }
2754                    } while (ccs_flush(head) && ccs_has_more_namespace(head));
2755          ccs_read_unlock(idx);          ccs_read_unlock(idx);
2756          len = head->read_user_buf - buffer;          len = head->read_user_buf - buffer;
2757          mutex_unlock(&head->io_sem);          mutex_unlock(&head->io_sem);
# Line 2693  ssize_t ccs_read_control(struct file *fi Line 2759  ssize_t ccs_read_control(struct file *fi
2759  }  }
2760    
2761  /**  /**
2762     * ccs_parse_policy - Parse a policy line.
2763     *
2764     * @head: Poiter to "struct ccs_io_buffer".
2765     * @line: Line to parse.
2766     *
2767     * Returns 0 on success, negative value otherwise.
2768     *
2769     * Caller holds ccs_read_lock().
2770     */
2771    static int ccs_parse_policy(struct ccs_io_buffer *head, char *line)
2772    {
2773            /* Delete request? */
2774            head->w.is_delete = !strncmp(line, "delete ", 7);
2775            if (head->w.is_delete)
2776                    memmove(line, line + 7, strlen(line + 7) + 1);
2777            /* Selecting namespace to update. */
2778            if (head->type == CCS_EXCEPTIONPOLICY || head->type == CCS_PROFILE) {
2779                    if (*line == '<') {
2780                            char *cp = strchr(line, ' ');
2781                            if (cp) {
2782                                    *cp++ = '\0';
2783                                    head->w.ns = ccs_assign_namespace(line);
2784                                    memmove(line, cp, strlen(cp) + 1);
2785                            } else
2786                                    head->w.ns = NULL;
2787                    } else
2788                            head->w.ns = &ccs_kernel_namespace;
2789                    /* Don't allow updating if namespace is invalid. */
2790                    if (!head->w.ns)
2791                            return -ENOENT;
2792            }
2793            /* Do the update. */
2794            switch (head->type) {
2795            case CCS_DOMAINPOLICY:
2796                    return ccs_write_domain(head);
2797            case CCS_EXCEPTIONPOLICY:
2798                    return ccs_write_exception(head);
2799            case CCS_EXECUTE_HANDLER:
2800            case CCS_PROCESS_STATUS:
2801                    return ccs_write_pid(head);
2802            case CCS_STAT:
2803                    return ccs_write_stat(head);
2804            case CCS_PROFILE:
2805                    return ccs_write_profile(head);
2806            case CCS_QUERY:
2807                    return ccs_write_answer(head);
2808            case CCS_MANAGER:
2809                    return ccs_write_manager(head);
2810            default:
2811                    return -ENOSYS;
2812            }
2813    }
2814    
2815    /**
2816   * ccs_write_control - write() for /proc/ccs/ interface.   * ccs_write_control - write() for /proc/ccs/ interface.
2817   *   *
2818   * @file:       Pointer to "struct file".   * @head:       Pointer to "struct ccs_io_buffer".
2819   * @buffer:     Pointer to buffer to read from.   * @buffer:     Pointer to buffer to read from.
2820   * @buffer_len: Size of @buffer.   * @buffer_len: Size of @buffer.
2821   *   *
2822   * Returns @buffer_len on success, negative value otherwise.   * Returns @buffer_len on success, negative value otherwise.
2823   */   */
2824  ssize_t ccs_write_control(struct file *file, const char __user *buffer,  ssize_t ccs_write_control(struct ccs_io_buffer *head,
2825                            const size_t buffer_len)                            const char __user *buffer, const size_t buffer_len)
2826  {  {
         struct ccs_io_buffer *head = file->private_data;  
2827          int error = buffer_len;          int error = buffer_len;
2828          size_t avail_len = buffer_len;          size_t avail_len = buffer_len;
2829          char *cp0 = head->write_buf;          char *cp0 = head->write_buf;
2830          int idx;          int idx;
         if (!head->write)  
                 return -ENOSYS;  
2831          if (!access_ok(VERIFY_READ, buffer, buffer_len))          if (!access_ok(VERIFY_READ, buffer, buffer_len))
2832                  return -EFAULT;                  return -EFAULT;
2833          if (mutex_lock_interruptible(&head->io_sem))          if (mutex_lock_interruptible(&head->io_sem))
2834                  return -EINTR;                  return -EINTR;
2835          idx = ccs_read_lock();          idx = ccs_read_lock();
         /* Don't allow updating policies by non manager programs. */  
         if (head->write != ccs_write_pid && head->write != ccs_write_domain &&  
             head->write != ccs_write_exception && !ccs_manager()) {  
                 ccs_read_unlock(idx);  
                 mutex_unlock(&head->io_sem);  
                 return -EPERM;  
         }  
2836          /* Read a line and dispatch it to the policy handler. */          /* Read a line and dispatch it to the policy handler. */
2837          while (avail_len > 0) {          while (avail_len > 0) {
2838                  char c;                  char c;
# Line 2751  ssize_t ccs_write_control(struct file *f Line 2861  ssize_t ccs_write_control(struct file *f
2861                  cp0[head->w.avail - 1] = '\0';                  cp0[head->w.avail - 1] = '\0';
2862                  head->w.avail = 0;                  head->w.avail = 0;
2863                  ccs_normalize_line(cp0);                  ccs_normalize_line(cp0);
2864                  {                  if (!strcmp(cp0, "reset")) {
2865                          const int ret = head->write(head);                          head->w.ns = &ccs_kernel_namespace;
2866                          if (ret == -EPERM) {                          head->w.domain = NULL;
2867                                  error = -EPERM;                          memset(&head->r, 0, sizeof(head->r));
2868                                  break;                          continue;
                         }  
                         if (ret)  
                                 continue;  
2869                  }                  }
2870                    /* Don't allow updating policies by non manager programs. */
2871                  switch (head->type) {                  switch (head->type) {
2872                    case CCS_PROCESS_STATUS:
2873                            /* This does not write anything. */
2874                            break;
2875                  case CCS_DOMAINPOLICY:                  case CCS_DOMAINPOLICY:
2876                            if (ccs_select_domain(head, cp0))
2877                                    continue;
2878                            /* fall through */
2879                  case CCS_EXCEPTIONPOLICY:                  case CCS_EXCEPTIONPOLICY:
2880                  case CCS_DOMAIN_STATUS:                          if (!strcmp(cp0, "select transition_only")) {
2881                  case CCS_STAT:                                  head->r.print_transition_related_only = true;
2882                  case CCS_PROFILE:                                  continue;
2883                  case CCS_MANAGER:                          }
2884                          ccs_update_stat(CCS_STAT_POLICY_UPDATES);                          /* fall through */
                         break;  
2885                  default:                  default:
2886                            if (!ccs_manager()) {
2887                                    error = -EPERM;
2888                                    goto out;
2889                            }
2890                    }
2891                    switch (ccs_parse_policy(head, cp0)) {
2892                    case -EPERM:
2893                            error = -EPERM;
2894                            goto out;
2895                    case 0:
2896                            /* Update statistics. */
2897                            switch (head->type) {
2898                            case CCS_DOMAINPOLICY:
2899                            case CCS_EXCEPTIONPOLICY:
2900                            case CCS_STAT:
2901                            case CCS_PROFILE:
2902                            case CCS_MANAGER:
2903                                    ccs_update_stat(CCS_STAT_POLICY_UPDATES);
2904                                    break;
2905                            default:
2906                                    break;
2907                            }
2908                          break;                          break;
2909                  }                  }
2910          }          }
2911    out:
2912          ccs_read_unlock(idx);          ccs_read_unlock(idx);
2913          mutex_unlock(&head->io_sem);          mutex_unlock(&head->io_sem);
2914          return error;          return error;
# Line 2781  ssize_t ccs_write_control(struct file *f Line 2917  ssize_t ccs_write_control(struct file *f
2917  /**  /**
2918   * ccs_close_control - close() for /proc/ccs/ interface.   * ccs_close_control - close() for /proc/ccs/ interface.
2919   *   *
2920   * @file: Pointer to "struct file".   * @head: Pointer to "struct ccs_io_buffer".
2921   *   *
2922   * Returns 0.   * Returns 0.
2923   */   */
2924  int ccs_close_control(struct file *file)  int ccs_close_control(struct ccs_io_buffer *head)
2925  {  {
         struct ccs_io_buffer *head = file->private_data;  
         file->private_data = NULL;  
2926          /*          /*
2927           * If the file is /proc/ccs/query, decrement the observer counter.           * If the file is /proc/ccs/query, decrement the observer counter.
2928           */           */
# Line 2809  void __init ccs_policy_io_init(void) Line 2943  void __init ccs_policy_io_init(void)
2943          ccsecurity_ops.check_profile = ccs_check_profile;          ccsecurity_ops.check_profile = ccs_check_profile;
2944  }  }
2945    
 #ifdef CONFIG_CCSECURITY_USE_BUILTIN_POLICY  
2946  /**  /**
2947   * ccs_load_builtin_policy - Load built-in policy.   * ccs_load_builtin_policy - Load built-in policy.
2948   *   *
# Line 2824  void __init ccs_load_builtin_policy(void Line 2957  void __init ccs_load_builtin_policy(void
2957           * "ccs_builtin_stat" in the form of "static char [] __initdata".           * "ccs_builtin_stat" in the form of "static char [] __initdata".
2958           */           */
2959  #include "builtin-policy.h"  #include "builtin-policy.h"
         struct ccs_io_buffer head;  
2960          u8 i;          u8 i;
2961          const int idx = ccs_read_lock();          const int idx = ccs_read_lock();
2962          for (i = 0; i < 5; i++) {          for (i = 0; i < 5; i++) {
2963                    struct ccs_io_buffer head = { };
2964                  char *start = "";                  char *start = "";
                 memset(&head, 0, sizeof(head));  
2965                  switch (i) {                  switch (i) {
2966                  case 0:                  case 0:
2967                          start = ccs_builtin_profile;                          start = ccs_builtin_profile;
2968                          head.write = ccs_write_profile;                          head.type = CCS_PROFILE;
2969                          break;                          break;
2970                  case 1:                  case 1:
2971                          start = ccs_builtin_exception_policy;                          start = ccs_builtin_exception_policy;
2972                          head.write = ccs_write_exception;                          head.type = CCS_EXCEPTIONPOLICY;
2973                          break;                          break;
2974                  case 2:                  case 2:
2975                          start = ccs_builtin_domain_policy;                          start = ccs_builtin_domain_policy;
2976                          head.write = ccs_write_domain;                          head.type = CCS_DOMAINPOLICY;
2977                          break;                          break;
2978                  case 3:                  case 3:
2979                          start = ccs_builtin_manager;                          start = ccs_builtin_manager;
2980                          head.write = ccs_write_manager;                          head.type = CCS_MANAGER;
2981                          break;                          break;
2982                  case 4:                  case 4:
2983                          start = ccs_builtin_stat;                          start = ccs_builtin_stat;
2984                          head.write = ccs_write_stat;                          head.type = CCS_STAT;
2985                          break;                          break;
2986                  }                  }
2987                  while (1) {                  while (1) {
# Line 2859  void __init ccs_load_builtin_policy(void Line 2991  void __init ccs_load_builtin_policy(void
2991                          *end = '\0';                          *end = '\0';
2992                          ccs_normalize_line(start);                          ccs_normalize_line(start);
2993                          head.write_buf = start;                          head.write_buf = start;
2994                          head.write(&head);                          ccs_parse_policy(&head, start);
2995                          start = end + 1;                          start = end + 1;
2996                  }                  }
2997          }          }
2998          ccs_read_unlock(idx);          ccs_read_unlock(idx);
2999  #ifdef CONFIG_CCSECURITY_ACTIVATE_FROM_THE_BEGINNING  #ifdef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
3000          ccs_check_profile();          ccs_check_profile();
3001  #endif  #endif
3002  }  }
 #endif  

Legend:
Removed from v.4806  
changed lines
  Added in v.5526

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