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

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 5485 by kumaneko, Sun Sep 25 08:39:53 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-pre   2011/09/16
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))) {          ccs_set_memory_size(sizeof(*entry));
502            if (!ptr && ccs_memory_ok(entry)) {
503                  ptr = entry;                  ptr = entry;
504                  ptr->default_config = CCS_CONFIG_DISABLED |                  ptr->default_config = CCS_CONFIG_DISABLED |
505                          CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG;                          CCS_CONFIG_WANT_GRANT_LOG | CCS_CONFIG_WANT_REJECT_LOG;
# Line 446  static struct ccs_profile *ccs_assign_pr Line 510  static struct ccs_profile *ccs_assign_pr
510                  ptr->pref[CCS_PREF_MAX_LEARNING_ENTRY] =                  ptr->pref[CCS_PREF_MAX_LEARNING_ENTRY] =
511                          CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY;                          CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY;
512                  mb(); /* Avoid out-of-order execution. */                  mb(); /* Avoid out-of-order execution. */
513                  ccs_profile_ptr[profile] = ptr;                  ns->profile_ptr[profile] = ptr;
514                  entry = NULL;                  entry = NULL;
515          }          }
516          mutex_unlock(&ccs_policy_lock);          mutex_unlock(&ccs_policy_lock);
# Line 465  static void ccs_check_profile(void) Line 529  static void ccs_check_profile(void)
529          struct ccs_domain_info *domain;          struct ccs_domain_info *domain;
530          const int idx = ccs_read_lock();          const int idx = ccs_read_lock();
531          ccs_policy_loaded = true;          ccs_policy_loaded = true;
532            printk(KERN_INFO "CCSecurity: 1.8.3-pre   2011/09/16\n");
533          list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {          list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
534                  const u8 profile = domain->profile;                  const u8 profile = domain->profile;
535                  if (ccs_profile_ptr[profile])                  const struct ccs_policy_namespace *ns = domain->ns;
536                    if (ns->profile_version != 20100903)
537                            printk(KERN_ERR
538                                   "Profile version %u is not supported.\n",
539                                   ns->profile_version);
540                    else if (!ns->profile_ptr[profile])
541                            printk(KERN_ERR
542                                   "Profile %u (used by '%s') is not defined.\n",
543                                   profile, domain->domainname->name);
544                    else
545                          continue;                          continue;
546                  printk(KERN_ERR "Profile %u must be defined before using it.\n",                  printk(KERN_ERR
547                         profile);                         "Userland tools for TOMOYO 1.8 must be installed and "
548                           "policy must be initialized.\n");
549                  printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/1.8/ "                  printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/1.8/ "
550                         "for more information.\n");                         "for more information.\n");
551                  panic("Profile %u (used by '%s') not defined.\n",                  panic("STOP!");
                       profile, domain->domainname->name);  
