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

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 4280 by kumaneko, Fri Dec 31 02:05:48 2010 UTC revision 5559 by kumaneko, Mon Oct 24 12:02:23 2011 UTC
# Line 1  Line 1 
1  /*  /*
2   * security/ccsecurity/policy_io.c   * security/ccsecurity/policy_io.c
3   *   *
4   * Copyright (C) 2005-2010  NTT DATA CORPORATION   * Copyright (C) 2005-2011  NTT DATA CORPORATION
5   *   *
6   * Version: 1.8.0+   2010/12/31   * 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 277  const char *ccs_yesno(const unsigned int Line 280  const char *ccs_yesno(const unsigned int
280          return value ? "yes" : "no";          return value ? "yes" : "no";
281  }  }
282    
283  /* Prototype fpr ccs_addprintf(). */  /* Prototype for ccs_addprintf(). */
284  static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)  static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
285          __attribute__ ((format(printf, 3, 4)));          __attribute__ ((format(printf, 3, 4)));
286    
# Line 310  static bool ccs_flush(struct ccs_io_buff Line 313  static bool ccs_flush(struct ccs_io_buff
313  {  {
314          while (head->r.w_pos) {          while (head->r.w_pos) {
315                  const char *w = head->r.w[0];                  const char *w = head->r.w[0];
316                  int len = strlen(w);                  size_t len = strlen(w);
317                  if (len) {                  if (len) {
318                          if (len > head->read_user_buf_avail)                          if (len > head->read_user_buf_avail)
319                                  len = head->read_user_buf_avail;                                  len = head->read_user_buf_avail;
# Line 322  static bool ccs_flush(struct ccs_io_buff Line 325  static bool ccs_flush(struct ccs_io_buff
325                          head->read_user_buf += len;                          head->read_user_buf += len;
326                          w += len;                          w += len;
327                  }                  }
328                  if (*w) {                  head->r.w[0] = w;
329                          head->r.w[0] = 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 363  static void ccs_set_string(struct ccs_io Line 365  static void ccs_set_string(struct ccs_io
365                  printk(KERN_WARNING "Too many words in a line.\n");                  printk(KERN_WARNING "Too many words in a line.\n");
366  }  }
367    
368    /* Prototype for ccs_io_printf(). */
369    static void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
370            __attribute__ ((format(printf, 2, 3)));
371    
372  /**  /**
373   * ccs_io_printf - printf() to "struct ccs_io_buffer" structure.   * ccs_io_printf - printf() to "struct ccs_io_buffer" structure.
374   *   *
# Line 371  static void ccs_set_string(struct ccs_io Line 377  static void ccs_set_string(struct ccs_io
377   *   *
378   * Returns nothing.   * Returns nothing.
379   */   */
380  void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)  static void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
381  {  {
382          va_list args;          va_list args;
383          int len;          size_t len;
384          int pos = head->r.avail;          size_t pos = head->r.avail;
385          int size = head->readbuf_size - pos;          int size = head->readbuf_size - pos;
386          if (size <= 0)          if (size <= 0)
387                  return;                  return;
# Line 416  static bool ccs_set_lf(struct ccs_io_buf Line 422  static bool ccs_set_lf(struct ccs_io_buf
422  }  }
423    
424  /**  /**
425     * ccs_set_slash - Put a shash to "struct ccs_io_buffer" structure.
426     *
427     * @head: Pointer to "struct ccs_io_buffer".
428     *
429     * Returns nothing.
430     */
431    static void ccs_set_slash(struct ccs_io_buffer *head)
432    {
433            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 446  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 465  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.0+   2010/12/31\n");  
553          printk(KERN_INFO "Mandatory Access Control activated.\n");          printk(KERN_INFO "Mandatory Access Control activated.\n");
554  }  }
555    
# Line 499  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 633  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 647  static int ccs_write_profile(struct ccs_ Line 713  static int ccs_write_profile(struct ccs_
713                  return -EINVAL;                  return -EINVAL;
714          *cp++ = '\0';          *cp++ = '\0';
715          if (!strcmp(data, "COMMENT")) {          if (!strcmp(data, "COMMENT")) {
716                  const struct ccs_path_info *old_comment = profile->comment;                  static DEFINE_SPINLOCK(lock);
717                  profile->comment = ccs_get_name(cp);                  const struct ccs_path_info *new_comment = ccs_get_name(cp);
718                    const struct ccs_path_info *old_comment;
719                    if (!new_comment)
720                            return -ENOMEM;
721                    spin_lock(&lock);
722                    old_comment = profile->comment;
723                    profile->comment = new_comment;
724                    spin_unlock(&lock);
725                  ccs_put_name(old_comment);                  ccs_put_name(old_comment);
726                  return 0;                  return 0;
727          }          }
# Line 689  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=%s\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 738  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 784  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 797  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 815  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 837  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 873  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 902  static bool ccs_manager(void) Line 992  static bool ccs_manager(void)
992          return found;          return found;
993  }  }
994    
995    static struct ccs_domain_info *ccs_find_domain_by_qid(unsigned int serial);
996    
997  /**  /**
998   * ccs_select_one - Parse select command.   * ccs_select_domain - Parse select command.
999   *   *
1000   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1001   * @data: String to parse.   * @data: String to parse.
# Line 912  static bool ccs_manager(void) Line 1004  static bool ccs_manager(void)
1004   *   *
1005   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1006   */   */
1007  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)
1008  {  {
1009          unsigned int pid;          unsigned int pid;
1010          struct ccs_domain_info *domain = NULL;          struct ccs_domain_info *domain = NULL;
1011          bool global_pid = false;          bool global_pid = false;
1012          if (!strcmp(data, "execute")) {          if (strncmp(data, "select ", 7))
1013                  head->r.print_execute_only = true;                  return false;
1014                  return true;          data += 7;
         }  
1015          if (sscanf(data, "pid=%u", &pid) == 1 ||          if (sscanf(data, "pid=%u", &pid) == 1 ||
1016              (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {              (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
1017                  struct task_struct *p;                  struct task_struct *p;
# Line 938  static bool ccs_select_one(struct ccs_io Line 1029  static bool ccs_select_one(struct ccs_io
1029                          domain = ccs_task_domain(p);                          domain = ccs_task_domain(p);
1030                  ccs_tasklist_unlock();                  ccs_tasklist_unlock();
1031          } else if (!strncmp(data, "domain=", 7)) {          } else if (!strncmp(data, "domain=", 7)) {
1032                  if (ccs_domain_def(data + 7))                  if (*(data + 7) == '<')
1033                          domain = ccs_find_domain(data + 7);                          domain = ccs_find_domain(data + 7);
1034            } else if (sscanf(data, "Q=%u", &pid) == 1) {
1035                    domain = ccs_find_domain_by_qid(pid);
1036          } else          } else
1037                  return false;                  return false;
1038          head->w.domain = domain;          head->w.domain = domain;
# Line 996  static bool ccs_same_task_acl(const stru Line 1089  static bool ccs_same_task_acl(const stru
1089   * @param: Pointer to "struct ccs_acl_param".   * @param: Pointer to "struct ccs_acl_param".
1090   *   *
1091   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1092     *
1093     * Caller holds ccs_read_lock().
1094   */   */
1095  static int ccs_write_task(struct ccs_acl_param *param)  static int ccs_write_task(struct ccs_acl_param *param)
1096  {  {
# Line 1044  static int ccs_write_task(struct ccs_acl Line 1139  static int ccs_write_task(struct ccs_acl
1139  /**  /**
1140   * ccs_write_domain2 - Write domain policy.   * ccs_write_domain2 - Write domain policy.
1141   *   *
1142     * @ns:        Pointer to "struct ccs_policy_namespace".
1143     * @list:      Pointer to "struct list_head".
1144   * @data:      Policy to be interpreted.   * @data:      Policy to be interpreted.
  * @domain:    Pointer to "struct ccs_domain_info".  
1145   * @is_delete: True if it is a delete request.   * @is_delete: True if it is a delete request.
1146   *   *
1147   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1148     *
1149     * Caller holds ccs_read_lock().
1150   */   */
1151  static int ccs_write_domain2(char *data, struct ccs_domain_info *domain,  static int ccs_write_domain2(struct ccs_policy_namespace *ns,
1152                                 struct list_head *list, char *data,
1153                               const bool is_delete)                               const bool is_delete)
1154  {  {
1155          struct ccs_acl_param param = {          struct ccs_acl_param param = {
1156                    .ns = ns,
1157                    .list = list,
1158                  .data = data,                  .data = data,
                 .domain = domain,  
1159                  .is_delete = is_delete,                  .is_delete = is_delete,
1160          };          };
1161          static const struct {          static const struct {
# Line 1067  static int ccs_write_domain2(char *data, Line 1167  static int ccs_write_domain2(char *data,
1167                  { "network unix ", ccs_write_unix_network },                  { "network unix ", ccs_write_unix_network },
1168                  { "misc ", ccs_write_misc },                  { "misc ", ccs_write_misc },
1169                  { "capability ", ccs_write_capability },                  { "capability ", ccs_write_capability },
1170                  { "ipc ", ccs_write_ipc },                  { "ipc signal ", ccs_write_ipc },
1171                  { "task ", ccs_write_task },                  { "task ", ccs_write_task },
1172          };          };
1173          u8 i;          u8 i;
1174          for (i = 0; i < 7; i++) {          for (i = 0; i < ARRAY_SIZE(ccs_callback); i++) {
1175                  if (!ccs_str_starts(&param.data, ccs_callback[i].keyword))                  if (!ccs_str_starts(&param.data, ccs_callback[i].keyword))
1176                          continue;                          continue;
1177                  return ccs_callback[i].write(&param);                  return ccs_callback[i].write(&param);
# Line 1079  static int ccs_write_domain2(char *data, Line 1179  static int ccs_write_domain2(char *data,
1179          return -EINVAL;          return -EINVAL;
1180  }  }
1181    
1182    /**
1183     * ccs_delete_domain - Delete a domain.
1184     *
1185     * @domainname: The name of domain.
1186     *
1187     * Returns 0.
1188     */
1189    static int ccs_delete_domain(char *domainname)
1190    {
1191            struct ccs_domain_info *domain;
1192            struct ccs_path_info name;
1193            name.name = domainname;
1194            ccs_fill_path_info(&name);
1195            if (mutex_lock_interruptible(&ccs_policy_lock))
1196                    return 0;
1197            /* Is there an active domain? */
1198            list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
1199                    /* Never delete ccs_kernel_domain. */
1200                    if (domain == &ccs_kernel_domain)
1201                            continue;
1202                    if (domain->is_deleted ||
1203                        ccs_pathcmp(domain->domainname, &name))
1204                            continue;
1205                    domain->is_deleted = true;
1206                    break;
1207            }
1208            mutex_unlock(&ccs_policy_lock);
1209            return 0;
1210    }
1211    
1212  /* String table for domain flags. */  /* String table for domain flags. */
1213  const char * const ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = {  const char * const ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = {
1214          [CCS_DIF_QUOTA_WARNED]      = "quota_exceeded\n",          [CCS_DIF_QUOTA_WARNED]      = "quota_exceeded\n",
# Line 1091  const char * const ccs_dif[CCS_MAX_DOMAI Line 1221  const char * const ccs_dif[CCS_MAX_DOMAI
1221   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1222   *   *
1223   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1224     *
1225     * Caller holds ccs_read_lock().
1226   */   */
1227  static int ccs_write_domain(struct ccs_io_buffer *head)  static int ccs_write_domain(struct ccs_io_buffer *head)
1228  {  {
1229          char *data = head->write_buf;          char *data = head->write_buf;
1230            struct ccs_policy_namespace *ns;
1231          struct ccs_domain_info *domain = head->w.domain;          struct ccs_domain_info *domain = head->w.domain;
1232          bool is_delete = false;          const bool is_delete = head->w.is_delete;
1233          bool is_select = false;          const bool is_select = !is_delete && ccs_str_starts(&data, "select ");
1234          unsigned int profile;          unsigned int profile;
1235          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 0;  
         /* Don't allow updating policies by non manager programs. */  
         if (!ccs_manager())  
                 return -EPERM;  
         if (ccs_domain_def(data)) {  
1236                  domain = NULL;                  domain = NULL;
1237                  if (is_delete)                  if (is_delete)
1238                          ccs_delete_domain(data);                          ccs_delete_domain(data);
1239                  else if (is_select)                  else if (is_select)
1240                          domain = ccs_find_domain(data);                          domain = ccs_find_domain(data);
1241                  else                  else
1242                          domain = ccs_assign_domain(data, 0, 0, false);                          domain = ccs_assign_domain(data, false);
1243                  head->w.domain = domain;                  head->w.domain = domain;
1244                  return 0;                  return 0;
1245          }          }
1246          if (!domain)          if (!domain)
1247                  return -EINVAL;                  return -EINVAL;
1248            ns = domain->ns;
1249          if (sscanf(data, "use_profile %u\n", &profile) == 1          if (sscanf(data, "use_profile %u\n", &profile) == 1
1250              && profile < CCS_MAX_PROFILES) {              && profile < CCS_MAX_PROFILES) {
1251                  if (!ccs_policy_loaded || ccs_profile_ptr[(u8) profile])                  if (!ccs_policy_loaded || ns->profile_ptr[(u8) profile])
1252                          if (!is_delete)                          if (!is_delete)
1253                                  domain->profile = (u8) profile;                                  domain->profile = (u8) profile;
1254                  return 0;                  return 0;
# Line 1142  static int ccs_write_domain(struct ccs_i Line 1266  static int ccs_write_domain(struct ccs_i
1266                  domain->flags[profile] = !is_delete;                  domain->flags[profile] = !is_delete;
1267                  return 0;                  return 0;
1268          }          }
1269          return ccs_write_domain2(data, domain, is_delete);          return ccs_write_domain2(ns, &domain->acl_info_list, data, is_delete);
1270  }  }
1271    
1272  /**  /**
# Line 1156  static int ccs_write_domain(struct ccs_i Line 1280  static int ccs_write_domain(struct ccs_i
1280  static void ccs_print_name_union(struct ccs_io_buffer *head,  static void ccs_print_name_union(struct ccs_io_buffer *head,
1281                                   const struct ccs_name_union *ptr)                                   const struct ccs_name_union *ptr)
1282  {  {
1283          const bool cond = head->r.print_cond_part;          ccs_set_space(head);
1284          if (!cond)          if (ptr->group) {
                 ccs_set_space(head);  
         if (ptr->is_group) {  
1285                  ccs_set_string(head, "@");                  ccs_set_string(head, "@");
1286                  ccs_set_string(head, ptr->group->group_name->name);                  ccs_set_string(head, ptr->group->group_name->name);
1287          } else {          } else {
                 if (cond)  
                         ccs_set_string(head, "\"");  
1288                  ccs_set_string(head, ptr->filename->name);                  ccs_set_string(head, ptr->filename->name);
                 if (cond)  
                         ccs_set_string(head, "\"");  
1289          }          }
1290  }  }
1291    
1292  /**  /**
1293   * ccs_print_number_union - Print a ccs_number_union.   * ccs_print_name_union_quoted - Print a ccs_name_union with a quote.
1294     *
1295     * @head: Pointer to "struct ccs_io_buffer".
1296     * @ptr:  Pointer to "struct ccs_name_union".
1297     *
1298     * Returns nothing.
1299     */
1300    static void ccs_print_name_union_quoted(struct ccs_io_buffer *head,
1301                                            const struct ccs_name_union *ptr)
1302    {
1303            if (ptr->group) {
1304                    ccs_set_string(head, "@");
1305                    ccs_set_string(head, ptr->group->group_name->name);
1306            } else {
1307                    ccs_set_string(head, "\"");
1308                    ccs_set_string(head, ptr->filename->name);
1309                    ccs_set_string(head, "\"");
1310            }
1311    }
1312    
1313    /**
1314     * ccs_print_number_union_nospace - Print a ccs_number_union without a space.
1315   *   *
1316   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1317   * @ptr:  Pointer to "struct ccs_number_union".   * @ptr:  Pointer to "struct ccs_number_union".
1318   *   *
1319   * Returns nothing.   * Returns nothing.
1320   */   */
1321  static void ccs_print_number_union(struct ccs_io_buffer *head,  static void ccs_print_number_union_nospace(struct ccs_io_buffer *head,
1322                                     const struct ccs_number_union *ptr)                                             const struct ccs_number_union *ptr)
1323  {  {
1324          if (!head->r.print_cond_part)          if (ptr->group) {
                 ccs_set_space(head);  
         if (ptr->is_group) {  
1325                  ccs_set_string(head, "@");                  ccs_set_string(head, "@");
1326                  ccs_set_string(head, ptr->group->group_name->name);                  ccs_set_string(head, ptr->group->group_name->name);
1327          } else {          } else {
# Line 1221  static void ccs_print_number_union(struc Line 1358  static void ccs_print_number_union(struc
1358  }  }
1359    
1360  /**  /**
1361     * ccs_print_number_union - Print a ccs_number_union.
1362     *
1363     * @head: Pointer to "struct ccs_io_buffer".
1364     * @ptr:  Pointer to "struct ccs_number_union".
1365     *
1366     * Returns nothing.
1367     */
1368    static void ccs_print_number_union(struct ccs_io_buffer *head,
1369                                       const struct ccs_number_union *ptr)
1370    {
1371            ccs_set_space(head);
1372            ccs_print_number_union_nospace(head, ptr);
1373    }
1374    
1375    /**
1376   * ccs_print_condition - Print condition part.   * ccs_print_condition - Print condition part.
1377   *   *
1378   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
# Line 1235  static bool ccs_print_condition(struct c Line 1387  static bool ccs_print_condition(struct c
1387          case 0:          case 0:
1388                  head->r.cond_index = 0;                  head->r.cond_index = 0;
1389                  head->r.cond_step++;                  head->r.cond_step++;
1390                    if (cond->transit && cond->exec_transit) {
1391                            ccs_set_space(head);
1392                            ccs_set_string(head, cond->transit->name);
1393                    }
1394                  /* fall through */                  /* fall through */
1395          case 1:          case 1:
1396                  {                  {
# Line 1287  static bool ccs_print_condition(struct c Line 1443  static bool ccs_print_condition(struct c
1443                                  switch (left) {                                  switch (left) {
1444                                  case CCS_ARGV_ENTRY:                                  case CCS_ARGV_ENTRY:
1445                                          ccs_io_printf(head,                                          ccs_io_printf(head,
1446                                                        "exec.argv[%u]%s\"%s\"",                                                        "exec.argv[%lu]%s=\"",
1447                                                        argv->index,                                                        argv->index,
1448                                                        argv->is_not ?                                                        argv->is_not ? "!" : "");
1449                                                        "!=" : "=",                                          ccs_set_string(head,
1450                                                        argv->value->name);                                                         argv->value->name);
1451                                            ccs_set_string(head, "\"");
1452                                          argv++;                                          argv++;
1453                                          continue;                                          continue;
1454                                  case CCS_ENVP_ENTRY:                                  case CCS_ENVP_ENTRY:
1455                                          ccs_io_printf(head,                                          ccs_set_string(head, "exec.envp[\"");
1456                                                        "exec.envp[\"%s\"]%s",                                          ccs_set_string(head, envp->name->name);
1457                                                        envp->name->name,                                          ccs_io_printf(head, "\"]%s=",
1458                                                        envp->is_not ?                                                        envp->is_not ? "!" : "");
                                                       "!=" : "=");  
1459                                          if (envp->value) {                                          if (envp->value) {
1460                                                  ccs_set_string(head, "\"");                                                  ccs_set_string(head, "\"");
1461                                                  ccs_set_string(head, envp->                                                  ccs_set_string(head, envp->
# Line 1311  static bool ccs_print_condition(struct c Line 1467  static bool ccs_print_condition(struct c
1467                                          envp++;                                          envp++;
1468                                          continue;                                          continue;
1469                                  case CCS_NUMBER_UNION:                                  case CCS_NUMBER_UNION:
1470                                          ccs_print_number_union(head,                                          ccs_print_number_union_nospace
1471                                                                 numbers_p++);                                                  (head, numbers_p++);
1472                                          break;                                          break;
1473                                  default:                                  default:
1474                                          ccs_set_string(head,                                          ccs_set_string(head,
# Line 1322  static bool ccs_print_condition(struct c Line 1478  static bool ccs_print_condition(struct c
1478                                  ccs_set_string(head, match ? "=" : "!=");                                  ccs_set_string(head, match ? "=" : "!=");
1479                                  switch (right) {                                  switch (right) {
1480                                  case CCS_NAME_UNION:                                  case CCS_NAME_UNION:
1481                                          ccs_print_name_union(head, names_p++);                                          ccs_print_name_union_quoted
1482                                                    (head, names_p++);
1483                                          break;                                          break;
1484                                  case CCS_NUMBER_UNION:                                  case CCS_NUMBER_UNION:
1485                                          ccs_print_number_union(head,                                          ccs_print_number_union_nospace
1486                                                                 numbers_p++);                                                  (head, numbers_p++);
1487                                          break;                                          break;
1488                                  default:                                  default:
1489                                          ccs_set_string(head,                                          ccs_set_string(head,
# Line 1347  static bool ccs_print_condition(struct c Line 1504  static bool ccs_print_condition(struct c
1504                          ccs_io_printf(head, " grant_log=%s",                          ccs_io_printf(head, " grant_log=%s",
1505                                        ccs_yesno(cond->grant_log ==                                        ccs_yesno(cond->grant_log ==
1506                                                  CCS_GRANTLOG_YES));                                                  CCS_GRANTLOG_YES));
1507                  if (cond->transit) {                  if (cond->transit && !cond->exec_transit) {
1508                            const char *name = cond->transit->name;
1509                          ccs_set_string(head, " auto_domain_transition=\"");                          ccs_set_string(head, " auto_domain_transition=\"");
1510                          ccs_set_string(head, cond->transit->name);                          ccs_set_string(head, name);
1511                          ccs_set_string(head, "\"");                          ccs_set_string(head, "\"");
1512                  }                  }
1513                  ccs_set_lf(head);                  ccs_set_lf(head);
# Line 1359  static bool ccs_print_condition(struct c Line 1517  static bool ccs_print_condition(struct c
1517  }  }
1518    
1519  /**  /**
1520   * ccs_fns - Find next set bit.   * ccs_set_group - Print "acl_group " header keyword and category name.
  *  
  * @perm: 8 bits value.  
  * @bit:  First bit to find.  
  *  
  * Returns next set bit on success, 8 otherwise.  
  */  
 static u8 ccs_fns(const u8 perm, u8 bit)  
 {  
         for ( ; bit < 8; bit++)  
                 if (perm & (1 << bit))  
                         break;  
         return bit;  
 }  
   
 /**  
  * ccs_set_group - Print "acl_group " header keyword.  
1521   *   *
1522   * @head: Pointer to "struct ccs_io_buffer".   * @head:     Pointer to "struct ccs_io_buffer".
1523     * @category: Category name.
1524   *   *
1525   * Returns nothing.   * Returns nothing.
1526   */   */
1527  static void ccs_set_group(struct ccs_io_buffer *head)  static void ccs_set_group(struct ccs_io_buffer *head, const char *category)
1528  {  {
1529          if (head->type == CCS_EXCEPTIONPOLICY)          if (head->type == CCS_EXCEPTIONPOLICY) {
1530                  ccs_io_printf(head, "acl_group %u ", head->r.group_index);                  ccs_print_namespace(head);
1531                    ccs_io_printf(head, "acl_group %u ", head->r.acl_group_index);
1532            }
1533            ccs_set_string(head, category);
1534  }  }
1535    
1536  /**  /**
# Line 1399  static bool ccs_print_entry(struct ccs_i Line 1545  static bool ccs_print_entry(struct ccs_i
1545                              const struct ccs_acl_info *acl)                              const struct ccs_acl_info *acl)
1546  {  {
1547          const u8 acl_type = acl->type;          const u8 acl_type = acl->type;
1548            const bool may_trigger_transition = acl->cond && acl->cond->transit;
1549            bool first = true;
1550          u8 bit;          u8 bit;
1551          if (head->r.print_cond_part)          if (head->r.print_cond_part)
1552                  goto print_cond_part;                  goto print_cond_part;
1553          if (acl->is_deleted)          if (acl->is_deleted)
1554                  return true;                  return true;
 next:  
         bit = head->r.bit;  
1555          if (!ccs_flush(head))          if (!ccs_flush(head))
1556                  return false;                  return false;
1557          else if (acl_type == CCS_TYPE_PATH_ACL) {          else if (acl_type == CCS_TYPE_PATH_ACL) {
1558                  struct ccs_path_acl *ptr                  struct ccs_path_acl *ptr
1559                          = container_of(acl, typeof(*ptr), head);                          = container_of(acl, typeof(*ptr), head);
1560                  const u16 perm = ptr->perm;                  const u16 perm = ptr->perm;
1561                  for ( ; bit < CCS_MAX_PATH_OPERATION; bit++) {                  for (bit = 0; bit < CCS_MAX_PATH_OPERATION; bit++) {
1562                          if (!(perm & (1 << bit)))                          if (!(perm & (1 << bit)))
1563                                  continue;                                  continue;
1564                          if (head->r.print_execute_only &&                          if (head->r.print_transition_related_only &&
1565                              bit != CCS_TYPE_EXECUTE                              bit != CCS_TYPE_EXECUTE && !may_trigger_transition)
                             /* && bit != CCS_TYPE_TRANSIT */)  
1566                                  continue;                                  continue;
1567                          break;                          if (first) {
1568                                    ccs_set_group(head, "file ");
1569                                    first = false;
1570                            } else {
1571                                    ccs_set_slash(head);
1572                            }
1573                            ccs_set_string(head, ccs_path_keyword[bit]);
1574                  }                  }
1575                  if (bit >= CCS_MAX_PATH_OPERATION)                  if (first)
1576                          goto done;                          return true;
                 ccs_set_group(head);  
                 ccs_set_string(head, "file ");  
                 ccs_set_string(head, ccs_path_keyword[bit]);  
1577                  ccs_print_name_union(head, &ptr->name);                  ccs_print_name_union(head, &ptr->name);
1578          } else if (acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER ||          } else if (acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER ||
1579                     acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {                     acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {
1580                  struct ccs_handler_acl *ptr                  struct ccs_handler_acl *ptr
1581                          = container_of(acl, typeof(*ptr), head);                          = container_of(acl, typeof(*ptr), head);
1582                  ccs_set_group(head);                  ccs_set_group(head, "task ");
                 ccs_set_string(head, "task ");  
1583                  ccs_set_string(head, acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER                  ccs_set_string(head, acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER
1584                                 ? "auto_execute_handler " :                                 ? "auto_execute_handler " :
1585                                 "denied_execute_handler ");                                 "denied_execute_handler ");
# Line 1441  next: Line 1588  next:
1588                     acl_type == CCS_TYPE_MANUAL_TASK_ACL) {                     acl_type == CCS_TYPE_MANUAL_TASK_ACL) {
1589                  struct ccs_task_acl *ptr =                  struct ccs_task_acl *ptr =
1590                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1591                  ccs_set_group(head);                  ccs_set_group(head, "task ");
                 ccs_set_string(head, "task ");  
1592                  ccs_set_string(head, acl_type == CCS_TYPE_AUTO_TASK_ACL ?                  ccs_set_string(head, acl_type == CCS_TYPE_AUTO_TASK_ACL ?
1593                                 "auto_domain_transition " :                                 "auto_domain_transition " :
1594                                 "manual_domain_transition ");                                 "manual_domain_transition ");
1595                  ccs_set_string(head, ptr->domainname->name);                  ccs_set_string(head, ptr->domainname->name);
1596          } else if (head->r.print_execute_only) {          } else if (head->r.print_transition_related_only &&
1597                       !may_trigger_transition) {
1598                  return true;                  return true;
1599          } else if (acl_type == CCS_TYPE_MKDEV_ACL) {          } else if (acl_type == CCS_TYPE_MKDEV_ACL) {
1600                  struct ccs_mkdev_acl *ptr =                  struct ccs_mkdev_acl *ptr =
1601                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1602                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1603                  if (bit >= CCS_MAX_MKDEV_OPERATION)                  for (bit = 0; bit < CCS_MAX_MKDEV_OPERATION; bit++) {
1604                          goto done;                          if (!(perm & (1 << bit)))
1605                  ccs_set_group(head);                                  continue;
1606                  ccs_set_string(head, "file ");                          if (first) {
1607                  ccs_set_string(head, ccs_mac_keywords[ccs_pnnn2mac[bit]]);                                  ccs_set_group(head, "file ");
1608                                    first = false;
1609                            } else {
1610                                    ccs_set_slash(head);
1611                            }
1612                            ccs_set_string(head, ccs_mac_keywords
1613                                           [ccs_pnnn2mac[bit]]);
1614                    }
1615                    if (first)
1616                            return true;
1617                  ccs_print_name_union(head, &ptr->name);                  ccs_print_name_union(head, &ptr->name);
1618                  ccs_print_number_union(head, &ptr->mode);                  ccs_print_number_union(head, &ptr->mode);
1619                  ccs_print_number_union(head, &ptr->major);                  ccs_print_number_union(head, &ptr->major);
# Line 1465  next: Line 1621  next:
1621          } else if (acl_type == CCS_TYPE_PATH2_ACL) {          } else if (acl_type == CCS_TYPE_PATH2_ACL) {
1622                  struct ccs_path2_acl *ptr =                  struct ccs_path2_acl *ptr =
1623                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1624                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1625                  if (bit >= CCS_MAX_PATH2_OPERATION)                  for (bit = 0; bit < CCS_MAX_PATH2_OPERATION; bit++) {
1626                          goto done;                          if (!(perm & (1 << bit)))
1627                  ccs_set_group(head);                                  continue;
1628                  ccs_set_string(head, "file ");                          if (first) {
1629                  ccs_set_string(head, ccs_mac_keywords[ccs_pp2mac[bit]]);                                  ccs_set_group(head, "file ");
1630                                    first = false;
1631                            } else {
1632                                    ccs_set_slash(head);
1633                            }
1634                            ccs_set_string(head, ccs_mac_keywords
1635                                           [ccs_pp2mac[bit]]);
1636                    }
1637                    if (first)
1638                            return true;
1639                  ccs_print_name_union(head, &ptr->name1);                  ccs_print_name_union(head, &ptr->name1);
1640                  ccs_print_name_union(head, &ptr->name2);                  ccs_print_name_union(head, &ptr->name2);
1641          } else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {          } else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
1642                  struct ccs_path_number_acl *ptr =                  struct ccs_path_number_acl *ptr =
1643                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1644                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1645                  if (bit >= CCS_MAX_PATH_NUMBER_OPERATION)                  for (bit = 0; bit < CCS_MAX_PATH_NUMBER_OPERATION; bit++) {
1646                          goto done;                          if (!(perm & (1 << bit)))
1647                  ccs_set_group(head);                                  continue;
1648                  ccs_set_string(head, "file ");                          if (first) {
1649                  ccs_set_string(head, ccs_mac_keywords[ccs_pn2mac[bit]]);                                  ccs_set_group(head, "file ");
1650                                    first = false;
1651                            } else {
1652                                    ccs_set_slash(head);
1653                            }
1654                            ccs_set_string(head, ccs_mac_keywords
1655                                           [ccs_pn2mac[bit]]);
1656                    }
1657                    if (first)
1658                            return true;
1659                  ccs_print_name_union(head, &ptr->name);                  ccs_print_name_union(head, &ptr->name);
1660                  ccs_print_number_union(head, &ptr->number);                  ccs_print_number_union(head, &ptr->number);
1661          } else if (acl_type == CCS_TYPE_ENV_ACL) {          } else if (acl_type == CCS_TYPE_ENV_ACL) {
1662                  struct ccs_env_acl *ptr =                  struct ccs_env_acl *ptr =
1663                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1664                  ccs_set_group(head);                  ccs_set_group(head, "misc env ");
                 ccs_set_string(head, "misc env ");  
1665                  ccs_set_string(head, ptr->env->name);                  ccs_set_string(head, ptr->env->name);
1666          } else if (acl_type == CCS_TYPE_CAPABILITY_ACL) {          } else if (acl_type == CCS_TYPE_CAPABILITY_ACL) {
1667                  struct ccs_capability_acl *ptr =                  struct ccs_capability_acl *ptr =
1668                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1669                  ccs_set_group(head);                  ccs_set_group(head, "capability ");
1670                  ccs_set_string(head, "capability ");                  ccs_set_string(head, ccs_mac_keywords
1671                  ccs_set_string(head,                                 [ccs_c2mac[ptr->operation]]);
                                ccs_mac_keywords[ccs_c2mac[ptr->operation]]);  
1672          } else if (acl_type == CCS_TYPE_INET_ACL) {          } else if (acl_type == CCS_TYPE_INET_ACL) {
1673                  struct ccs_inet_acl *ptr =                  struct ccs_inet_acl *ptr =
1674                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1675                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1676                  if (bit >= CCS_MAX_NETWORK_OPERATION)                  for (bit = 0; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
1677                          goto done;                          if (!(perm & (1 << bit)))
1678                  ccs_set_group(head);                                  continue;
1679                  ccs_set_string(head, "network inet ");                          if (first) {
1680                  ccs_set_string(head, ccs_proto_keyword[ptr->protocol]);                                  ccs_set_group(head, "network inet ");
1681                  ccs_set_space(head);                                  ccs_set_string(head, ccs_proto_keyword
1682                  ccs_set_string(head, ccs_socket_keyword[bit]);                                                 [ptr->protocol]);
1683                                    ccs_set_space(head);
1684                                    first = false;
1685                            } else {
1686                                    ccs_set_slash(head);
1687                            }
1688                            ccs_set_string(head, ccs_socket_keyword[bit]);
1689                    }
1690                    if (first)
1691                            return true;
1692                  ccs_set_space(head);                  ccs_set_space(head);
1693                  switch (ptr->address_type) {                  if (ptr->address.group) {
                         char buf[128];  
                 case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP:  
1694                          ccs_set_string(head, "@");                          ccs_set_string(head, "@");
1695                          ccs_set_string(head,                          ccs_set_string(head,
1696                                         ptr->address.group->group_name->name);                                         ptr->address.group->group_name->name);
1697                          break;                  } else {
1698                  case CCS_IP_ADDRESS_TYPE_IPv4:                          char buf[128];
1699                          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);  
1700                          ccs_io_printf(head, "%s", buf);                          ccs_io_printf(head, "%s", buf);
                         break;  
1701                  }                  }
1702                  ccs_print_number_union(head, &ptr->port);                  ccs_print_number_union(head, &ptr->port);
1703          } else if (acl_type == CCS_TYPE_UNIX_ACL) {          } else if (acl_type == CCS_TYPE_UNIX_ACL) {
1704                  struct ccs_unix_acl *ptr =                  struct ccs_unix_acl *ptr =
1705                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1706                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1707                  if (bit >= CCS_MAX_NETWORK_OPERATION)                  for (bit = 0; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
1708                          goto done;                          if (!(perm & (1 << bit)))
1709                  ccs_set_group(head);                                  continue;
1710                  ccs_set_string(head, "network unix ");                          if (first) {
1711                  ccs_set_string(head, ccs_proto_keyword[ptr->protocol]);                                  ccs_set_group(head, "network unix ");
1712                  ccs_set_space(head);                                  ccs_set_string(head, ccs_proto_keyword
1713                  ccs_set_string(head, ccs_socket_keyword[bit]);                                                 [ptr->protocol]);
1714                                    ccs_set_space(head);
1715                                    first = false;
1716                            } else {
1717                                    ccs_set_slash(head);
1718                            }
1719                            ccs_set_string(head, ccs_socket_keyword[bit]);
1720                    }
1721                    if (first)
1722                            return true;
1723                  ccs_print_name_union(head, &ptr->name);                  ccs_print_name_union(head, &ptr->name);
1724          } else if (acl_type == CCS_TYPE_SIGNAL_ACL) {          } else if (acl_type == CCS_TYPE_SIGNAL_ACL) {
1725                  struct ccs_signal_acl *ptr =                  struct ccs_signal_acl *ptr =
1726                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1727                  ccs_set_group(head);                  ccs_set_group(head, "ipc signal ");
1728                  ccs_set_string(head, "ipc signal ");                  ccs_print_number_union_nospace(head, &ptr->sig);
1729                  ccs_io_printf(head, "%u ", ptr->sig);                  ccs_set_space(head);
1730                  ccs_set_string(head, ptr->domainname->name);                  ccs_set_string(head, ptr->domainname->name);
1731          } else if (acl_type == CCS_TYPE_MOUNT_ACL) {          } else if (acl_type == CCS_TYPE_MOUNT_ACL) {
1732                  struct ccs_mount_acl *ptr =                  struct ccs_mount_acl *ptr =
1733                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1734                  ccs_set_group(head);                  ccs_set_group(head, "file mount");
                 ccs_io_printf(head, "file mount");  
1735                  ccs_print_name_union(head, &ptr->dev_name);                  ccs_print_name_union(head, &ptr->dev_name);
1736                  ccs_print_name_union(head, &ptr->dir_name);                  ccs_print_name_union(head, &ptr->dir_name);
1737                  ccs_print_name_union(head, &ptr->fs_type);                  ccs_print_name_union(head, &ptr->fs_type);
1738                  ccs_print_number_union(head, &ptr->flags);                  ccs_print_number_union(head, &ptr->flags);
1739          }          }
         head->r.bit = bit + 1;  
1740          if (acl->cond) {          if (acl->cond) {
1741                  head->r.print_cond_part = true;                  head->r.print_cond_part = true;
1742                  head->r.cond_step = 0;                  head->r.cond_step = 0;
# Line 1570  print_cond_part: Line 1749  print_cond_part:
1749          } else {          } else {
1750                  ccs_set_lf(head);                  ccs_set_lf(head);
1751          }          }
         switch (acl_type) {  
         case CCS_TYPE_PATH_ACL:  
         case CCS_TYPE_MKDEV_ACL:  
         case CCS_TYPE_PATH2_ACL:  
         case CCS_TYPE_PATH_NUMBER_ACL:  
         case CCS_TYPE_INET_ACL:  
         case CCS_TYPE_UNIX_ACL:  
                 goto next;  
         }  
 done:  
         head->r.bit = 0;  
1752          return true;          return true;
1753  }  }
1754    
1755  /**  /**
1756   * ccs_read_domain2 - Read domain policy.   * ccs_read_domain2 - Read domain policy.
1757   *   *
1758   * @head:   Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1759   * @domain: Pointer to "struct ccs_domain_info".   * @list: Pointer to "struct list_head".
  * @index:  Index number.  
1760   *   *
1761   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1762   *   *
1763   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1764   */   */
1765  static bool ccs_read_domain2(struct ccs_io_buffer *head,  static bool ccs_read_domain2(struct ccs_io_buffer *head,
1766                               struct ccs_domain_info *domain,                               struct list_head *list)
                              const u8 index)  
1767  {  {
1768          list_for_each_cookie(head->r.acl, &domain->acl_info_list[index]) {          list_for_each_cookie(head->r.acl, list) {
1769                  struct ccs_acl_info *ptr =                  struct ccs_acl_info *ptr =
1770                          list_entry(head->r.acl, typeof(*ptr), list);                          list_entry(head->r.acl, typeof(*ptr), list);
1771                  if (!ccs_print_entry(head, ptr))                  if (!ccs_print_entry(head, ptr))
# Line 1644  static void ccs_read_domain(struct ccs_i Line 1810  static void ccs_read_domain(struct ccs_i
1810                          ccs_set_lf(head);                          ccs_set_lf(head);
1811                          /* fall through */                          /* fall through */
1812                  case 1:                  case 1:
1813                          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))  
1814                                  return;                                  return;
1815                          head->r.step++;                          head->r.step++;
1816                          if (!ccs_set_lf(head))                          if (!ccs_set_lf(head))
1817                                  return;                                  return;
1818                          /* fall through */                          /* fall through */
1819                  case 3:                  case 2:
1820                          head->r.step = 0;                          head->r.step = 0;
1821                          if (head->r.print_this_domain_only)                          if (head->r.print_this_domain_only)
1822                                  goto done;                                  goto done;
# Line 1666  done: Line 1827  done:
1827  }  }
1828    
1829  /**  /**
  * 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;  
 }  
   
 /**  
1830   * ccs_write_pid - Specify PID to obtain domainname.   * ccs_write_pid - Specify PID to obtain domainname.
1831   *   *
1832   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
# Line 1807  static void ccs_read_pid(struct ccs_io_b Line 1902  static void ccs_read_pid(struct ccs_io_b
1902    
1903  /* String table for domain transition control keywords. */  /* String table for domain transition control keywords. */
1904  static const char * const ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {  static const char * const ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {
1905            [CCS_TRANSITION_CONTROL_NO_RESET]      = "no_reset_domain ",
1906            [CCS_TRANSITION_CONTROL_RESET]         = "reset_domain ",
1907          [CCS_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ",          [CCS_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ",
1908          [CCS_TRANSITION_CONTROL_INITIALIZE]    = "initialize_domain ",          [CCS_TRANSITION_CONTROL_INITIALIZE]    = "initialize_domain ",
1909          [CCS_TRANSITION_CONTROL_NO_KEEP]       = "no_keep_domain ",          [CCS_TRANSITION_CONTROL_NO_KEEP]       = "no_keep_domain ",
# Line 1829  static const char * const ccs_group_name Line 1926  static const char * const ccs_group_name
1926   */   */
1927  static int ccs_write_exception(struct ccs_io_buffer *head)  static int ccs_write_exception(struct ccs_io_buffer *head)
1928  {  {
1929          char *data = head->write_buf;          const bool is_delete = head->w.is_delete;
1930          const bool is_delete = ccs_str_starts(&data, "delete ");          struct ccs_acl_param param = {
1931          u8 i;                  .ns = head->w.ns,
1932          static const struct {                  .is_delete = is_delete,
1933                  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 },  
1934          };          };
1935          for (i = 0; i < 2; i++)          u8 i;
1936                  if (ccs_str_starts(&data, ccs_callback[i].keyword))          if (ccs_str_starts(&param.data, "aggregator "))
1937                          return ccs_callback[i].write(data, is_delete);                  return ccs_write_aggregator(&param);
1938            if (ccs_str_starts(&param.data, "deny_autobind "))
1939                    return ccs_write_reserved_port(&param);
1940          for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)          for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)
1941                  if (ccs_str_starts(&data, ccs_transition_type[i]))                  if (ccs_str_starts(&param.data, ccs_transition_type[i]))
1942                          return ccs_write_transition_control(data, is_delete,                          return ccs_write_transition_control(&param, i);
                                                             i);  
1943          for (i = 0; i < CCS_MAX_GROUP; i++)          for (i = 0; i < CCS_MAX_GROUP; i++)
1944                  if (ccs_str_starts(&data, ccs_group_name[i]))                  if (ccs_str_starts(&param.data, ccs_group_name[i]))
1945                          return ccs_write_group(data, is_delete, i);                          return ccs_write_group(&param, i);
1946          if (ccs_str_starts(&data, "acl_group ")) {          if (ccs_str_starts(&param.data, "acl_group ")) {
1947                  unsigned int group;                  unsigned int group;
1948                  if (sscanf(data, "%u", &group) == 1 &&                  char *data;
1949                      group < CCS_MAX_ACL_GROUPS) {                  group = simple_strtoul(param.data, &data, 10);
1950                          data = strchr(data, ' ');                  if (group < CCS_MAX_ACL_GROUPS && *data++ == ' ')
1951                          if (data)                          return ccs_write_domain2(head->w.ns,
1952                                  return ccs_write_domain2(data + 1,                                                   &head->w.ns->acl_group[group],
1953                                                           &ccs_acl_group[group],                                                   data, is_delete);
                                                          is_delete);  
                 }  
1954          }          }
1955          return -EINVAL;          return -EINVAL;
1956  }  }
# Line 1875  static int ccs_write_exception(struct cc Line 1967  static int ccs_write_exception(struct cc
1967   */   */
1968  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)
1969  {  {
1970          list_for_each_cookie(head->r.group, &ccs_group_list[idx]) {          struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
1971                                                           namespace_list);
1972            struct list_head *list = &ns->group_list[idx];
1973            list_for_each_cookie(head->r.group, list) {
1974                  struct ccs_group *group =                  struct ccs_group *group =
1975                          list_entry(head->r.group, typeof(*group), head.list);                          list_entry(head->r.group, typeof(*group), head.list);
1976                  list_for_each_cookie(head->r.acl, &group->member_list) {                  list_for_each_cookie(head->r.acl, &group->member_list) {
# Line 1885  static bool ccs_read_group(struct ccs_io Line 1980  static bool ccs_read_group(struct ccs_io
1980                                  continue;                                  continue;
1981                          if (!ccs_flush(head))                          if (!ccs_flush(head))
1982                                  return false;                                  return false;
1983                            ccs_print_namespace(head);
1984                          ccs_set_string(head, ccs_group_name[idx]);                          ccs_set_string(head, ccs_group_name[idx]);
1985                          ccs_set_string(head, group->group_name->name);                          ccs_set_string(head, group->group_name->name);
1986                          if (idx == CCS_PATH_GROUP) {                          if (idx == CCS_PATH_GROUP) {
# Line 1901  static bool ccs_read_group(struct ccs_io Line 1997  static bool ccs_read_group(struct ccs_io
1997                                  struct ccs_address_group *member =                                  struct ccs_address_group *member =
1998                                          container_of(ptr, typeof(*member),                                          container_of(ptr, typeof(*member),
1999                                                       head);                                                       head);
2000                                  if (member->is_ipv6)                                  ccs_print_ip(buffer, sizeof(buffer),
2001                                          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);  
2002                                  ccs_io_printf(head, " %s", buffer);                                  ccs_io_printf(head, " %s", buffer);
2003                          }                          }
2004                          ccs_set_lf(head);                          ccs_set_lf(head);
# Line 1931  static bool ccs_read_group(struct ccs_io Line 2021  static bool ccs_read_group(struct ccs_io
2021   */   */
2022  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)
2023  {  {
2024          list_for_each_cookie(head->r.acl, &ccs_policy_list[idx]) {          struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
2025                                                           namespace_list);
2026            struct list_head *list = &ns->policy_list[idx];
2027            list_for_each_cookie(head->r.acl, list) {
2028                  struct ccs_acl_head *acl =                  struct ccs_acl_head *acl =
2029                          container_of(head->r.acl, typeof(*acl), list);                          container_of(head->r.acl, typeof(*acl), list);
2030                  if (acl->is_deleted)                  if (acl->is_deleted)
2031                          continue;                          continue;
2032                    if (head->r.print_transition_related_only &&
2033                        idx != CCS_ID_TRANSITION_CONTROL)
2034                            continue;
2035                  if (!ccs_flush(head))                  if (!ccs_flush(head))
2036                          return false;                          return false;
2037                  switch (idx) {                  switch (idx) {
# Line 1943  static bool ccs_read_policy(struct ccs_i Line 2039  static bool ccs_read_policy(struct ccs_i
2039                          {                          {
2040                                  struct ccs_transition_control *ptr =                                  struct ccs_transition_control *ptr =
2041                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
2042                                    ccs_print_namespace(head);
2043                                  ccs_set_string(head,                                  ccs_set_string(head,
2044                                                 ccs_transition_type[ptr->type]);                                                 ccs_transition_type[ptr->type]);
2045                                  ccs_set_string(head, ptr->program ?                                  ccs_set_string(head, ptr->program ?
# Line 1956  static bool ccs_read_policy(struct ccs_i Line 2053  static bool ccs_read_policy(struct ccs_i
2053                          {                          {
2054                                  struct ccs_aggregator *ptr =                                  struct ccs_aggregator *ptr =
2055                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
2056                                    ccs_print_namespace(head);
2057                                  ccs_set_string(head, "aggregator ");                                  ccs_set_string(head, "aggregator ");
2058                                  ccs_set_string(head, ptr->original_name->name);                                  ccs_set_string(head, ptr->original_name->name);
2059                                  ccs_set_space(head);                                  ccs_set_space(head);
# Line 1967  static bool ccs_read_policy(struct ccs_i Line 2065  static bool ccs_read_policy(struct ccs_i
2065                          {                          {
2066                                  struct ccs_reserved *ptr =                                  struct ccs_reserved *ptr =
2067                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
2068                                  const u16 min_port = ptr->min_port;                                  ccs_print_namespace(head);
                                 const u16 max_port = ptr->max_port;  
2069                                  ccs_set_string(head, "deny_autobind ");                                  ccs_set_string(head, "deny_autobind ");
2070                                  ccs_io_printf(head, "%u", min_port);                                  ccs_print_number_union_nospace(head,
2071                                  if (min_port != max_port)                                                                 &ptr->port);
                                         ccs_io_printf(head, "-%u", max_port);  
2072                          }                          }
2073                          break;                          break;
2074                  default:                  default:
# Line 1995  static bool ccs_read_policy(struct ccs_i Line 2091  static bool ccs_read_policy(struct ccs_i
2091   */   */
2092  static void ccs_read_exception(struct ccs_io_buffer *head)  static void ccs_read_exception(struct ccs_io_buffer *head)
2093  {  {
2094            struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
2095                                                           namespace_list);
2096          if (head->r.eof)          if (head->r.eof)
2097                  return;                  return;
2098          while (head->r.step < CCS_MAX_POLICY &&          while (head->r.step < CCS_MAX_POLICY &&
# Line 2008  static void ccs_read_exception(struct cc Line 2106  static void ccs_read_exception(struct cc
2106          if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP)          if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP)
2107                  return;                  return;
2108          while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP          while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP
2109                 + CCS_MAX_ACL_GROUPS * 2) {                 + CCS_MAX_ACL_GROUPS) {
2110                  head->r.group_index = (head->r.step - CCS_MAX_POLICY                  head->r.acl_group_index =
2111                                         - CCS_MAX_GROUP) / 2;                          head->r.step - CCS_MAX_POLICY - CCS_MAX_GROUP;
2112                  if (!ccs_read_domain2(head,                  if (!ccs_read_domain2(head, &ns->acl_group
2113                                        &ccs_acl_group[head->r.group_index],                                        [head->r.acl_group_index]))
                                       head->r.step & 1))  
2114                          return;                          return;
2115                  head->r.step++;                  head->r.step++;
2116          }          }
# Line 2028  static DECLARE_WAIT_QUEUE_HEAD(ccs_answe Line 2125  static DECLARE_WAIT_QUEUE_HEAD(ccs_answe
2125  /* Structure for query. */  /* Structure for query. */
2126  struct ccs_query {  struct ccs_query {
2127          struct list_head list;          struct list_head list;
2128            struct ccs_domain_info *domain;
2129          char *query;          char *query;
2130          int query_len;          size_t query_len;
2131          unsigned int serial;          unsigned int serial;
2132          int timer;          u8 timer;
2133          int answer;          u8 answer;
2134          u8 retry;          u8 retry;
2135  };  };
2136    
# Line 2116  static void ccs_add_entry(char *header) Line 2214  static void ccs_add_entry(char *header)
2214          if (symlink)          if (symlink)
2215                  ccs_addprintf(buffer, len, "%s", symlink);                  ccs_addprintf(buffer, len, "%s", symlink);
2216          ccs_normalize_line(buffer);          ccs_normalize_line(buffer);
2217          if (!ccs_write_domain2(buffer, ccs_current_domain(), false))          {
2218                  ccs_update_stat(CCS_STAT_POLICY_UPDATES);                  struct ccs_domain_info *domain = ccs_current_domain();
2219                    if (!ccs_write_domain2(domain->ns, &domain->acl_info_list,
2220                                           buffer, false))
2221                            ccs_update_stat(CCS_STAT_POLICY_UPDATES);
2222            }
2223          kfree(buffer);          kfree(buffer);
2224  }  }
2225    
# Line 2170  int ccs_supervisor(struct ccs_request_in Line 2272  int ccs_supervisor(struct ccs_request_in
2272                  goto out;                  goto out;
2273          case CCS_CONFIG_LEARNING:          case CCS_CONFIG_LEARNING:
2274                  error = 0;                  error = 0;
2275                  /* Check mac_learning_entry parameter. */                  /* Check max_learning_entry parameter. */
2276                  if (ccs_domain_quota_ok(r))                  if (ccs_domain_quota_ok(r))
2277                          break;                          break;
2278                  /* fall through */                  /* fall through */
# Line 2189  int ccs_supervisor(struct ccs_request_in Line 2291  int ccs_supervisor(struct ccs_request_in
2291                  goto out;                  goto out;
2292          }          }
2293          len = ccs_round2(entry.query_len);          len = ccs_round2(entry.query_len);
2294            entry.domain = ccs_current_domain();
2295          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2296          if (ccs_memory_quota[CCS_MEMORY_QUERY] &&          if (ccs_memory_quota[CCS_MEMORY_QUERY] &&
2297              ccs_memory_used[CCS_MEMORY_QUERY] + len              ccs_memory_used[CCS_MEMORY_QUERY] + len
# Line 2236  out: Line 2339  out:
2339  }  }
2340    
2341  /**  /**
2342     * ccs_find_domain_by_qid - Get domain by query id.
2343     *
2344     * @serial: Query ID assigned by ccs_supervisor().
2345     *
2346     * Returns pointer to "struct ccs_domain_info" if found, NULL otherwise.
2347     */
2348    static struct ccs_domain_info *ccs_find_domain_by_qid(unsigned int serial)
2349    {
2350            struct ccs_query *ptr;
2351            struct ccs_domain_info *domain = NULL;
2352            spin_lock(&ccs_query_list_lock);
2353            list_for_each_entry(ptr, &ccs_query_list, list) {
2354                    if (ptr->serial != serial || ptr->answer)
2355                            continue;
2356                    domain = ptr->domain;
2357                    break;
2358            }
2359            spin_unlock(&ccs_query_list_lock);
2360            return domain;
2361    }
2362    
2363    /**
2364   * ccs_poll_query - poll() for /proc/ccs/query.   * ccs_poll_query - poll() for /proc/ccs/query.
2365   *   *
2366   * @file: Pointer to "struct file".   * @file: Pointer to "struct file".
# Line 2280  static int ccs_poll_query(struct file *f Line 2405  static int ccs_poll_query(struct file *f
2405  static void ccs_read_query(struct ccs_io_buffer *head)  static void ccs_read_query(struct ccs_io_buffer *head)
2406  {  {
2407          struct list_head *tmp;          struct list_head *tmp;
2408          int pos = 0;          unsigned int pos = 0;
2409          int len = 0;          size_t len = 0;
2410          char *buf;          char *buf;
2411          if (head->r.w_pos)          if (head->r.w_pos)
2412                  return;                  return;
# Line 2318  static void ccs_read_query(struct ccs_io Line 2443  static void ccs_read_query(struct ccs_io
2443                   * can change, but I don't care.                   * can change, but I don't care.
2444                   */                   */
2445                  if (len == ptr->query_len)                  if (len == ptr->query_len)
2446                          snprintf(buf, len + 32, "Q%u-%hu\n%s", ptr->serial,                          snprintf(buf, len + 31, "Q%u-%hu\n%s", ptr->serial,
2447                                   ptr->retry, ptr->query);                                   ptr->retry, ptr->query);
2448                  break;                  break;
2449          }          }
# Line 2359  static int ccs_write_answer(struct ccs_i Line 2484  static int ccs_write_answer(struct ccs_i
2484                  if (ptr->serial != serial)                  if (ptr->serial != serial)
2485                          continue;                          continue;
2486                  if (!ptr->answer)                  if (!ptr->answer)
2487                          ptr->answer = answer;                          ptr->answer = (u8) answer;
2488                  break;                  break;
2489          }          }
2490          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
# Line 2378  static void ccs_read_version(struct ccs_ Line 2503  static void ccs_read_version(struct ccs_
2503  {  {
2504          if (head->r.eof)          if (head->r.eof)
2505                  return;                  return;
2506          ccs_set_string(head, "1.8.0");          ccs_set_string(head, "1.8.3");
2507          head->r.eof = true;          head->r.eof = true;
2508  }  }
2509    
2510  /* String table for /proc/ccs/meminfo interface. */  /* String table for /proc/ccs/stat interface. */
2511  static const char * const ccs_policy_headers[CCS_MAX_POLICY_STAT] = {  static const char * const ccs_policy_headers[CCS_MAX_POLICY_STAT] = {
2512          [CCS_STAT_POLICY_UPDATES]    = "update:",          [CCS_STAT_POLICY_UPDATES]    = "update:",
2513          [CCS_STAT_POLICY_LEARNING]   = "violation in learning mode:",          [CCS_STAT_POLICY_LEARNING]   = "violation in learning mode:",
# Line 2390  static const char * const ccs_policy_hea Line 2515  static const char * const ccs_policy_hea
2515          [CCS_STAT_POLICY_ENFORCING]  = "violation in enforcing mode:",          [CCS_STAT_POLICY_ENFORCING]  = "violation in enforcing mode:",
2516  };  };
2517    
2518  /* String table for /proc/ccs/meminfo interface. */  /* String table for /proc/ccs/stat interface. */
2519  static const char * const ccs_memory_headers[CCS_MAX_MEMORY_STAT] = {  static const char * const ccs_memory_headers[CCS_MAX_MEMORY_STAT] = {
2520          [CCS_MEMORY_POLICY] = "policy:",          [CCS_MEMORY_POLICY]     = "policy:",
2521          [CCS_MEMORY_AUDIT]  = "audit log:",          [CCS_MEMORY_AUDIT]      = "audit log:",
2522          [CCS_MEMORY_QUERY]  = "query message:",          [CCS_MEMORY_QUERY]      = "query message:",
2523  };  };
2524    
2525  /* Timestamp counter for last updated. */  /* Timestamp counter for last updated. */
# Line 2474  static int ccs_write_stat(struct ccs_io_ Line 2599  static int ccs_write_stat(struct ccs_io_
2599          u8 i;          u8 i;
2600          if (ccs_str_starts(&data, "Memory used by "))          if (ccs_str_starts(&data, "Memory used by "))
2601                  for (i = 0; i < CCS_MAX_MEMORY_STAT; i++)                  for (i = 0; i < CCS_MAX_MEMORY_STAT; i++)
2602                          if (ccs_str_starts(&data, ccs_memory_headers[i]))                          if (ccs_str_starts(&data, ccs_memory_headers[i])) {
2603                                  sscanf(data, "%u", &ccs_memory_quota[i]);                                  if (*data == ' ')
2604          return 0;                                          data++;
2605  }                                  ccs_memory_quota[i] =
2606                                            simple_strtoul(data, NULL, 10);
2607  /* String table for /proc/ccs/meminfo interface. */                          }
 static const char * const ccs_old_memory_header[CCS_MAX_MEMORY_STAT] = {  
         [CCS_MEMORY_POLICY] = "Policy:",  
         [CCS_MEMORY_AUDIT]  = "Audit logs:",  
         [CCS_MEMORY_QUERY]  = "Query lists:",  
 };  
   
 /**  
  * ccs_read_memory_counter - Read memory usage.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  *  
  * Returns nothing.  
  */  
 static void ccs_read_memory_counter(struct ccs_io_buffer *head)  
 {  
         unsigned int total = 0;  
         int i;  
         if (head->r.eof)  
                 return;  
         for (i = 0; i < CCS_MAX_MEMORY_STAT; i++) {  
                 unsigned int used = ccs_memory_used[i];  
                 total += used;  
                 ccs_io_printf(head, "%-12s %10u", ccs_old_memory_header[i],  
                               used);  
                 if (ccs_memory_quota[i])  
                         ccs_io_printf(head, "   (Quota: %10u)",  
                                       ccs_memory_quota[i]);  
                 ccs_io_printf(head, "\n");  
         }  
         ccs_io_printf(head, "%-12s %10u\n", "Total:", total);  
         head->r.eof = true;  
 }  
   
 /**  
  * ccs_write_memory_quota - Set memory quota.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  *  
  * Returns 0.  
  */  
 static int ccs_write_memory_quota(struct ccs_io_buffer *head)  
 {  
         char *data = head->write_buf;  
         u8 i;  
         for (i = 0; i < CCS_MAX_MEMORY_STAT; i++)  
                 if (ccs_str_starts(&data, ccs_old_memory_header[i]))  
                         sscanf(data, "%u", &ccs_memory_quota[i]);  
2608          return 0;          return 0;
2609  }  }
2610    
# Line 2545  int ccs_open_control(const u8 type, stru Line 2623  int ccs_open_control(const u8 type, stru
2623                  return -ENOMEM;                  return -ENOMEM;
2624          mutex_init(&head->io_sem);          mutex_init(&head->io_sem);
2625          head->type = type;          head->type = type;
2626          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 */  
2627                  /* Allow execute_handler to read process's status. */                  /* Allow execute_handler to read process's status. */
2628                  if (!(ccs_current_flags() & CCS_TASK_IS_EXECUTE_HANDLER)) {                  if (!(ccs_current_flags() & CCS_TASK_IS_EXECUTE_HANDLER)) {
2629                          kfree(head);                          kfree(head);
2630                          return -EPERM;                          return -EPERM;
2631                  }                  }
                 /* 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_MEMINFO: /* /proc/ccs/meminfo */  
                 head->write = ccs_write_memory_quota;  
                 head->read = ccs_read_memory_counter;  
                 head->readbuf_size = 512;  
                 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;  
2632          }          }
2633          if (!(file->f_mode & FMODE_READ)) {          if ((file->f_mode & FMODE_READ) && type != CCS_AUDIT &&
2634                  /*              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) {  
2635                  /* Don't allocate read_buf for poll() access. */                  /* Don't allocate read_buf for poll() access. */
2636                  if (!head->readbuf_size)                  head->readbuf_size = 4096;
                         head->readbuf_size = 4096;  
2637                  head->read_buf = kzalloc(head->readbuf_size, CCS_GFP_FLAGS);                  head->read_buf = kzalloc(head->readbuf_size, CCS_GFP_FLAGS);
2638                  if (!head->read_buf) {                  if (!head->read_buf) {
2639                          kfree(head);                          kfree(head);
2640                          return -ENOMEM;                          return -ENOMEM;
2641                  }                  }
2642          }          }
2643          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) {  
2644                  head->writebuf_size = 4096;                  head->writebuf_size = 4096;
2645                  head->write_buf = kzalloc(head->writebuf_size, CCS_GFP_FLAGS);                  head->write_buf = kzalloc(head->writebuf_size, CCS_GFP_FLAGS);
2646                  if (!head->write_buf) {                  if (!head->write_buf) {
# Line 2640  int ccs_open_control(const u8 type, stru Line 2656  int ccs_open_control(const u8 type, stru
2656           */           */
2657          if (type == CCS_QUERY)          if (type == CCS_QUERY)
2658                  atomic_inc(&ccs_query_observers);                  atomic_inc(&ccs_query_observers);
         else if (type != CCS_AUDIT && type != CCS_VERSION &&  
                  type != CCS_MEMINFO && type != CCS_STAT)  
                 head->reader_idx = ccs_lock();  
2659          file->private_data = head;          file->private_data = head;
2660            ccs_notify_gc(head, true);
2661          return 0;          return 0;
2662  }  }
2663    
# Line 2662  int ccs_open_control(const u8 type, stru Line 2676  int ccs_open_control(const u8 type, stru
2676  int ccs_poll_control(struct file *file, poll_table *wait)  int ccs_poll_control(struct file *file, poll_table *wait)
2677  {  {
2678          struct ccs_io_buffer *head = file->private_data;          struct ccs_io_buffer *head = file->private_data;
2679          if (!head->poll)          switch (head->type) {
2680            case CCS_AUDIT:
2681                    return ccs_poll_log(file, wait);
2682            case CCS_QUERY:
2683                    return ccs_poll_query(file, wait);
2684            default:
2685                  return -ENOSYS;                  return -ENOSYS;
2686          return head->poll(file, wait);          }
2687    }
2688    
2689    /**
2690     * ccs_set_namespace_cursor - Set namespace to read.
2691     *
2692     * @head: Pointer to "struct ccs_io_buffer".
2693     *
2694     * Returns nothing.
2695     */
2696    static inline void ccs_set_namespace_cursor(struct ccs_io_buffer *head)
2697    {
2698            struct list_head *ns;
2699            if (head->type != CCS_EXCEPTIONPOLICY && head->type != CCS_PROFILE)
2700                    return;
2701            /*
2702             * If this is the first read, or reading previous namespace finished
2703             * and has more namespaces to read, update the namespace cursor.
2704             */
2705            ns = head->r.ns;
2706            if (!ns || (head->r.eof && ns->next != &ccs_namespace_list)) {
2707                    /* Clearing is OK because ccs_flush() returned true. */
2708                    memset(&head->r, 0, sizeof(head->r));
2709                    head->r.ns = ns ? ns->next : ccs_namespace_list.next;
2710            }
2711    }
2712    
2713    /**
2714     * ccs_has_more_namespace - Check for unread namespaces.
2715     *
2716     * @head: Pointer to "struct ccs_io_buffer".
2717     *
2718     * Returns true if we have more entries to print, false otherwise.
2719     */
2720    static inline bool ccs_has_more_namespace(struct ccs_io_buffer *head)
2721    {
2722            return (head->type == CCS_EXCEPTIONPOLICY ||
2723                    head->type == CCS_PROFILE) && head->r.eof &&
2724                    head->r.ns->next != &ccs_namespace_list;
2725  }  }
2726    
2727  /**  /**
2728   * ccs_read_control - read() for /proc/ccs/ interface.   * ccs_read_control - read() for /proc/ccs/ interface.
2729   *   *
2730   * @file:       Pointer to "struct file".   * @head:       Pointer to "struct ccs_io_buffer".
2731   * @buffer:     Poiner to buffer to write to.   * @buffer:     Poiner to buffer to write to.
2732   * @buffer_len: Size of @buffer.   * @buffer_len: Size of @buffer.
2733   *   *
2734   * Returns bytes read on success, negative value otherwise.   * Returns bytes read on success, negative value otherwise.
2735   */   */
2736  int ccs_read_control(struct file *file, char __user *buffer,  ssize_t ccs_read_control(struct ccs_io_buffer *head, char __user *buffer,
2737                       const int buffer_len)                           const size_t buffer_len)
2738  {  {
2739          int len;          int len;
         struct ccs_io_buffer *head = file->private_data;  
2740          int idx;          int idx;
         if (!head->read)  
                 return -ENOSYS;  
2741          if (!access_ok(VERIFY_WRITE, buffer, buffer_len))          if (!access_ok(VERIFY_WRITE, buffer, buffer_len))
2742                  return -EFAULT;                  return -EFAULT;
2743          if (mutex_lock_interruptible(&head->io_sem))          if (mutex_lock_interruptible(&head->io_sem))
# Line 2693  int ccs_read_control(struct file *file, Line 2747  int ccs_read_control(struct file *file,
2747          idx = ccs_read_lock();          idx = ccs_read_lock();
2748          if (ccs_flush(head))          if (ccs_flush(head))
2749                  /* Call the policy handler. */                  /* Call the policy handler. */
2750                  head->read(head);                  do {
2751          ccs_flush(head);                          ccs_set_namespace_cursor(head);
2752                            switch (head->type) {
2753                            case CCS_DOMAINPOLICY:
2754                                    ccs_read_domain(head);
2755                                    break;
2756                            case CCS_EXCEPTIONPOLICY:
2757                                    ccs_read_exception(head);
2758                                    break;
2759                            case CCS_AUDIT:
2760                                    ccs_read_log(head);
2761                                    break;
2762                            case CCS_EXECUTE_HANDLER:
2763                            case CCS_PROCESS_STATUS:
2764                                    ccs_read_pid(head);
2765                                    break;
2766                            case CCS_VERSION:
2767                                    ccs_read_version(head);
2768                                    break;
2769                            case CCS_STAT:
2770                                    ccs_read_stat(head);
2771                                    break;
2772                            case CCS_PROFILE:
2773                                    ccs_read_profile(head);
2774                                    break;
2775                            case CCS_QUERY:
2776                                    ccs_read_query(head);
2777                                    break;
2778                            case CCS_MANAGER:
2779                                    ccs_read_manager(head);
2780                                    break;
2781                            }
2782                    } while (ccs_flush(head) && ccs_has_more_namespace(head));
2783          ccs_read_unlock(idx);          ccs_read_unlock(idx);
2784          len = head->read_user_buf - buffer;          len = head->read_user_buf - buffer;
2785          mutex_unlock(&head->io_sem);          mutex_unlock(&head->io_sem);
# Line 2702  int ccs_read_control(struct file *file, Line 2787  int ccs_read_control(struct file *file,
2787  }  }
2788    
2789  /**  /**
2790     * ccs_parse_policy - Parse a policy line.
2791     *
2792     * @head: Poiter to "struct ccs_io_buffer".
2793     * @line: Line to parse.
2794     *
2795     * Returns 0 on success, negative value otherwise.
2796     *
2797     * Caller holds ccs_read_lock().
2798     */
2799    static int ccs_parse_policy(struct ccs_io_buffer *head, char *line)
2800    {
2801            /* Delete request? */
2802            head->w.is_delete = !strncmp(line, "delete ", 7);
2803            if (head->w.is_delete)
2804                    memmove(line, line + 7, strlen(line + 7) + 1);
2805            /* Selecting namespace to update. */
2806            if (head->type == CCS_EXCEPTIONPOLICY || head->type == CCS_PROFILE) {
2807                    if (*line == '<') {
2808                            char *cp = strchr(line, ' ');
2809                            if (cp) {
2810                                    *cp++ = '\0';
2811                                    head->w.ns = ccs_assign_namespace(line);
2812                                    memmove(line, cp, strlen(cp) + 1);
2813                            } else
2814                                    head->w.ns = NULL;
2815                    } else
2816                            head->w.ns = &ccs_kernel_namespace;
2817                    /* Don't allow updating if namespace is invalid. */
2818                    if (!head->w.ns)
2819                            return -ENOENT;
2820            }
2821            /* Do the update. */
2822            switch (head->type) {
2823            case CCS_DOMAINPOLICY:
2824                    return ccs_write_domain(head);
2825            case CCS_EXCEPTIONPOLICY:
2826                    return ccs_write_exception(head);
2827            case CCS_EXECUTE_HANDLER:
2828            case CCS_PROCESS_STATUS:
2829                    return ccs_write_pid(head);
2830            case CCS_STAT:
2831                    return ccs_write_stat(head);
2832            case CCS_PROFILE:
2833                    return ccs_write_profile(head);
2834            case CCS_QUERY:
2835                    return ccs_write_answer(head);
2836            case CCS_MANAGER:
2837                    return ccs_write_manager(head);
2838            default:
2839                    return -ENOSYS;
2840            }
2841    }
2842    
2843    /**
2844   * ccs_write_control - write() for /proc/ccs/ interface.   * ccs_write_control - write() for /proc/ccs/ interface.
2845   *   *
2846   * @file:       Pointer to "struct file".   * @head:       Pointer to "struct ccs_io_buffer".
2847   * @buffer:     Pointer to buffer to read from.   * @buffer:     Pointer to buffer to read from.
2848   * @buffer_len: Size of @buffer.   * @buffer_len: Size of @buffer.
2849   *   *
2850   * Returns @buffer_len on success, negative value otherwise.   * Returns @buffer_len on success, negative value otherwise.
2851   */   */
2852  int ccs_write_control(struct file *file, const char __user *buffer,  ssize_t ccs_write_control(struct ccs_io_buffer *head,
2853                        const int buffer_len)                            const char __user *buffer, const size_t buffer_len)
2854  {  {
         struct ccs_io_buffer *head = file->private_data;  
2855          int error = buffer_len;          int error = buffer_len;
2856          int avail_len = buffer_len;          size_t avail_len = buffer_len;
2857          char *cp0 = head->write_buf;          char *cp0 = head->write_buf;
2858          int idx;          int idx;
         if (!head->write)  
                 return -ENOSYS;  
2859          if (!access_ok(VERIFY_READ, buffer, buffer_len))          if (!access_ok(VERIFY_READ, buffer, buffer_len))
2860                  return -EFAULT;                  return -EFAULT;
2861          if (mutex_lock_interruptible(&head->io_sem))          if (mutex_lock_interruptible(&head->io_sem))
2862                  return -EINTR;                  return -EINTR;
2863          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 &&  
             !ccs_manager()) {  
                 ccs_read_unlock(idx);  
                 mutex_unlock(&head->io_sem);  
                 return -EPERM;  
         }  
2864          /* Read a line and dispatch it to the policy handler. */          /* Read a line and dispatch it to the policy handler. */
2865          while (avail_len > 0) {          while (avail_len > 0) {
2866                  char c;                  char c;
# Line 2760  int ccs_write_control(struct file *file, Line 2889  int ccs_write_control(struct file *file,
2889                  cp0[head->w.avail - 1] = '\0';                  cp0[head->w.avail - 1] = '\0';
2890                  head->w.avail = 0;                  head->w.avail = 0;
2891                  ccs_normalize_line(cp0);                  ccs_normalize_line(cp0);
2892                  if (head->write(head))                  if (!strcmp(cp0, "reset")) {
2893                            head->w.ns = &ccs_kernel_namespace;
2894                            head->w.domain = NULL;
2895                            memset(&head->r, 0, sizeof(head->r));
2896                          continue;                          continue;
2897                    }
2898                    /* Don't allow updating policies by non manager programs. */
2899                  switch (head->type) {                  switch (head->type) {
2900                    case CCS_PROCESS_STATUS:
2901                            /* This does not write anything. */
2902                            break;
2903                  case CCS_DOMAINPOLICY:                  case CCS_DOMAINPOLICY:
2904                            if (ccs_select_domain(head, cp0))
2905                                    continue;
2906                            /* fall through */
2907                  case CCS_EXCEPTIONPOLICY:                  case CCS_EXCEPTIONPOLICY:
2908                  case CCS_DOMAIN_STATUS:                          if (!strcmp(cp0, "select transition_only")) {
2909                  case CCS_MEMINFO:                                  head->r.print_transition_related_only = true;
2910                  case CCS_PROFILE:                                  continue;
2911                  case CCS_MANAGER:                          }
2912                          ccs_update_stat(CCS_STAT_POLICY_UPDATES);                          /* fall through */
2913                    default:
2914                            if (!ccs_manager()) {
2915                                    error = -EPERM;
2916                                    goto out;
2917                            }
2918                    }
2919                    switch (ccs_parse_policy(head, cp0)) {
2920                    case -EPERM:
2921                            error = -EPERM;
2922                            goto out;
2923                    case 0:
2924                            /* Update statistics. */
2925                            switch (head->type) {
2926                            case CCS_DOMAINPOLICY:
2927                            case CCS_EXCEPTIONPOLICY:
2928                            case CCS_STAT:
2929                            case CCS_PROFILE:
2930                            case CCS_MANAGER:
2931                                    ccs_update_stat(CCS_STAT_POLICY_UPDATES);
2932                                    break;
2933                            default:
2934                                    break;
2935                            }
2936                            break;
2937                  }                  }
2938          }          }
2939    out:
2940          ccs_read_unlock(idx);          ccs_read_unlock(idx);
2941          mutex_unlock(&head->io_sem);          mutex_unlock(&head->io_sem);
2942          return error;          return error;
# Line 2780  int ccs_write_control(struct file *file, Line 2945  int ccs_write_control(struct file *file,
2945  /**  /**
2946   * ccs_close_control - close() for /proc/ccs/ interface.   * ccs_close_control - close() for /proc/ccs/ interface.
2947   *   *
2948   * @file: Pointer to "struct file".   * @head: Pointer to "struct ccs_io_buffer".
2949   *   *
2950   * Returns 0.   * Returns 0.
2951   */   */
2952  int ccs_close_control(struct file *file)  int ccs_close_control(struct ccs_io_buffer *head)
2953  {  {
         struct ccs_io_buffer *head = file->private_data;  
         const bool is_write = head->write_buf != NULL;  
         const u8 type = head->type;  
2954          /*          /*
2955           * If the file is /proc/ccs/query, decrement the observer counter.           * If the file is /proc/ccs/query, decrement the observer counter.
2956           */           */
2957          if (type == CCS_QUERY) {          if (head->type == CCS_QUERY &&
2958                  if (atomic_dec_and_test(&ccs_query_observers))              atomic_dec_and_test(&ccs_query_observers))
2959                          wake_up_all(&ccs_answer_wait);                  wake_up_all(&ccs_answer_wait);
2960          } else if (type != CCS_AUDIT && type != CCS_VERSION &&          ccs_notify_gc(head, false);
                    type != CCS_MEMINFO && type != CCS_STAT)  
                 ccs_unlock(head->reader_idx);  
         /* Release memory used for policy I/O. */  
         kfree(head->read_buf);  
         head->read_buf = NULL;  
         kfree(head->write_buf);  
         head->write_buf = NULL;  
         kfree(head);  
         head = NULL;  
         file->private_data = NULL;  
         if (is_write)  
                 ccs_run_gc();  
2961          return 0;          return 0;
2962  }  }
2963    
# Line 2820  void __init ccs_policy_io_init(void) Line 2970  void __init ccs_policy_io_init(void)
2970  {  {
2971          ccsecurity_ops.check_profile = ccs_check_profile;          ccsecurity_ops.check_profile = ccs_check_profile;
2972  }  }
2973    
2974    /**
2975     * ccs_load_builtin_policy - Load built-in policy.
2976     *
2977     * Returns nothing.
2978     */
2979    void __init ccs_load_builtin_policy(void)
2980    {
2981            /*
2982             * This include file is manually created and contains built-in policy
2983             * named "ccs_builtin_profile", "ccs_builtin_exception_policy",
2984             * "ccs_builtin_domain_policy", "ccs_builtin_manager",
2985             * "ccs_builtin_stat" in the form of "static char [] __initdata".
2986             */
2987    #include "builtin-policy.h"
2988            u8 i;
2989            const int idx = ccs_read_lock();
2990            for (i = 0; i < 5; i++) {
2991                    struct ccs_io_buffer head = { };
2992                    char *start = "";
2993                    switch (i) {
2994                    case 0:
2995                            start = ccs_builtin_profile;
2996                            head.type = CCS_PROFILE;
2997                            break;
2998                    case 1:
2999                            start = ccs_builtin_exception_policy;
3000                            head.type = CCS_EXCEPTIONPOLICY;
3001                            break;
3002                    case 2:
3003                            start = ccs_builtin_domain_policy;
3004                            head.type = CCS_DOMAINPOLICY;
3005                            break;
3006                    case 3:
3007                            start = ccs_builtin_manager;
3008                            head.type = CCS_MANAGER;
3009                            break;
3010                    case 4:
3011                            start = ccs_builtin_stat;
3012                            head.type = CCS_STAT;
3013                            break;
3014                    }
3015                    while (1) {
3016                            char *end = strchr(start, '\n');
3017                            if (!end)
3018                                    break;
3019                            *end = '\0';
3020                            ccs_normalize_line(start);
3021                            head.write_buf = start;
3022                            ccs_parse_policy(&head, start);
3023                            start = end + 1;
3024                    }
3025            }
3026            ccs_read_unlock(idx);
3027    #ifdef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
3028            ccs_check_profile();
3029    #endif
3030    }

Legend:
Removed from v.4280  
changed lines
  Added in v.5559

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