552          }          }
553          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");  
554          printk(KERN_INFO "Mandatory Access Control activated.\n");          printk(KERN_INFO "Mandatory Access Control activated.\n");
555  }  }
556    
# Line 499  static void ccs_check_profile(void) Line 564  static void ccs_check_profile(void)
564  struct ccs_profile *ccs_profile(const u8 profile)  struct ccs_profile *ccs_profile(const u8 profile)
565  {  {
566          static struct ccs_profile ccs_null_profile;          static struct ccs_profile ccs_null_profile;
567          struct ccs_profile *ptr = ccs_profile_ptr[profile];          struct ccs_profile *ptr = ccs_current_namespace()->
568                    profile_ptr[profile];
569          if (!ptr)          if (!ptr)
570                  ptr = &ccs_null_profile;                  ptr = &ccs_null_profile;
571          return ptr;          return ptr;
# Line 633  static int ccs_write_profile(struct ccs_ Line 699  static int ccs_write_profile(struct ccs_
699          unsigned int i;          unsigned int i;
700          char *cp;          char *cp;
701          struct ccs_profile *profile;          struct ccs_profile *profile;
702          if (sscanf(data, "PROFILE_VERSION=%u", &ccs_profile_version) == 1)          if (sscanf(data, "PROFILE_VERSION=%u", &head->w.ns->profile_version)
703                == 1)
704                  return 0;                  return 0;
705          i = simple_strtoul(data, &cp, 10);          i = simple_strtoul(data, &cp, 10);
706          if (*cp != '-')          if (*cp != '-')
707                  return -EINVAL;                  return -EINVAL;
708          data = cp + 1;          data = cp + 1;
709          profile = ccs_assign_profile(i);          profile = ccs_assign_profile(head->w.ns, i);
710          if (!profile)          if (!profile)
711                  return -EINVAL;                  return -EINVAL;
712          cp = strchr(data, '=');          cp = strchr(data, '=');
# Line 647  static int ccs_write_profile(struct ccs_ Line 714  static int ccs_write_profile(struct ccs_
714                  return -EINVAL;                  return -EINVAL;
715          *cp++ = '\0';          *cp++ = '\0';
716          if (!strcmp(data, "COMMENT")) {          if (!strcmp(data, "COMMENT")) {
717                  const struct ccs_path_info *old_comment = profile->comment;                  static DEFINE_SPINLOCK(lock);
718                  profile->comment = ccs_get_name(cp);                  const struct ccs_path_info *new_comment = ccs_get_name(cp);
719                    const struct ccs_path_info *old_comment;
720                    if (!new_comment)
721                            return -ENOMEM;
722                    spin_lock(&lock);
723                    old_comment = profile->comment;
724                    profile->comment = new_comment;
725                    spin_unlock(&lock);
726                  ccs_put_name(old_comment);                  ccs_put_name(old_comment);
727                  return 0;                  return 0;
728          }          }
# Line 689  static void ccs_print_config(struct ccs_ Line 763  static void ccs_print_config(struct ccs_
763  static void ccs_read_profile(struct ccs_io_buffer *head)  static void ccs_read_profile(struct ccs_io_buffer *head)
764  {  {
765          u8 index;          u8 index;
766            struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
767                                                           namespace_list);
768          const struct ccs_profile *profile;          const struct ccs_profile *profile;
769            if (head->r.eof)
770                    return;
771  next:  next:
772          index = head->r.index;          index = head->r.index;
773          profile = ccs_profile_ptr[index];          profile = ns->profile_ptr[index];
774          switch (head->r.step) {          switch (head->r.step) {
775          case 0:          case 0:
776                  ccs_io_printf(head, "PROFILE_VERSION=%s\n", "20100903");                  ccs_print_namespace(head);
777                    ccs_io_printf(head, "PROFILE_VERSION=%u\n",
778                                  ns->profile_version);
779                  head->r.step++;                  head->r.step++;
780                  break;                  break;
781          case 1:          case 1:
782                  for ( ; head->r.index < CCS_MAX_PROFILES;                  for ( ; head->r.index < CCS_MAX_PROFILES; head->r.index++)
783                        head->r.index++)                          if (ns->profile_ptr[head->r.index])
                         if (ccs_profile_ptr[head->r.index])  
784                                  break;                                  break;
785                  if (head->r.index == CCS_MAX_PROFILES)                  if (head->r.index == CCS_MAX_PROFILES) {
786                            head->r.eof = true;
787                          return;                          return;
788                    }
789                  head->r.step++;                  head->r.step++;
790                  break;                  break;
791          case 2:          case 2:
792                  {                  {
793                          u8 i;                          u8 i;
794                          const struct ccs_path_info *comment = profile->comment;                          const struct ccs_path_info *comment = profile->comment;
795                            ccs_print_namespace(head);
796                          ccs_io_printf(head, "%u-COMMENT=", index);                          ccs_io_printf(head, "%u-COMMENT=", index);
797                          ccs_set_string(head, comment ? comment->name : "");                          ccs_set_string(head, comment ? comment->name : "");
798                          ccs_set_lf(head);                          ccs_set_lf(head);
799                            ccs_print_namespace(head);
800                          ccs_io_printf(head, "%u-PREFERENCE={ ", index);                          ccs_io_printf(head, "%u-PREFERENCE={ ", index);
801                          for (i = 0; i < CCS_MAX_PREF; i++)                          for (i = 0; i < CCS_MAX_PREF; i++)
802                                  ccs_io_printf(head, "%s=%u ",                                  ccs_io_printf(head, "%s=%u ",
803                                                ccs_pref_keywords[i],                                                ccs_pref_keywords[i],
804                                                profile->pref[i]);                                                profile->pref[i]);
805                          ccs_set_string(head, " }\n");                          ccs_set_string(head, "}\n");
806                          head->r.step++;                          head->r.step++;
807                  }                  }
808                  break;                  break;
809          case 3:          case 3:
810                  {                  {
811                            ccs_print_namespace(head);
812                          ccs_io_printf(head, "%u-%s", index, "CONFIG");                          ccs_io_printf(head, "%u-%s", index, "CONFIG");
813                          ccs_print_config(head, profile->default_config);                          ccs_print_config(head, profile->default_config);
814                          head->r.bit = 0;                          head->r.bit = 0;
# Line 738  next: Line 822  next:
822                          const u8 config = profile->config[i];                          const u8 config = profile->config[i];
823                          if (config == CCS_CONFIG_USE_DEFAULT)                          if (config == CCS_CONFIG_USE_DEFAULT)
824                                  continue;                                  continue;
825                            ccs_print_namespace(head);
826                          if (i < CCS_MAX_MAC_INDEX)                          if (i < CCS_MAX_MAC_INDEX)
827                                  ccs_io_printf(head, "%u-CONFIG::%s::%s", index,                                  ccs_io_printf(head, "%u-CONFIG::%s::%s", index,
828                                                ccs_category_keywords                                                ccs_category_keywords
# Line 784  static bool ccs_same_manager(const struc Line 869  static bool ccs_same_manager(const struc
869   *   *
870   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
871   */   */
872  static int ccs_update_manager_entry(const char *manager, const bool is_delete)  static inline int ccs_update_manager_entry(const char *manager,
873                                               const bool is_delete)
874  {  {
875          struct ccs_manager e = { };          struct ccs_manager e = { };
876            struct ccs_acl_param param = {
877                    /* .ns = &ccs_kernel_namespace, */
878                    .is_delete = is_delete,
879                    .list = &ccs_kernel_namespace.policy_list[CCS_ID_MANAGER],
880            };
881          int error = is_delete ? -ENOENT : -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
882          if (ccs_domain_def(manager)) {          if (ccs_domain_def(manager)) {
883                  if (!ccs_correct_domain(manager))                  if (!ccs_correct_domain(manager))
# Line 797  static int ccs_update_manager_entry(cons Line 888  static int ccs_update_manager_entry(cons
888                          return -EINVAL;                          return -EINVAL;
889          }          }
890          e.manager = ccs_get_name(manager);          e.manager = ccs_get_name(manager);
891          if (!e.manager)          if (e.manager) {
892                  return error;                  error = ccs_update_policy(&e.head, sizeof(e), &param,
893          error = ccs_update_policy(&e.head, sizeof(e), is_delete,                                            ccs_same_manager);
894                                    &ccs_policy_list[CCS_ID_MANAGER],                  ccs_put_name(e.manager);
895                                    ccs_same_manager);          }
         ccs_put_name(e.manager);  
896          return error;          return error;
897  }  }
898    
# Line 815  static int ccs_update_manager_entry(cons Line 905  static int ccs_update_manager_entry(cons
905   */   */
906  static int ccs_write_manager(struct ccs_io_buffer *head)  static int ccs_write_manager(struct ccs_io_buffer *head)
907  {  {
908          char *data = head->write_buf;          const char *data = head->write_buf;
         bool is_delete = ccs_str_starts(&data, "delete ");  
909          if (!strcmp(data, "manage_by_non_root")) {          if (!strcmp(data, "manage_by_non_root")) {
910                  ccs_manage_by_non_root = !is_delete;                  ccs_manage_by_non_root = !head->w.is_delete;
911                  return 0;                  return 0;
912          }          }
913          return ccs_update_manager_entry(data, is_delete);          return ccs_update_manager_entry(data, head->w.is_delete);
914  }  }
915    
916  /**  /**
# Line 837  static void ccs_read_manager(struct ccs_ Line 926  static void ccs_read_manager(struct ccs_
926  {  {
927          if (head->r.eof)          if (head->r.eof)
928                  return;                  return;
929          list_for_each_cookie(head->r.acl, &ccs_policy_list[CCS_ID_MANAGER]) {          list_for_each_cookie(head->r.acl, &ccs_kernel_namespace.
930                                 policy_list[CCS_ID_MANAGER]) {
931                  struct ccs_manager *ptr =                  struct ccs_manager *ptr =
932                          list_entry(head->r.acl, typeof(*ptr), head.list);                          list_entry(head->r.acl, typeof(*ptr), head.list);
933                  if (ptr->head.is_deleted)                  if (ptr->head.is_deleted)
# Line 873  static bool ccs_manager(void) Line 963  static bool ccs_manager(void)
963          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))
964                  return false;                  return false;
965          exe = ccs_get_exe();          exe = ccs_get_exe();
966          list_for_each_entry_srcu(ptr, &ccs_policy_list[CCS_ID_MANAGER],          list_for_each_entry_srcu(ptr, &ccs_kernel_namespace.
967                                   head.list, &ccs_ss) {                                   policy_list[CCS_ID_MANAGER], head.list,
968                                     &ccs_ss) {
969                  if (ptr->head.is_deleted)                  if (ptr->head.is_deleted)
970                          continue;                          continue;
971                  if (ptr->is_domain) {                  if (ptr->is_domain) {
# Line 903  static bool ccs_manager(void) Line 994  static bool ccs_manager(void)
994  }  }
995    
996  /**  /**
997   * ccs_select_one - Parse select command.   * ccs_select_domain - Parse select command.
998   *   *
999   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1000   * @data: String to parse.   * @data: String to parse.
# Line 912  static bool ccs_manager(void) Line 1003  static bool ccs_manager(void)
1003   *   *
1004   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1005   */   */
1006  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)
1007  {  {
1008          unsigned int pid;          unsigned int pid;
1009          struct ccs_domain_info *domain = NULL;          struct ccs_domain_info *domain = NULL;
1010          bool global_pid = false;          bool global_pid = false;
1011          if (!strcmp(data, "execute")) {          if (strncmp(data, "select ", 7))
1012                  head->r.print_execute_only = true;                  return false;
1013                  return true;          data += 7;
         }  
1014          if (sscanf(data, "pid=%u", &pid) == 1 ||          if (sscanf(data, "pid=%u", &pid) == 1 ||
1015              (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {              (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
1016                  struct task_struct *p;                  struct task_struct *p;
# Line 938  static bool ccs_select_one(struct ccs_io Line 1028  static bool ccs_select_one(struct ccs_io
1028                          domain = ccs_task_domain(p);                          domain = ccs_task_domain(p);
1029                  ccs_tasklist_unlock();                  ccs_tasklist_unlock();
1030          } else if (!strncmp(data, "domain=", 7)) {          } else if (!strncmp(data, "domain=", 7)) {
1031                  if (ccs_domain_def(data + 7))                  if (*(data + 7) == '<')
1032                          domain = ccs_find_domain(data + 7);                          domain = ccs_find_domain(data + 7);
1033          } else          } else
1034                  return false;                  return false;
# Line 996  static bool ccs_same_task_acl(const stru Line 1086  static bool ccs_same_task_acl(const stru
1086   * @param: Pointer to "struct ccs_acl_param".   * @param: Pointer to "struct ccs_acl_param".
1087   *   *
1088   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1089     *
1090     * Caller holds ccs_read_lock().
1091   */   */
1092  static int ccs_write_task(struct ccs_acl_param *param)  static int ccs_write_task(struct ccs_acl_param *param)
1093  {  {
# Line 1044  static int ccs_write_task(struct ccs_acl Line 1136  static int ccs_write_task(struct ccs_acl
1136  /**  /**
1137   * ccs_write_domain2 - Write domain policy.   * ccs_write_domain2 - Write domain policy.
1138   *   *
1139     * @ns:        Pointer to "struct ccs_policy_namespace".
1140     * @list:      Pointer to "struct list_head".
1141   * @data:      Policy to be interpreted.   * @data:      Policy to be interpreted.
  * @domain:    Pointer to "struct ccs_domain_info".  
1142   * @is_delete: True if it is a delete request.   * @is_delete: True if it is a delete request.
1143   *   *
1144   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1145     *
1146     * Caller holds ccs_read_lock().
1147   */   */
1148  static int ccs_write_domain2(char *data, struct ccs_domain_info *domain,  static int ccs_write_domain2(struct ccs_policy_namespace *ns,
1149                                 struct list_head *list, char *data,
1150                               const bool is_delete)                               const bool is_delete)
1151  {  {
1152          struct ccs_acl_param param = {          struct ccs_acl_param param = {
1153                    .ns = ns,
1154                    .list = list,
1155                  .data = data,                  .data = data,
                 .domain = domain,  
1156                  .is_delete = is_delete,                  .is_delete = is_delete,
1157          };          };
1158          static const struct {          static const struct {
# Line 1067  static int ccs_write_domain2(char *data, Line 1164  static int ccs_write_domain2(char *data,
1164                  { "network unix ", ccs_write_unix_network },                  { "network unix ", ccs_write_unix_network },
1165                  { "misc ", ccs_write_misc },                  { "misc ", ccs_write_misc },
1166                  { "capability ", ccs_write_capability },                  { "capability ", ccs_write_capability },
1167                  { "ipc ", ccs_write_ipc },                  { "ipc signal ", ccs_write_ipc },
1168                  { "task ", ccs_write_task },                  { "task ", ccs_write_task },
1169          };          };
1170          u8 i;          u8 i;
1171          for (i = 0; i < 7; i++) {          for (i = 0; i < ARRAY_SIZE(ccs_callback); i++) {
1172                  if (!ccs_str_starts(&param.data, ccs_callback[i].keyword))                  if (!ccs_str_starts(&param.data, ccs_callback[i].keyword))
1173                          continue;                          continue;
1174                  return ccs_callback[i].write(&param);                  return ccs_callback[i].write(&param);
# Line 1079  static int ccs_write_domain2(char *data, Line 1176  static int ccs_write_domain2(char *data,
1176          return -EINVAL;          return -EINVAL;
1177  }  }
1178    
1179    /**
1180     * ccs_delete_domain - Delete a domain.
1181     *
1182     * @domainname: The name of domain.
1183     *
1184     * Returns 0.
1185     */
1186    static int ccs_delete_domain(char *domainname)
1187    {
1188            struct ccs_domain_info *domain;
1189            struct ccs_path_info name;
1190            name.name = domainname;
1191            ccs_fill_path_info(&name);
1192            if (mutex_lock_interruptible(&ccs_policy_lock))
1193                    return 0;
1194            /* Is there an active domain? */
1195            list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
1196                    /* Never delete ccs_kernel_domain. */
1197                    if (domain == &ccs_kernel_domain)
1198                            continue;
1199                    if (domain->is_deleted ||
1200                        ccs_pathcmp(domain->domainname, &name))
1201                            continue;
1202                    domain->is_deleted = true;
1203                    break;
1204            }
1205            mutex_unlock(&ccs_policy_lock);
1206            return 0;
1207    }
1208    
1209  /* String table for domain flags. */  /* String table for domain flags. */
1210  const char * const ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = {  const char * const ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = {
1211          [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 1218  const char * const ccs_dif[CCS_MAX_DOMAI
1218   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1219   *   *
1220   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1221     *
1222     * Caller holds ccs_read_lock().
1223   */   */
1224  static int ccs_write_domain(struct ccs_io_buffer *head)  static int ccs_write_domain(struct ccs_io_buffer *head)
1225  {  {
1226          char *data = head->write_buf;          char *data = head->write_buf;
1227            struct ccs_policy_namespace *ns;
1228          struct ccs_domain_info *domain = head->w.domain;          struct ccs_domain_info *domain = head->w.domain;
1229          bool is_delete = false;          const bool is_delete = head->w.is_delete;
1230          bool is_select = false;          const bool is_select = !is_delete && ccs_str_starts(&data, "select ");
1231          unsigned int profile;          unsigned int profile;
1232          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)) {  
1233                  domain = NULL;                  domain = NULL;
1234                  if (is_delete)                  if (is_delete)
1235                          ccs_delete_domain(data);                          ccs_delete_domain(data);
1236                  else if (is_select)                  else if (is_select)
1237                          domain = ccs_find_domain(data);                          domain = ccs_find_domain(data);
1238                  else                  else
1239                          domain = ccs_assign_domain(data, 0, 0, false);                          domain = ccs_assign_domain(data, false);
1240                  head->w.domain = domain;                  head->w.domain = domain;
1241                  return 0;                  return 0;
1242          }          }
1243          if (!domain)          if (!domain)
1244                  return -EINVAL;                  return -EINVAL;
1245            ns = domain->ns;
1246          if (sscanf(data, "use_profile %u\n", &profile) == 1          if (sscanf(data, "use_profile %u\n", &profile) == 1
1247              && profile < CCS_MAX_PROFILES) {              && profile < CCS_MAX_PROFILES) {
1248                  if (!ccs_policy_loaded || ccs_profile_ptr[(u8) profile])                  if (!ccs_policy_loaded || ns->profile_ptr[(u8) profile])
1249                          if (!is_delete)                          if (!is_delete)
1250                                  domain->profile = (u8) profile;                                  domain->profile = (u8) profile;
1251                  return 0;                  return 0;
# Line 1142  static int ccs_write_domain(struct ccs_i Line 1263  static int ccs_write_domain(struct ccs_i
1263                  domain->flags[profile] = !is_delete;                  domain->flags[profile] = !is_delete;
1264                  return 0;                  return 0;
1265          }          }
1266          return ccs_write_domain2(data, domain, is_delete);          return ccs_write_domain2(ns, &domain->acl_info_list, data, is_delete);
1267  }  }
1268    
1269  /**  /**
# Line 1156  static int ccs_write_domain(struct ccs_i Line 1277  static int ccs_write_domain(struct ccs_i
1277  static void ccs_print_name_union(struct ccs_io_buffer *head,  static void ccs_print_name_union(struct ccs_io_buffer *head,
1278                                   const struct ccs_name_union *ptr)                                   const struct ccs_name_union *ptr)
1279  {  {
1280          const bool cond = head->r.print_cond_part;          ccs_set_space(head);
1281          if (!cond)          if (ptr->group) {
                 ccs_set_space(head);  
         if (ptr->is_group) {  
1282                  ccs_set_string(head, "@");                  ccs_set_string(head, "@");
1283                  ccs_set_string(head, ptr->group->group_name->name);                  ccs_set_string(head, ptr->group->group_name->name);
1284          } else {          } else {
                 if (cond)  
                         ccs_set_string(head, "\"");  
1285                  ccs_set_string(head, ptr->filename->name);                  ccs_set_string(head, ptr->filename->name);
                 if (cond)  
                         ccs_set_string(head, "\"");  
1286          }          }
1287  }  }
1288    
1289  /**  /**
1290   * ccs_print_number_union - Print a ccs_number_union.   * ccs_print_name_union_quoted - Print a ccs_name_union with a quote.
1291     *
1292     * @head: Pointer to "struct ccs_io_buffer".
1293     * @ptr:  Pointer to "struct ccs_name_union".
1294     *
1295     * Returns nothing.
1296     */
1297    static void ccs_print_name_union_quoted(struct ccs_io_buffer *head,
1298                                            const struct ccs_name_union *ptr)
1299    {
1300            if (ptr->group) {
1301                    ccs_set_string(head, "@");
1302                    ccs_set_string(head, ptr->group->group_name->name);
1303            } else {
1304                    ccs_set_string(head, "\"");
1305                    ccs_set_string(head, ptr->filename->name);
1306                    ccs_set_string(head, "\"");
1307            }
1308    }
1309    
1310    /**
1311     * ccs_print_number_union_nospace - Print a ccs_number_union without a space.
1312   *   *
1313   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1314   * @ptr:  Pointer to "struct ccs_number_union".   * @ptr:  Pointer to "struct ccs_number_union".
1315   *   *
1316   * Returns nothing.   * Returns nothing.
1317   */   */
1318  static void ccs_print_number_union(struct ccs_io_buffer *head,  static void ccs_print_number_union_nospace(struct ccs_io_buffer *head,
1319                                     const struct ccs_number_union *ptr)                                             const struct ccs_number_union *ptr)
1320  {  {
1321          if (!head->r.print_cond_part)          if (ptr->group) {
                 ccs_set_space(head);  
         if (ptr->is_group) {  
1322                  ccs_set_string(head, "@");                  ccs_set_string(head, "@");
1323                  ccs_set_string(head, ptr->group->group_name->name);                  ccs_set_string(head, ptr->group->group_name->name);
1324          } else {          } else {
# Line 1221  static void ccs_print_number_union(struc Line 1355  static void ccs_print_number_union(struc
1355  }  }
1356    
1357  /**  /**
1358     * ccs_print_number_union - Print a ccs_number_union.
1359     *
1360     * @head: Pointer to "struct ccs_io_buffer".
1361     * @ptr:  Pointer to "struct ccs_number_union".
1362     *
1363     * Returns nothing.
1364     */
1365    static void ccs_print_number_union(struct ccs_io_buffer *head,
1366                                       const struct ccs_number_union *ptr)
1367    {
1368            ccs_set_space(head);
1369            ccs_print_number_union_nospace(head, ptr);
1370    }
1371    
1372    /**
1373   * ccs_print_condition - Print condition part.   * ccs_print_condition - Print condition part.
1374   *   *
1375   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
# Line 1235  static bool ccs_print_condition(struct c Line 1384  static bool ccs_print_condition(struct c
1384          case 0:          case 0:
1385                  head->r.cond_index = 0;                  head->r.cond_index = 0;
1386                  head->r.cond_step++;                  head->r.cond_step++;
1387                    if (cond->transit && cond->exec_transit) {
1388                            ccs_set_space(head);
1389                            ccs_set_string(head, cond->transit->name);
1390                    }
1391                  /* fall through */                  /* fall through */
1392          case 1:          case 1:
1393                  {                  {
# Line 1287  static bool ccs_print_condition(struct c Line 1440  static bool ccs_print_condition(struct c
1440                                  switch (left) {                                  switch (left) {
1441                                  case CCS_ARGV_ENTRY:                                  case CCS_ARGV_ENTRY:
1442                                          ccs_io_printf(head,                                          ccs_io_printf(head,
1443                                                        "exec.argv[%u]%s\"%s\"",                                                        "exec.argv[%lu]%s=\"",
1444                                                        argv->index,                                                        argv->index,
1445                                                        argv->is_not ?                                                        argv->is_not ? "!" : "");
1446                                                        "!=" : "=",                                          ccs_set_string(head,
1447                                                        argv->value->name);                                                         argv->value->name);
1448                                            ccs_set_string(head, "\"");
1449                                          argv++;                                          argv++;
1450                                          continue;                                          continue;
1451                                  case CCS_ENVP_ENTRY:                                  case CCS_ENVP_ENTRY:
1452                                          ccs_io_printf(head,                                          ccs_set_string(head, "exec.envp[\"");
1453                                                        "exec.envp[\"%s\"]%s",                                          ccs_set_string(head, envp->name->name);
1454                                                        envp->name->name,                                          ccs_io_printf(head, "\"]%s=",
1455                                                        envp->is_not ?                                                        envp->is_not ? "!" : "");
                                                       "!=" : "=");  
1456                                          if (envp->value) {                                          if (envp->value) {
1457                                                  ccs_set_string(head, "\"");                                                  ccs_set_string(head, "\"");
1458                                                  ccs_set_string(head, envp->                                                  ccs_set_string(head, envp->
# Line 1311  static bool ccs_print_condition(struct c Line 1464  static bool ccs_print_condition(struct c
1464                                          envp++;                                          envp++;
1465                                          continue;                                          continue;
1466                                  case CCS_NUMBER_UNION:                                  case CCS_NUMBER_UNION:
1467                                          ccs_print_number_union(head,                                          ccs_print_number_union_nospace
1468                                                                 numbers_p++);                                                  (head, numbers_p++);
1469                                          break;                                          break;
1470                                  default:                                  default:
1471                                          ccs_set_string(head,                                          ccs_set_string(head,
# Line 1322  static bool ccs_print_condition(struct c Line 1475  static bool ccs_print_condition(struct c
1475                                  ccs_set_string(head, match ? "=" : "!=");                                  ccs_set_string(head, match ? "=" : "!=");
1476                                  switch (right) {                                  switch (right) {
1477                                  case CCS_NAME_UNION:                                  case CCS_NAME_UNION:
1478                                          ccs_print_name_union(head, names_p++);                                          ccs_print_name_union_quoted
1479                                                    (head, names_p++);
1480                                          break;                                          break;
1481                                  case CCS_NUMBER_UNION:                                  case CCS_NUMBER_UNION:
1482                                          ccs_print_number_union(head,                                          ccs_print_number_union_nospace
1483                                                                 numbers_p++);                                                  (head, numbers_p++);
1484                                          break;                                          break;
1485                                  default:                                  default:
1486                                          ccs_set_string(head,                                          ccs_set_string(head,
# Line 1347  static bool ccs_print_condition(struct c Line 1501  static bool ccs_print_condition(struct c
1501                          ccs_io_printf(head, " grant_log=%s",                          ccs_io_printf(head, " grant_log=%s",
1502                                        ccs_yesno(cond->grant_log ==                                        ccs_yesno(cond->grant_log ==
1503                                                  CCS_GRANTLOG_YES));                                                  CCS_GRANTLOG_YES));
1504                  if (cond->transit) {                  if (cond->transit && !cond->exec_transit) {
1505                            const char *name = cond->transit->name;
1506                          ccs_set_string(head, " auto_domain_transition=\"");                          ccs_set_string(head, " auto_domain_transition=\"");
1507                          ccs_set_string(head, cond->transit->name);                          ccs_set_string(head, name);
1508                          ccs_set_string(head, "\"");                          ccs_set_string(head, "\"");
1509                  }                  }
1510                  ccs_set_lf(head);                  ccs_set_lf(head);
# Line 1359  static bool ccs_print_condition(struct c Line 1514  static bool ccs_print_condition(struct c
1514  }  }
1515    
1516  /**  /**
1517   * 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.  
1518   *   *
1519   * @head: Pointer to "struct ccs_io_buffer".   * @head:     Pointer to "struct ccs_io_buffer".
1520     * @category: Category name.
1521   *   *
1522   * Returns nothing.   * Returns nothing.
1523   */   */
1524  static void ccs_set_group(struct ccs_io_buffer *head)  static void ccs_set_group(struct ccs_io_buffer *head, const char *category)
1525  {  {
1526          if (head->type == CCS_EXCEPTIONPOLICY)          if (head->type == CCS_EXCEPTIONPOLICY) {
1527                  ccs_io_printf(head, "acl_group %u ", head->r.group_index);                  ccs_print_namespace(head);
1528                    ccs_io_printf(head, "acl_group %u ", head->r.acl_group_index);
1529            }
1530            ccs_set_string(head, category);
1531  }  }
1532    
1533  /**  /**
# Line 1399  static bool ccs_print_entry(struct ccs_i Line 1542  static bool ccs_print_entry(struct ccs_i
1542                              const struct ccs_acl_info *acl)                              const struct ccs_acl_info *acl)
1543  {  {
1544          const u8 acl_type = acl->type;          const u8 acl_type = acl->type;
1545            const bool may_trigger_transition = acl->cond && acl->cond->transit;
1546            bool first = true;
1547          u8 bit;          u8 bit;
1548          if (head->r.print_cond_part)          if (head->r.print_cond_part)
1549                  goto print_cond_part;                  goto print_cond_part;
1550          if (acl->is_deleted)          if (acl->is_deleted)
1551                  return true;                  return true;
 next:  
         bit = head->r.bit;  
1552          if (!ccs_flush(head))          if (!ccs_flush(head))
1553                  return false;                  return false;
1554          else if (acl_type == CCS_TYPE_PATH_ACL) {          else if (acl_type == CCS_TYPE_PATH_ACL) {
1555                  struct ccs_path_acl *ptr                  struct ccs_path_acl *ptr
1556                          = container_of(acl, typeof(*ptr), head);                          = container_of(acl, typeof(*ptr), head);
1557                  const u16 perm = ptr->perm;                  const u16 perm = ptr->perm;
1558                  for ( ; bit < CCS_MAX_PATH_OPERATION; bit++) {                  for (bit = 0; bit < CCS_MAX_PATH_OPERATION; bit++) {
1559                          if (!(perm & (1 << bit)))                          if (!(perm & (1 << bit)))
1560                                  continue;                                  continue;
1561                          if (head->r.print_execute_only &&                          if (head->r.print_transition_related_only &&
1562                              bit != CCS_TYPE_EXECUTE                              bit != CCS_TYPE_EXECUTE && !may_trigger_transition)
                             /* && bit != CCS_TYPE_TRANSIT */)  
1563                                  continue;                                  continue;
1564                          break;                          if (first) {
1565                                    ccs_set_group(head, "file ");
1566                                    first = false;
1567                            } else {
1568                                    ccs_set_slash(head);
1569                            }
1570                            ccs_set_string(head, ccs_path_keyword[bit]);
1571                  }                  }
1572                  if (bit >= CCS_MAX_PATH_OPERATION)                  if (first)
1573                          goto done;                          return true;
                 ccs_set_group(head);  
                 ccs_set_string(head, "file ");  
                 ccs_set_string(head, ccs_path_keyword[bit]);  
1574                  ccs_print_name_union(head, &ptr->name);                  ccs_print_name_union(head, &ptr->name);
1575          } else if (acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER ||          } else if (acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER ||
1576                     acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {                     acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {
1577                  struct ccs_handler_acl *ptr                  struct ccs_handler_acl *ptr
1578                          = container_of(acl, typeof(*ptr), head);                          = container_of(acl, typeof(*ptr), head);
1579                  ccs_set_group(head);                  ccs_set_group(head, "task ");
                 ccs_set_string(head, "task ");  
1580                  ccs_set_string(head, acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER                  ccs_set_string(head, acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER
1581                                 ? "auto_execute_handler " :                                 ? "auto_execute_handler " :
1582                                 "denied_execute_handler ");                                 "denied_execute_handler ");
# Line 1441  next: Line 1585  next:
1585                     acl_type == CCS_TYPE_MANUAL_TASK_ACL) {                     acl_type == CCS_TYPE_MANUAL_TASK_ACL) {
1586                  struct ccs_task_acl *ptr =                  struct ccs_task_acl *ptr =
1587                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1588                  ccs_set_group(head);                  ccs_set_group(head, "task ");
                 ccs_set_string(head, "task ");  
1589                  ccs_set_string(head, acl_type == CCS_TYPE_AUTO_TASK_ACL ?                  ccs_set_string(head, acl_type == CCS_TYPE_AUTO_TASK_ACL ?
1590                                 "auto_domain_transition " :                                 "auto_domain_transition " :
1591                                 "manual_domain_transition ");                                 "manual_domain_transition ");
1592                  ccs_set_string(head, ptr->domainname->name);                  ccs_set_string(head, ptr->domainname->name);
1593          } else if (head->r.print_execute_only) {          } else if (head->r.print_transition_related_only &&
1594                       !may_trigger_transition) {
1595                  return true;                  return true;
1596          } else if (acl_type == CCS_TYPE_MKDEV_ACL) {          } else if (acl_type == CCS_TYPE_MKDEV_ACL) {
1597                  struct ccs_mkdev_acl *ptr =                  struct ccs_mkdev_acl *ptr =
1598                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1599                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1600                  if (bit >= CCS_MAX_MKDEV_OPERATION)                  for (bit = 0; bit < CCS_MAX_MKDEV_OPERATION; bit++) {
1601                          goto done;                          if (!(perm & (1 << bit)))
1602                  ccs_set_group(head);                                  continue;
1603                  ccs_set_string(head, "file ");                          if (first) {
1604                  ccs_set_string(head, ccs_mac_keywords[ccs_pnnn2mac[bit]]);                                  ccs_set_group(head, "file ");
1605                                    first = false;
1606                            } else {
1607                                    ccs_set_slash(head);
1608                            }
1609                            ccs_set_string(head, ccs_mac_keywords
1610                                           [ccs_pnnn2mac[bit]]);
1611                    }
1612                    if (first)
1613                            return true;
1614                  ccs_print_name_union(head, &ptr->name);                  ccs_print_name_union(head, &ptr->name);
1615                  ccs_print_number_union(head, &ptr->mode);                  ccs_print_number_union(head, &ptr->mode);
1616                  ccs_print_number_union(head, &ptr->major);                  ccs_print_number_union(head, &ptr->major);
# Line 1465  next: Line 1618  next:
1618          } else if (acl_type == CCS_TYPE_PATH2_ACL) {          } else if (acl_type == CCS_TYPE_PATH2_ACL) {
1619                  struct ccs_path2_acl *ptr =                  struct ccs_path2_acl *ptr =
1620                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1621                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1622                  if (bit >= CCS_MAX_PATH2_OPERATION)                  for (bit = 0; bit < CCS_MAX_PATH2_OPERATION; bit++) {
1623                          goto done;                          if (!(perm & (1 << bit)))
1624                  ccs_set_group(head);                                  continue;
1625                  ccs_set_string(head, "file ");                          if (first) {
1626                  ccs_set_string(head, ccs_mac_keywords[ccs_pp2mac[bit]]);                                  ccs_set_group(head, "file ");
1627                                    first = false;
1628                            } else {
1629                                    ccs_set_slash(head);
1630                            }
1631                            ccs_set_string(head, ccs_mac_keywords
1632                                           [ccs_pp2mac[bit]]);
1633                    }
1634                    if (first)
1635                            return true;
1636                  ccs_print_name_union(head, &ptr->name1);                  ccs_print_name_union(head, &ptr->name1);
1637                  ccs_print_name_union(head, &ptr->name2);                  ccs_print_name_union(head, &ptr->name2);
1638          } else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {          } else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
1639                  struct ccs_path_number_acl *ptr =                  struct ccs_path_number_acl *ptr =
1640                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1641                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1642                  if (bit >= CCS_MAX_PATH_NUMBER_OPERATION)                  for (bit = 0; bit < CCS_MAX_PATH_NUMBER_OPERATION; bit++) {
1643                          goto done;                          if (!(perm & (1 << bit)))
1644                  ccs_set_group(head);                                  continue;
1645                  ccs_set_string(head, "file ");                          if (first) {
1646                  ccs_set_string(head, ccs_mac_keywords[ccs_pn2mac[bit]]);                                  ccs_set_group(head, "file ");
1647                                    first = false;
1648                            } else {
1649                                    ccs_set_slash(head);
1650                            }
1651                            ccs_set_string(head, ccs_mac_keywords
1652                                           [ccs_pn2mac[bit]]);
1653                    }
1654                    if (first)
1655                            return true;
1656                  ccs_print_name_union(head, &ptr->name);                  ccs_print_name_union(head, &ptr->name);
1657                  ccs_print_number_union(head, &ptr->number);                  ccs_print_number_union(head, &ptr->number);
1658          } else if (acl_type == CCS_TYPE_ENV_ACL) {          } else if (acl_type == CCS_TYPE_ENV_ACL) {
1659                  struct ccs_env_acl *ptr =                  struct ccs_env_acl *ptr =
1660                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1661                  ccs_set_group(head);                  ccs_set_group(head, "misc env ");
                 ccs_set_string(head, "misc env ");  
1662                  ccs_set_string(head, ptr->env->name);                  ccs_set_string(head, ptr->env->name);
1663          } else if (acl_type == CCS_TYPE_CAPABILITY_ACL) {          } else if (acl_type == CCS_TYPE_CAPABILITY_ACL) {
1664                  struct ccs_capability_acl *ptr =                  struct ccs_capability_acl *ptr =
1665                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1666                  ccs_set_group(head);                  ccs_set_group(head, "capability ");
1667                  ccs_set_string(head, "capability ");                  ccs_set_string(head, ccs_mac_keywords
1668                  ccs_set_string(head,                                 [ccs_c2mac[ptr->operation]]);
                                ccs_mac_keywords[ccs_c2mac[ptr->operation]]);  
1669          } else if (acl_type == CCS_TYPE_INET_ACL) {          } else if (acl_type == CCS_TYPE_INET_ACL) {
1670                  struct ccs_inet_acl *ptr =                  struct ccs_inet_acl *ptr =
1671                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1672                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1673                  if (bit >= CCS_MAX_NETWORK_OPERATION)                  for (bit = 0; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
1674                          goto done;                          if (!(perm & (1 << bit)))
1675                  ccs_set_group(head);                                  continue;
1676                  ccs_set_string(head, "network inet ");                          if (first) {
1677                  ccs_set_string(head, ccs_proto_keyword[ptr->protocol]);                                  ccs_set_group(head, "network inet ");
1678                  ccs_set_space(head);                                  ccs_set_string(head, ccs_proto_keyword
1679                  ccs_set_string(head, ccs_socket_keyword[bit]);                                                 [ptr->protocol]);
1680                                    ccs_set_space(head);
1681                                    first = false;
1682                            } else {
1683                                    ccs_set_slash(head);
1684                            }
1685                            ccs_set_string(head, ccs_socket_keyword[bit]);
1686                    }
1687                    if (first)
1688                            return true;
1689                  ccs_set_space(head);                  ccs_set_space(head);
1690                  switch (ptr->address_type) {                  if (ptr->address.group) {
                         char buf[128];  
                 case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP:  
1691                          ccs_set_string(head, "@");                          ccs_set_string(head, "@");
1692                          ccs_set_string(head,                          ccs_set_string(head,
1693                                         ptr->address.group->group_name->name);                                         ptr->address.group->group_name->name);
1694                          break;                  } else {
1695                  case CCS_IP_ADDRESS_TYPE_IPv4:                          char buf[128];
1696                          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);  
1697                          ccs_io_printf(head, "%s", buf);                          ccs_io_printf(head, "%s", buf);
                         break;  
1698                  }                  }
1699                  ccs_print_number_union(head, &ptr->port);                  ccs_print_number_union(head, &ptr->port);
1700          } else if (acl_type == CCS_TYPE_UNIX_ACL) {          } else if (acl_type == CCS_TYPE_UNIX_ACL) {
1701                  struct ccs_unix_acl *ptr =                  struct ccs_unix_acl *ptr =
1702                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1703                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1704                  if (bit >= CCS_MAX_NETWORK_OPERATION)                  for (bit = 0; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
1705                          goto done;                          if (!(perm & (1 << bit)))
1706                  ccs_set_group(head);                                  continue;
1707                  ccs_set_string(head, "network unix ");                          if (first) {
1708                  ccs_set_string(head, ccs_proto_keyword[ptr->protocol]);                                  ccs_set_group(head, "network unix ");
1709                  ccs_set_space(head);                                  ccs_set_string(head, ccs_proto_keyword
1710                  ccs_set_string(head, ccs_socket_keyword[bit]);                                                 [ptr->protocol]);
1711                                    ccs_set_space(head);
1712                                    first = false;
1713                            } else {
1714                                    ccs_set_slash(head);
1715                            }
1716                            ccs_set_string(head, ccs_socket_keyword[bit]);
1717                    }
1718                    if (first)
1719                            return true;
1720                  ccs_print_name_union(head, &ptr->name);                  ccs_print_name_union(head, &ptr->name);
1721          } else if (acl_type == CCS_TYPE_SIGNAL_ACL) {          } else if (acl_type == CCS_TYPE_SIGNAL_ACL) {
1722                  struct ccs_signal_acl *ptr =                  struct ccs_signal_acl *ptr =
1723                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1724                  ccs_set_group(head);                  ccs_set_group(head, "ipc signal ");
1725                  ccs_set_string(head, "ipc signal ");                  ccs_print_number_union_nospace(head, &ptr->sig);
1726                  ccs_io_printf(head, "%u ", ptr->sig);                  ccs_set_space(head);
1727                  ccs_set_string(head, ptr->domainname->name);                  ccs_set_string(head, ptr->domainname->name);
1728          } else if (acl_type == CCS_TYPE_MOUNT_ACL) {          } else if (acl_type == CCS_TYPE_MOUNT_ACL) {
1729                  struct ccs_mount_acl *ptr =                  struct ccs_mount_acl *ptr =
1730                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1731                  ccs_set_group(head);                  ccs_set_group(head, "file mount");
                 ccs_io_printf(head, "file mount");  
1732                  ccs_print_name_union(head, &ptr->dev_name);                  ccs_print_name_union(head, &ptr->dev_name);
1733                  ccs_print_name_union(head, &ptr->dir_name);                  ccs_print_name_union(head, &ptr->dir_name);
1734                  ccs_print_name_union(head, &ptr->fs_type);                  ccs_print_name_union(head, &ptr->fs_type);
1735                  ccs_print_number_union(head, &ptr->flags);                  ccs_print_number_union(head, &ptr->flags);
1736          }          }
         head->r.bit = bit + 1;  
1737          if (acl->cond) {          if (acl->cond) {
1738                  head->r.print_cond_part = true;                  head->r.print_cond_part = true;
1739                  head->r.cond_step = 0;                  head->r.cond_step = 0;
# Line 1570  print_cond_part: Line 1746  print_cond_part:
1746          } else {          } else {
1747                  ccs_set_lf(head);                  ccs_set_lf(head);
1748          }          }
         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;  
1749          return true;          return true;
1750  }  }
1751    
1752  /**  /**
1753   * ccs_read_domain2 - Read domain policy.   * ccs_read_domain2 - Read domain policy.
1754   *   *
1755   * @head:   Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1756   * @domain: Pointer to "struct ccs_domain_info".   * @list: Pointer to "struct list_head".
  * @index:  Index number.  
1757   *   *
1758   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1759   *   *
1760   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1761   */   */
1762  static bool ccs_read_domain2(struct ccs_io_buffer *head,  static bool ccs_read_domain2(struct ccs_io_buffer *head,
1763                               struct ccs_domain_info *domain,                               struct list_head *list)
                              const u8 index)  
1764  {  {
1765          list_for_each_cookie(head->r.acl, &domain->acl_info_list[index]) {          list_for_each_cookie(head->r.acl, list) {
1766                  struct ccs_acl_info *ptr =                  struct ccs_acl_info *ptr =
1767                          list_entry(head->r.acl, typeof(*ptr), list);                          list_entry(head->r.acl, typeof(*ptr), list);
1768                  if (!ccs_print_entry(head, ptr))                  if (!ccs_print_entry(head, ptr))
# Line 1644  static void ccs_read_domain(struct ccs_i Line 1807  static void ccs_read_domain(struct ccs_i
1807                          ccs_set_lf(head);                          ccs_set_lf(head);
1808                          /* fall through */                          /* fall through */
1809                  case 1:                  case 1:
1810                          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))  
1811                                  return;                                  return;
1812                          head->r.step++;                          head->r.step++;
1813                          if (!ccs_set_lf(head))                          if (!ccs_set_lf(head))
1814                                  return;                                  return;
1815                          /* fall through */                          /* fall through */
1816                  case 3:                  case 2:
1817                          head->r.step = 0;                          head->r.step = 0;
1818                          if (head->r.print_this_domain_only)                          if (head->r.print_this_domain_only)
1819                                  goto done;                                  goto done;
# Line 1666  done: Line 1824  done:
1824  }  }
1825    
1826  /**  /**
  * 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;  
 }  
   
 /**  
1827   * ccs_write_pid - Specify PID to obtain domainname.   * ccs_write_pid - Specify PID to obtain domainname.
1828   *   *
1829   * @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 1899  static void ccs_read_pid(struct ccs_io_b
1899    
1900  /* String table for domain transition control keywords. */  /* String table for domain transition control keywords. */
1901  static const char * const ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {  static const char * const ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {
1902            [CCS_TRANSITION_CONTROL_NO_RESET]      = "no_reset_domain ",
1903            [CCS_TRANSITION_CONTROL_RESET]         = "reset_domain ",
1904          [CCS_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ",          [CCS_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ",
1905          [CCS_TRANSITION_CONTROL_INITIALIZE]    = "initialize_domain ",          [CCS_TRANSITION_CONTROL_INITIALIZE]    = "initialize_domain ",
1906          [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 1923  static const char * const ccs_group_name
1923   */   */
1924  static int ccs_write_exception(struct ccs_io_buffer *head)  static int ccs_write_exception(struct ccs_io_buffer *head)
1925  {  {
1926          char *data = head->write_buf;          const bool is_delete = head->w.is_delete;
1927          const bool is_delete = ccs_str_starts(&data, "delete ");          struct ccs_acl_param param = {
1928          u8 i;                  .ns = head->w.ns,
1929          static const struct {                  .is_delete = is_delete,
1930                  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 },  
1931          };          };
1932          for (i = 0; i < 2; i++)          u8 i;
1933                  if (ccs_str_starts(&data, ccs_callback[i].keyword))          if (ccs_str_starts(&param.data, "aggregator "))
1934                          return ccs_callback[i].write(data, is_delete);                  return ccs_write_aggregator(&param);
1935            if (ccs_str_starts(&param.data, "deny_autobind "))
1936                    return ccs_write_reserved_port(&param);
1937          for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)          for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)
1938                  if (ccs_str_starts(&data, ccs_transition_type[i]))                  if (ccs_str_starts(&param.data, ccs_transition_type[i]))
1939                          return ccs_write_transition_control(data, is_delete,                          return ccs_write_transition_control(&param, i);
                                                             i);  
1940          for (i = 0; i < CCS_MAX_GROUP; i++)          for (i = 0; i < CCS_MAX_GROUP; i++)
1941                  if (ccs_str_starts(&data, ccs_group_name[i]))                  if (ccs_str_starts(&param.data, ccs_group_name[i]))
1942                          return ccs_write_group(data, is_delete, i);                          return ccs_write_group(&param, i);
1943          if (ccs_str_starts(&data, "acl_group ")) {          if (ccs_str_starts(&param.data, "acl_group ")) {
1944                  unsigned int group;                  unsigned int group;
1945                  if (sscanf(data, "%u", &group) == 1 &&                  char *data;
1946                      group < CCS_MAX_ACL_GROUPS) {                  group = simple_strtoul(param.data, &data, 10);
1947                          data = strchr(data, ' ');                  if (group < CCS_MAX_ACL_GROUPS && *data++ == ' ')
1948                          if (data)                          return ccs_write_domain2(head->w.ns,
1949                                  return ccs_write_domain2(data + 1,                                                   &head->w.ns->acl_group[group],
1950                                                           &ccs_acl_group[group],                                                   data, is_delete);
                                                          is_delete);  
                 }  
1951          }          }
1952          return -EINVAL;          return -EINVAL;
1953  }  }
# Line 1875  static int ccs_write_exception(struct cc Line 1964  static int ccs_write_exception(struct cc
1964   */   */
1965  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)
1966  {  {
1967          list_for_each_cookie(head->r.group, &ccs_group_list[idx]) {          struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
1968                                                           namespace_list);
1969            struct list_head *list = &ns->group_list[idx];
1970            list_for_each_cookie(head->r.group, list) {
1971                  struct ccs_group *group =                  struct ccs_group *group =
1972                          list_entry(head->r.group, typeof(*group), head.list);                          list_entry(head->r.group, typeof(*group), head.list);
1973                  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 1977  static bool ccs_read_group(struct ccs_io
1977                                  continue;                                  continue;
1978                          if (!ccs_flush(head))                          if (!ccs_flush(head))
1979                                  return false;                                  return false;
1980                            ccs_print_namespace(head);
1981                          ccs_set_string(head, ccs_group_name[idx]);                          ccs_set_string(head, ccs_group_name[idx]);
1982                          ccs_set_string(head, group->group_name->name);                          ccs_set_string(head, group->group_name->name);
1983                          if (idx == CCS_PATH_GROUP) {                          if (idx == CCS_PATH_GROUP) {
# Line 1901  static bool ccs_read_group(struct ccs_io Line 1994  static bool ccs_read_group(struct ccs_io
1994                                  struct ccs_address_group *member =                                  struct ccs_address_group *member =
1995                                          container_of(ptr, typeof(*member),                                          container_of(ptr, typeof(*member),
1996                                                       head);                                                       head);
1997                                  if (member->is_ipv6)                                  ccs_print_ip(buffer, sizeof(buffer),
1998                                          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);  
1999                                  ccs_io_printf(head, " %s", buffer);                                  ccs_io_printf(head, " %s", buffer);
2000                          }                          }
2001                          ccs_set_lf(head);                          ccs_set_lf(head);
# Line 1931  static bool ccs_read_group(struct ccs_io Line 2018  static bool ccs_read_group(struct ccs_io
2018   */   */
2019  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)
2020  {  {
2021          list_for_each_cookie(head->r.acl, &ccs_policy_list[idx]) {          struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
2022                                                           namespace_list);
2023            struct list_head *list = &ns->policy_list[idx];
2024            list_for_each_cookie(head->r.acl, list) {
2025                  struct ccs_acl_head *acl =                  struct ccs_acl_head *acl =
2026                          container_of(head->r.acl, typeof(*acl), list);                          container_of(head->r.acl, typeof(*acl), list);
2027                  if (acl->is_deleted)                  if (acl->is_deleted)
2028                          continue;                          continue;
2029                    if (head->r.print_transition_related_only &&
2030                        idx != CCS_ID_TRANSITION_CONTROL)
2031                            continue;
2032                  if (!ccs_flush(head))                  if (!ccs_flush(head))
2033                          return false;                          return false;
2034                  switch (idx) {                  switch (idx) {
# Line 1943  static bool ccs_read_policy(struct ccs_i Line 2036  static bool ccs_read_policy(struct ccs_i
2036                          {                          {
2037                                  struct ccs_transition_control *ptr =                                  struct ccs_transition_control *ptr =
2038                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
2039                                    ccs_print_namespace(head);
2040                                  ccs_set_string(head,                                  ccs_set_string(head,
2041                                                 ccs_transition_type[ptr->type]);                                                 ccs_transition_type[ptr->type]);
2042                                  ccs_set_string(head, ptr->program ?                                  ccs_set_string(head, ptr->program ?
# Line 1956  static bool ccs_read_policy(struct ccs_i Line 2050  static bool ccs_read_policy(struct ccs_i
2050                          {                          {
2051                                  struct ccs_aggregator *ptr =                                  struct ccs_aggregator *ptr =
2052                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
2053                                    ccs_print_namespace(head);
2054                                  ccs_set_string(head, "aggregator ");                                  ccs_set_string(head, "aggregator ");
2055                                  ccs_set_string(head, ptr->original_name->name);                                  ccs_set_string(head, ptr->original_name->name);
2056                                  ccs_set_space(head);                                  ccs_set_space(head);
# Line 1967  static bool ccs_read_policy(struct ccs_i Line 2062  static bool ccs_read_policy(struct ccs_i
2062                          {                          {
2063                                  struct ccs_reserved *ptr =                                  struct ccs_reserved *ptr =
2064                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
2065                                  const u16 min_port = ptr->min_port;                                  ccs_print_namespace(head);
                                 const u16 max_port = ptr->max_port;  
2066                                  ccs_set_string(head, "deny_autobind ");                                  ccs_set_string(head, "deny_autobind ");
2067                                  ccs_io_printf(head, "%u", min_port);                                  ccs_print_number_union_nospace(head,
2068                                  if (min_port != max_port)                                                                 &ptr->port);
                                         ccs_io_printf(head, "-%u", max_port);  
2069                          }                          }
2070                          break;                          break;
2071                  default:                  default:
# Line 1995  static bool ccs_read_policy(struct ccs_i Line 2088  static bool ccs_read_policy(struct ccs_i
2088   */   */
2089  static void ccs_read_exception(struct ccs_io_buffer *head)  static void ccs_read_exception(struct ccs_io_buffer *head)
2090  {  {
2091            struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
2092                                                           namespace_list);
2093          if (head->r.eof)          if (head->r.eof)
2094                  return;                  return;
2095          while (head->r.step < CCS_MAX_POLICY &&          while (head->r.step < CCS_MAX_POLICY &&
# Line 2008  static void ccs_read_exception(struct cc Line 2103  static void ccs_read_exception(struct cc
2103          if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP)          if (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP)
2104                  return;                  return;
2105          while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP          while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP
2106                 + CCS_MAX_ACL_GROUPS * 2) {                 + CCS_MAX_ACL_GROUPS) {
2107                  head->r.group_index = (head->r.step - CCS_MAX_POLICY                  head->r.acl_group_index =
2108                                         - CCS_MAX_GROUP) / 2;                          head->r.step - CCS_MAX_POLICY - CCS_MAX_GROUP;
2109                  if (!ccs_read_domain2(head,                  if (!ccs_read_domain2(head, &ns->acl_group
2110                                        &ccs_acl_group[head->r.group_index],                                        [head->r.acl_group_index]))
                                       head->r.step & 1))  
2111                          return;                          return;
2112                  head->r.step++;                  head->r.step++;
2113          }          }
# Line 2029  static DECLARE_WAIT_QUEUE_HEAD(ccs_answe Line 2123  static DECLARE_WAIT_QUEUE_HEAD(ccs_answe
2123  struct ccs_query {  struct ccs_query {
2124          struct list_head list;          struct list_head list;
2125          char *query;          char *query;
2126          int query_len;          size_t query_len;
2127          unsigned int serial;          unsigned int serial;
2128          int timer;          u8 timer;
2129          int answer;          u8 answer;
2130          u8 retry;          u8 retry;
2131  };  };
2132    
# Line 2116  static void ccs_add_entry(char *header) Line 2210  static void ccs_add_entry(char *header)
2210          if (symlink)          if (symlink)
2211                  ccs_addprintf(buffer, len, "%s", symlink);                  ccs_addprintf(buffer, len, "%s", symlink);
2212          ccs_normalize_line(buffer);          ccs_normalize_line(buffer);
2213          if (!ccs_write_domain2(buffer, ccs_current_domain(), false))          {
2214                  ccs_update_stat(CCS_STAT_POLICY_UPDATES);                  struct ccs_domain_info *domain = ccs_current_domain();
2215                    if (!ccs_write_domain2(domain->ns, &domain->acl_info_list,
2216                                           buffer, false))
2217                            ccs_update_stat(CCS_STAT_POLICY_UPDATES);
2218            }
2219          kfree(buffer);          kfree(buffer);
2220  }  }
2221    
# Line 2170  int ccs_supervisor(struct ccs_request_in Line 2268  int ccs_supervisor(struct ccs_request_in
2268                  goto out;                  goto out;
2269          case CCS_CONFIG_LEARNING:          case CCS_CONFIG_LEARNING:
2270                  error = 0;                  error = 0;
2271                  /* Check mac_learning_entry parameter. */                  /* Check max_learning_entry parameter. */
2272                  if (ccs_domain_quota_ok(r))                  if (ccs_domain_quota_ok(r))
2273                          break;                          break;
2274                  /* fall through */                  /* fall through */
# Line 2280  static int ccs_poll_query(struct file *f Line 2378  static int ccs_poll_query(struct file *f
2378  static void ccs_read_query(struct ccs_io_buffer *head)  static void ccs_read_query(struct ccs_io_buffer *head)
2379  {  {
2380          struct list_head *tmp;          struct list_head *tmp;
2381          int pos = 0;          unsigned int pos = 0;
2382          int len = 0;          size_t len = 0;
2383          char *buf;          char *buf;
2384          if (head->r.w_pos)          if (head->r.w_pos)
2385                  return;                  return;
# Line 2318  static void ccs_read_query(struct ccs_io Line 2416  static void ccs_read_query(struct ccs_io
2416                   * can change, but I don't care.                   * can change, but I don't care.
2417                   */                   */
2418                  if (len == ptr->query_len)                  if (len == ptr->query_len)
2419                          snprintf(buf, len + 32, "Q%u-%hu\n%s", ptr->serial,                          snprintf(buf, len + 31, "Q%u-%hu\n%s", ptr->serial,
2420                                   ptr->retry, ptr->query);                                   ptr->retry, ptr->query);
2421                  break;                  break;
2422          }          }
# Line 2359  static int ccs_write_answer(struct ccs_i Line 2457  static int ccs_write_answer(struct ccs_i
2457                  if (ptr->serial != serial)                  if (ptr->serial != serial)
2458                          continue;                          continue;
2459                  if (!ptr->answer)                  if (!ptr->answer)
2460                          ptr->answer = answer;                          ptr->answer = (u8) answer;
2461                  break;                  break;
2462          }          }
2463          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
# Line 2378  static void ccs_read_version(struct ccs_ Line 2476  static void ccs_read_version(struct ccs_
2476  {  {
2477          if (head->r.eof)          if (head->r.eof)
2478                  return;                  return;
2479          ccs_set_string(head, "1.8.0");          ccs_set_string(head, "1.8.3-pre");
2480          head->r.eof = true;          head->r.eof = true;
2481  }  }
2482    
2483  /* String table for /proc/ccs/meminfo interface. */  /* String table for /proc/ccs/stat interface. */
2484  static const char * const ccs_policy_headers[CCS_MAX_POLICY_STAT] = {  static const char * const ccs_policy_headers[CCS_MAX_POLICY_STAT] = {
2485          [CCS_STAT_POLICY_UPDATES]    = "update:",          [CCS_STAT_POLICY_UPDATES]    = "update:",
2486          [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 2488  static const char * const ccs_policy_hea
2488          [CCS_STAT_POLICY_ENFORCING]  = "violation in enforcing mode:",          [CCS_STAT_POLICY_ENFORCING]  = "violation in enforcing mode:",
2489  };  };
2490    
2491  /* String table for /proc/ccs/meminfo interface. */  /* String table for /proc/ccs/stat interface. */
2492  static const char * const ccs_memory_headers[CCS_MAX_MEMORY_STAT] = {  static const char * const ccs_memory_headers[CCS_MAX_MEMORY_STAT] = {
2493          [CCS_MEMORY_POLICY] = "policy:",          [CCS_MEMORY_POLICY]     = "policy:",
2494          [CCS_MEMORY_AUDIT]  = "audit log:",          [CCS_MEMORY_AUDIT]      = "audit log:",
2495          [CCS_MEMORY_QUERY]  = "query message:",          [CCS_MEMORY_QUERY]      = "query message:",
2496  };  };
2497    
2498  /* Timestamp counter for last updated. */  /* Timestamp counter for last updated. */
# Line 2474  static int ccs_write_stat(struct ccs_io_ Line 2572  static int ccs_write_stat(struct ccs_io_
2572          u8 i;          u8 i;
2573          if (ccs_str_starts(&data, "Memory used by "))          if (ccs_str_starts(&data, "Memory used by "))
2574                  for (i = 0; i < CCS_MAX_MEMORY_STAT; i++)                  for (i = 0; i < CCS_MAX_MEMORY_STAT; i++)
2575                          if (ccs_str_starts(&data, ccs_memory_headers[i]))                          if (ccs_str_starts(&data, ccs_memory_headers[i])) {
2576                                  sscanf(data, "%u", &ccs_memory_quota[i]);                                  if (*data == ' ')
2577          return 0;                                          data++;
2578  }                                  ccs_memory_quota[i] =
2579                                            simple_strtoul(data, NULL, 10);
2580  /* 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]);  
2581          return 0;          return 0;
2582  }  }
2583    
# Line 2545  int ccs_open_control(const u8 type, stru Line 2596  int ccs_open_control(const u8 type, stru
2596                  return -ENOMEM;                  return -ENOMEM;
2597          mutex_init(&head->io_sem);          mutex_init(&head->io_sem);
2598          head->type = type;          head->type = type;
2599          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 */  
2600                  /* Allow execute_handler to read process's status. */                  /* Allow execute_handler to read process's status. */
2601                  if (!(ccs_current_flags() & CCS_TASK_IS_EXECUTE_HANDLER)) {                  if (!(ccs_current_flags() & CCS_TASK_IS_EXECUTE_HANDLER)) {
2602                          kfree(head);                          kfree(head);
2603                          return -EPERM;                          return -EPERM;
2604                  }                  }
                 /* 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;  
2605          }          }
2606          if (!(file->f_mode & FMODE_READ)) {          if ((file->f_mode & FMODE_READ) && type != CCS_AUDIT &&
2607                  /*              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) {  
2608                  /* Don't allocate read_buf for poll() access. */                  /* Don't allocate read_buf for poll() access. */
2609                  if (!head->readbuf_size)                  head->readbuf_size = 4096;
                         head->readbuf_size = 4096;  
2610                  head->read_buf = kzalloc(head->readbuf_size, CCS_GFP_FLAGS);                  head->read_buf = kzalloc(head->readbuf_size, CCS_GFP_FLAGS);
2611                  if (!head->read_buf) {                  if (!head->read_buf) {
2612                          kfree(head);                          kfree(head);
2613                          return -ENOMEM;                          return -ENOMEM;
2614                  }                  }
2615          }          }
2616          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) {  
2617                  head->writebuf_size = 4096;                  head->writebuf_size = 4096;
2618                  head->write_buf = kzalloc(head->writebuf_size, CCS_GFP_FLAGS);                  head->write_buf = kzalloc(head->writebuf_size, CCS_GFP_FLAGS);
2619                  if (!head->write_buf) {                  if (!head->write_buf) {
# Line 2640  int ccs_open_control(const u8 type, stru Line 2629  int ccs_open_control(const u8 type, stru
2629           */           */
2630          if (type == CCS_QUERY)          if (type == CCS_QUERY)
2631                  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();  
2632          file->private_data = head;          file->private_data = head;
2633            ccs_notify_gc(head, true);
2634          return 0;          return 0;
2635  }  }
2636    
# Line 2662  int ccs_open_control(const u8 type, stru Line 2649  int ccs_open_control(const u8 type, stru
2649  int ccs_poll_control(struct file *file, poll_table *wait)  int ccs_poll_control(struct file *file, poll_table *wait)
2650  {  {
2651          struct ccs_io_buffer *head = file->private_data;          struct ccs_io_buffer *head = file->private_data;
2652          if (!head->poll)          switch (head->type) {
2653            case CCS_AUDIT:
2654                    return ccs_poll_log(file, wait);
2655            case CCS_QUERY:
2656                    return ccs_poll_query(file, wait);
2657            default:
2658                  return -ENOSYS;                  return -ENOSYS;
2659          return head->poll(file, wait);          }
2660    }
2661    
2662    /**
2663     * ccs_set_namespace_cursor - Set namespace to read.
2664     *
2665     * @head: Pointer to "struct ccs_io_buffer".
2666     *
2667     * Returns nothing.
2668     */
2669    static inline void ccs_set_namespace_cursor(struct ccs_io_buffer *head)
2670    {
2671            struct list_head *ns;
2672            if (head->type != CCS_EXCEPTIONPOLICY && head->type != CCS_PROFILE)
2673                    return;
2674            /*
2675             * If this is the first read, or reading previous namespace finished
2676             * and has more namespaces to read, update the namespace cursor.
2677             */
2678            ns = head->r.ns;
2679            if (!ns || (head->r.eof && ns->next != &ccs_namespace_list)) {
2680                    /* Clearing is OK because ccs_flush() returned true. */
2681                    memset(&head->r, 0, sizeof(head->r));
2682                    head->r.ns = ns ? ns->next : ccs_namespace_list.next;
2683            }
2684    }
2685    
2686    /**
2687     * ccs_has_more_namespace - Check for unread namespaces.
2688     *
2689     * @head: Pointer to "struct ccs_io_buffer".
2690     *
2691     * Returns true if we have more entries to print, false otherwise.
2692     */
2693    static inline bool ccs_has_more_namespace(struct ccs_io_buffer *head)
2694    {
2695            return (head->type == CCS_EXCEPTIONPOLICY ||
2696                    head->type == CCS_PROFILE) && head->r.eof &&
2697                    head->r.ns->next != &ccs_namespace_list;
2698  }  }
2699    
2700  /**  /**
2701   * ccs_read_control - read() for /proc/ccs/ interface.   * ccs_read_control - read() for /proc/ccs/ interface.
2702   *   *
2703   * @file:       Pointer to "struct file".   * @head:       Pointer to "struct ccs_io_buffer".
2704   * @buffer:     Poiner to buffer to write to.   * @buffer:     Poiner to buffer to write to.
2705   * @buffer_len: Size of @buffer.   * @buffer_len: Size of @buffer.
2706   *   *
2707   * Returns bytes read on success, negative value otherwise.   * Returns bytes read on success, negative value otherwise.
2708   */   */
2709  int ccs_read_control(struct file *file, char __user *buffer,  ssize_t ccs_read_control(struct ccs_io_buffer *head, char __user *buffer,
2710                       const int buffer_len)                           const size_t buffer_len)
2711  {  {
2712          int len;          int len;
         struct ccs_io_buffer *head = file->private_data;  
2713          int idx;          int idx;
         if (!head->read)  
                 return -ENOSYS;  
2714          if (!access_ok(VERIFY_WRITE, buffer, buffer_len))          if (!access_ok(VERIFY_WRITE, buffer, buffer_len))
2715                  return -EFAULT;                  return -EFAULT;
2716          if (mutex_lock_interruptible(&head->io_sem))          if (mutex_lock_interruptible(&head->io_sem))
# Line 2693  int ccs_read_control(struct file *file, Line 2720  int ccs_read_control(struct file *file,
2720          idx = ccs_read_lock();          idx = ccs_read_lock();
2721          if (ccs_flush(head))          if (ccs_flush(head))
2722                  /* Call the policy handler. */                  /* Call the policy handler. */
2723                  head->read(head);                  do {
2724          ccs_flush(head);                          ccs_set_namespace_cursor(head);
2725                            switch (head->type) {
2726                            case CCS_DOMAINPOLICY:
2727                                    ccs_read_domain(head);
2728                                    break;
2729                            case CCS_EXCEPTIONPOLICY:
2730                                    ccs_read_exception(head);
2731                                    break;
2732                            case CCS_AUDIT:
2733                                    ccs_read_log(head);
2734                                    break;
2735                            case CCS_EXECUTE_HANDLER:
2736                            case CCS_PROCESS_STATUS:
2737                                    ccs_read_pid(head);
2738                                    break;
2739                            case CCS_VERSION:
2740                                    ccs_read_version(head);
2741                                    break;
2742                            case CCS_STAT:
2743                                    ccs_read_stat(head);
2744                                    break;
2745                            case CCS_PROFILE:
2746                                    ccs_read_profile(head);
2747                                    break;
2748                            case CCS_QUERY:
2749                                    ccs_read_query(head);
2750                                    break;
2751                            case CCS_MANAGER:
2752                                    ccs_read_manager(head);
2753                                    break;
2754                            }
2755                    } while (ccs_flush(head) && ccs_has_more_namespace(head));
2756          ccs_read_unlock(idx);          ccs_read_unlock(idx);
2757          len = head->read_user_buf - buffer;          len = head->read_user_buf - buffer;
2758          mutex_unlock(&head->io_sem);          mutex_unlock(&head->io_sem);
# Line 2702  int ccs_read_control(struct file *file, Line 2760  int ccs_read_control(struct file *file,
2760  }  }
2761    
2762  /**  /**
2763     * ccs_parse_policy - Parse a policy line.
2764     *
2765     * @head: Poiter to "struct ccs_io_buffer".
2766     * @line: Line to parse.
2767     *
2768     * Returns 0 on success, negative value otherwise.
2769     *
2770     * Caller holds ccs_read_lock().
2771     */
2772    static int ccs_parse_policy(struct ccs_io_buffer *head, char *line)
2773    {
2774            /* Delete request? */
2775            head->w.is_delete = !strncmp(line, "delete ", 7);
2776            if (head->w.is_delete)
2777                    memmove(line, line + 7, strlen(line + 7) + 1);
2778            /* Selecting namespace to update. */
2779            if (head->type == CCS_EXCEPTIONPOLICY || head->type == CCS_PROFILE) {
2780                    if (*line == '<') {
2781                            char *cp = strchr(line, ' ');
2782                            if (cp) {
2783                                    *cp++ = '\0';
2784                                    head->w.ns = ccs_assign_namespace(line);
2785                                    memmove(line, cp, strlen(cp) + 1);
2786                            } else
2787                                    head->w.ns = NULL;
2788                    } else
2789                            head->w.ns = &ccs_kernel_namespace;
2790                    /* Don't allow updating if namespace is invalid. */
2791                    if (!head->w.ns)
2792                            return -ENOENT;
2793            }
2794            /* Do the update. */
2795            switch (head->type) {
2796            case CCS_DOMAINPOLICY:
2797                    return ccs_write_domain(head);
2798            case CCS_EXCEPTIONPOLICY:
2799                    return ccs_write_exception(head);
2800            case CCS_EXECUTE_HANDLER:
2801            case CCS_PROCESS_STATUS:
2802                    return ccs_write_pid(head);
2803            case CCS_STAT:
2804                    return ccs_write_stat(head);
2805            case CCS_PROFILE:
2806                    return ccs_write_profile(head);
2807            case CCS_QUERY:
2808                    return ccs_write_answer(head);
2809            case CCS_MANAGER:
2810                    return ccs_write_manager(head);
2811            default:
2812                    return -ENOSYS;
2813            }
2814    }
2815    
2816    /**
2817   * ccs_write_control - write() for /proc/ccs/ interface.   * ccs_write_control - write() for /proc/ccs/ interface.
2818   *   *
2819   * @file:       Pointer to "struct file".   * @head:       Pointer to "struct ccs_io_buffer".
2820   * @buffer:     Pointer to buffer to read from.   * @buffer:     Pointer to buffer to read from.
2821   * @buffer_len: Size of @buffer.   * @buffer_len: Size of @buffer.
2822   *   *
2823   * Returns @buffer_len on success, negative value otherwise.   * Returns @buffer_len on success, negative value otherwise.
2824   */   */
2825  int ccs_write_control(struct file *file, const char __user *buffer,  ssize_t ccs_write_control(struct ccs_io_buffer *head,
2826                        const int buffer_len)                            const char __user *buffer, const size_t buffer_len)
2827  {  {
         struct ccs_io_buffer *head = file->private_data;  
2828          int error = buffer_len;          int error = buffer_len;
2829          int avail_len = buffer_len;          size_t avail_len = buffer_len;
2830          char *cp0 = head->write_buf;          char *cp0 = head->write_buf;
2831          int idx;          int idx;
         if (!head->write)  
                 return -ENOSYS;  
2832          if (!access_ok(VERIFY_READ, buffer, buffer_len))          if (!access_ok(VERIFY_READ, buffer, buffer_len))
2833                  return -EFAULT;                  return -EFAULT;
2834          if (mutex_lock_interruptible(&head->io_sem))          if (mutex_lock_interruptible(&head->io_sem))
2835                  return -EINTR;                  return -EINTR;
2836          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;  
         }  
2837          /* Read a line and dispatch it to the policy handler. */          /* Read a line and dispatch it to the policy handler. */
2838          while (avail_len > 0) {          while (avail_len > 0) {
2839                  char c;                  char c;
# Line 2760  int ccs_write_control(struct file *file, Line 2862  int ccs_write_control(struct file *file,
2862                  cp0[head->w.avail - 1] = '\0';                  cp0[head->w.avail - 1] = '\0';
2863                  head->w.avail = 0;                  head->w.avail = 0;
2864                  ccs_normalize_line(cp0);                  ccs_normalize_line(cp0);
2865                  if (head->write(head))                  if (!strcmp(cp0, "reset")) {
2866                            head->w.ns = &ccs_kernel_namespace;
2867                            head->w.domain = NULL;
2868                            memset(&head->r, 0, sizeof(head->r));
2869                          continue;                          continue;
2870                    }
2871                    /* Don't allow updating policies by non manager programs. */
2872                  switch (head->type) {                  switch (head->type) {
2873                    case CCS_PROCESS_STATUS:
2874                            /* This does not write anything. */
2875                            break;
2876                  case CCS_DOMAINPOLICY:                  case CCS_DOMAINPOLICY:
2877                            if (ccs_select_domain(head, cp0))
2878                                    continue;
2879                            /* fall through */
2880                  case CCS_EXCEPTIONPOLICY:                  case CCS_EXCEPTIONPOLICY:
2881                  case CCS_DOMAIN_STATUS:                          if (!strcmp(cp0, "select transition_only")) {
2882                  case CCS_MEMINFO:                                  head->r.print_transition_related_only = true;
2883                  case CCS_PROFILE:                                  continue;
2884                  case CCS_MANAGER:                          }
2885                          ccs_update_stat(CCS_STAT_POLICY_UPDATES);                          /* fall through */
2886                    default:
2887                            if (!ccs_manager()) {
2888                                    error = -EPERM;
2889                                    goto out;
2890                            }
2891                    }
2892                    switch (ccs_parse_policy(head, cp0)) {
2893                    case -EPERM:
2894                            error = -EPERM;
2895                            goto out;
2896                    case 0:
2897                            /* Update statistics. */
2898                            switch (head->type) {
2899                            case CCS_DOMAINPOLICY:
2900                            case CCS_EXCEPTIONPOLICY:
2901                            case CCS_STAT:
2902                            case CCS_PROFILE:
2903                            case CCS_MANAGER:
2904                                    ccs_update_stat(CCS_STAT_POLICY_UPDATES);
2905                                    break;
2906                            default:
2907                                    break;
2908                            }
2909                            break;
2910                  }                  }
2911          }          }
2912    out:
2913          ccs_read_unlock(idx);          ccs_read_unlock(idx);
2914          mutex_unlock(&head->io_sem);          mutex_unlock(&head->io_sem);
2915          return error;          return error;
# Line 2780  int ccs_write_control(struct file *file, Line 2918  int ccs_write_control(struct file *file,
2918  /**  /**
2919   * ccs_close_control - close() for /proc/ccs/ interface.   * ccs_close_control - close() for /proc/ccs/ interface.
2920   *   *
2921   * @file: Pointer to "struct file".   * @head: Pointer to "struct ccs_io_buffer".
2922   *   *
2923   * Returns 0.   * Returns 0.
2924   */   */
2925  int ccs_close_control(struct file *file)  int ccs_close_control(struct ccs_io_buffer *head)
2926  {  {
         struct ccs_io_buffer *head = file->private_data;  
         const bool is_write = head->write_buf != NULL;  
         const u8 type = head->type;  
2927          /*          /*
2928           * If the file is /proc/ccs/query, decrement the observer counter.           * If the file is /proc/ccs/query, decrement the observer counter.
2929           */           */
2930          if (type == CCS_QUERY) {          if (head->type == CCS_QUERY &&
2931                  if (atomic_dec_and_test(&ccs_query_observers))              atomic_dec_and_test(&ccs_query_observers))
2932                          wake_up_all(&ccs_answer_wait);                  wake_up_all(&ccs_answer_wait);
2933          } 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();  
2934          return 0;          return 0;
2935  }  }
2936    
# Line 2820  void __init ccs_policy_io_init(void) Line 2943  void __init ccs_policy_io_init(void)
2943  {  {
2944          ccsecurity_ops.check_profile = ccs_check_profile;          ccsecurity_ops.check_profile = ccs_check_profile;
2945  }  }
2946    
2947    /**
2948     * ccs_load_builtin_policy - Load built-in policy.
2949     *
2950     * Returns nothing.
2951     */
2952    void __init ccs_load_builtin_policy(void)
2953    {
2954            /*
2955             * This include file is manually created and contains built-in policy
2956             * named "ccs_builtin_profile", "ccs_builtin_exception_policy",
2957             * "ccs_builtin_domain_policy", "ccs_builtin_manager",
2958             * "ccs_builtin_stat" in the form of "static char [] __initdata".
2959             */
2960    #include "builtin-policy.h"
2961            u8 i;
2962            const int idx = ccs_read_lock();
2963            for (i = 0; i < 5; i++) {
2964                    struct ccs_io_buffer head = { };
2965                    char *start = "";
2966                    switch (i) {
2967                    case 0:
2968                            start = ccs_builtin_profile;
2969                            head.type = CCS_PROFILE;
2970                            break;
2971                    case 1:
2972                            start = ccs_builtin_exception_policy;
2973                            head.type = CCS_EXCEPTIONPOLICY;
2974                            break;
2975                    case 2:
2976                            start = ccs_builtin_domain_policy;
2977                            head.type = CCS_DOMAINPOLICY;
2978                            break;
2979                    case 3:
2980                            start = ccs_builtin_manager;
2981                            head.type = CCS_MANAGER;
2982                            break;
2983                    case 4:
2984                            start = ccs_builtin_stat;
2985                            head.type = CCS_STAT;
2986                            break;
2987                    }
2988                    while (1) {
2989                            char *end = strchr(start, '\n');
2990                            if (!end)
2991                                    break;
2992                            *end = '\0';
2993                            ccs_normalize_line(start);
2994                            head.write_buf = start;
2995                            ccs_parse_policy(&head, start);
2996                            start = end + 1;
2997                    }
2998            }
2999            ccs_read_unlock(idx);
3000    #ifdef CONFIG_CCSECURITY_OMIT_USERSPACE_LOADER
3001            ccs_check_profile();
3002    #endif
3003    }

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

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