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

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 5075 by kumaneko, Wed Jun 1 06:06:50 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.2-pre   2011/06/01
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 277  const char *ccs_yesno(const unsigned int Line 270  const char *ccs_yesno(const unsigned int
270          return value ? "yes" : "no";          return value ? "yes" : "no";
271  }  }
272    
273  /* Prototype fpr ccs_addprintf(). */  /* Prototype for ccs_addprintf(). */
274  static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)  static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
275          __attribute__ ((format(printf, 3, 4)));          __attribute__ ((format(printf, 3, 4)));
276    
# Line 310  static bool ccs_flush(struct ccs_io_buff Line 303  static bool ccs_flush(struct ccs_io_buff
303  {  {
304          while (head->r.w_pos) {          while (head->r.w_pos) {
305                  const char *w = head->r.w[0];                  const char *w = head->r.w[0];
306                  int len = strlen(w);                  size_t len = strlen(w);
307                  if (len) {                  if (len) {
308                          if (len > head->read_user_buf_avail)                          if (len > head->read_user_buf_avail)
309                                  len = head->read_user_buf_avail;                                  len = head->read_user_buf_avail;
# Line 322  static bool ccs_flush(struct ccs_io_buff Line 315  static bool ccs_flush(struct ccs_io_buff
315                          head->read_user_buf += len;                          head->read_user_buf += len;
316                          w += len;                          w += len;
317                  }                  }
318                  if (*w) {                  head->r.w[0] = w;
319                          head->r.w[0] = w;                  if (*w)
320                          return false;                          return false;
                 }  
321                  /* Add '\0' for audit logs and query. */                  /* Add '\0' for audit logs and query. */
322                  if (head->poll) {                  if (head->poll) {
323                          if (!head->read_user_buf_avail ||                          if (!head->read_user_buf_avail ||
# Line 363  static void ccs_set_string(struct ccs_io Line 355  static void ccs_set_string(struct ccs_io
355                  printk(KERN_WARNING "Too many words in a line.\n");                  printk(KERN_WARNING "Too many words in a line.\n");
356  }  }
357    
358    /* Prototype for ccs_io_printf(). */
359    static void ccs_io_printf(struct ccs_io_buffer *head, const char *fmt, ...)
360            __attribute__ ((format(printf, 2, 3)));
361    
362  /**  /**
363   * ccs_io_printf - printf() to "struct ccs_io_buffer" structure.   * ccs_io_printf - printf() to "struct ccs_io_buffer" structure.
364   *   *
# Line 371  static void ccs_set_string(struct ccs_io Line 367  static void ccs_set_string(struct ccs_io
367   *   *
368   * Returns nothing.   * Returns nothing.
369   */   */
370  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, ...)
371  {  {
372          va_list args;          va_list args;
373          int len;          size_t len;
374          int pos = head->r.avail;          size_t pos = head->r.avail;
375          int size = head->readbuf_size - pos;          int size = head->readbuf_size - pos;
376          if (size <= 0)          if (size <= 0)
377                  return;                  return;
# Line 416  static bool ccs_set_lf(struct ccs_io_buf Line 412  static bool ccs_set_lf(struct ccs_io_buf
412  }  }
413    
414  /**  /**
415     * ccs_set_slash - Put a shash to "struct ccs_io_buffer" structure.
416     *
417     * @head: Pointer to "struct ccs_io_buffer".
418     *
419     * Returns nothing.
420     */
421    static void ccs_set_slash(struct ccs_io_buffer *head)
422    {
423            ccs_set_string(head, "/");
424    }
425    
426    /* List of namespaces. */
427    LIST_HEAD(ccs_namespace_list);
428    /* True if namespace other than ccs_kernel_namespace is defined. */
429    static bool ccs_namespace_enabled;
430    
431    /**
432     * ccs_init_policy_namespace - Initialize namespace.
433     *
434     * @ns: Pointer to "struct ccs_policy_namespace".
435     *
436     * Returns nothing.
437     */
438    void ccs_init_policy_namespace(struct ccs_policy_namespace *ns)
439    {
440            unsigned int idx;
441            for (idx = 0; idx < CCS_MAX_ACL_GROUPS; idx++) {
442                    INIT_LIST_HEAD(&ns->acl_group[idx][0]);
443                    INIT_LIST_HEAD(&ns->acl_group[idx][1]);
444            }
445            for (idx = 0; idx < CCS_MAX_GROUP; idx++)
446                    INIT_LIST_HEAD(&ns->group_list[idx]);
447            for (idx = 0; idx < CCS_MAX_POLICY; idx++)
448                    INIT_LIST_HEAD(&ns->policy_list[idx]);
449            ns->profile_version = 20100903;
450            ccs_namespace_enabled = !list_empty(&ccs_namespace_list);
451            list_add_tail_rcu(&ns->namespace_list, &ccs_namespace_list);
452    }
453    
454    /**
455     * ccs_print_namespace - Print namespace header.
456     *
457     * @head: Pointer to "struct ccs_io_buffer".
458     *
459     * Returns nothing.
460     */
461    static void ccs_print_namespace(struct ccs_io_buffer *head)
462    {
463            if (!ccs_namespace_enabled)
464                    return;
465            ccs_set_string(head,
466                           container_of(head->r.ns, struct ccs_policy_namespace,
467                                        namespace_list)->name);
468            ccs_set_space(head);
469    }
470    
471    /**
472   * ccs_assign_profile - Create a new profile.   * ccs_assign_profile - Create a new profile.
473   *   *
474     * @ns:      Pointer to "struct ccs_policy_namespace".
475   * @profile: Profile number to create.   * @profile: Profile number to create.
476   *   *
477   * Returns pointer to "struct ccs_profile" on success, NULL otherwise.   * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
478   */   */
479  static struct ccs_profile *ccs_assign_profile(const unsigned int profile)  static struct ccs_profile *ccs_assign_profile(struct ccs_policy_namespace *ns,
480                                                  const unsigned int profile)
481  {  {
482          struct ccs_profile *ptr;          struct ccs_profile *ptr;
483          struct ccs_profile *entry;          struct ccs_profile *entry;
484          if (profile >= CCS_MAX_PROFILES)          if (profile >= CCS_MAX_PROFILES)
485                  return NULL;                  return NULL;
486          ptr = ccs_profile_ptr[profile];          ptr = ns->profile_ptr[profile];
487          if (ptr)          if (ptr)
488                  return ptr;                  return ptr;
489          entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);          entry = kzalloc(sizeof(*entry), CCS_GFP_FLAGS);
490          if (mutex_lock_interruptible(&ccs_policy_lock))          if (mutex_lock_interruptible(&ccs_policy_lock))
491                  goto out;                  goto out;
492          ptr = ccs_profile_ptr[profile];          ptr = ns->profile_ptr[profile];
493          if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {          if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {
494                  ptr = entry;                  ptr = entry;
495                  ptr->default_config = CCS_CONFIG_DISABLED |                  ptr->default_config = CCS_CONFIG_DISABLED |
# Line 446  static struct ccs_profile *ccs_assign_pr Line 501  static struct ccs_profile *ccs_assign_pr
501                  ptr->pref[CCS_PREF_MAX_LEARNING_ENTRY] =                  ptr->pref[CCS_PREF_MAX_LEARNING_ENTRY] =
502                          CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY;                          CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY;
503                  mb(); /* Avoid out-of-order execution. */                  mb(); /* Avoid out-of-order execution. */
504                  ccs_profile_ptr[profile] = ptr;                  ns->profile_ptr[profile] = ptr;
505                  entry = NULL;                  entry = NULL;
506          }          }
507          mutex_unlock(&ccs_policy_lock);          mutex_unlock(&ccs_policy_lock);
# Line 465  static void ccs_check_profile(void) Line 520  static void ccs_check_profile(void)
520          struct ccs_domain_info *domain;          struct ccs_domain_info *domain;
521          const int idx = ccs_read_lock();          const int idx = ccs_read_lock();
522          ccs_policy_loaded = true;          ccs_policy_loaded = true;
523            printk(KERN_INFO "CCSecurity: 1.8.2-pre   2011/06/01\n");
524          list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {          list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
525                  const u8 profile = domain->profile;                  const u8 profile = domain->profile;
526                  if (ccs_profile_ptr[profile])                  const struct ccs_policy_namespace *ns = domain->ns;
527                    if (ns->profile_version != 20100903)
528                            printk(KERN_ERR
529                                   "Profile version %u is not supported.\n",
530                                   ns->profile_version);
531                    else if (!ns->profile_ptr[profile])
532                            printk(KERN_ERR
533                                   "Profile %u (used by '%s') is not defined.\n",
534                                   profile, domain->domainname->name);
535                    else
536                          continue;                          continue;
537                  printk(KERN_ERR "Profile %u must be defined before using it.\n",                  printk(KERN_ERR
538                         profile);                         "Userland tools for TOMOYO 1.8 must be installed and "
539                           "policy must be initialized.\n");
540                  printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/1.8/ "                  printk(KERN_ERR "Please see http://tomoyo.sourceforge.jp/1.8/ "
541                         "for more information.\n");                         "for more information.\n");
542                  panic("Profile %u (used by '%s') not defined.\n",                  panic("STOP!");
                       profile, domain->domainname->name);  
543          }          }
544          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");  
545          printk(KERN_INFO "Mandatory Access Control activated.\n");          printk(KERN_INFO "Mandatory Access Control activated.\n");
546  }  }
547    
# Line 499  static void ccs_check_profile(void) Line 555  static void ccs_check_profile(void)
555  struct ccs_profile *ccs_profile(const u8 profile)  struct ccs_profile *ccs_profile(const u8 profile)
556  {  {
557          static struct ccs_profile ccs_null_profile;          static struct ccs_profile ccs_null_profile;
558          struct ccs_profile *ptr = ccs_profile_ptr[profile];          struct ccs_profile *ptr = ccs_current_namespace()->
559                    profile_ptr[profile];
560          if (!ptr)          if (!ptr)
561                  ptr = &ccs_null_profile;                  ptr = &ccs_null_profile;
562          return ptr;          return ptr;
# Line 633  static int ccs_write_profile(struct ccs_ Line 690  static int ccs_write_profile(struct ccs_
690          unsigned int i;          unsigned int i;
691          char *cp;          char *cp;
692          struct ccs_profile *profile;          struct ccs_profile *profile;
693          if (sscanf(data, "PROFILE_VERSION=%u", &ccs_profile_version) == 1)          if (sscanf(data, "PROFILE_VERSION=%u", &head->w.ns->profile_version)
694                == 1)
695                  return 0;                  return 0;
696          i = simple_strtoul(data, &cp, 10);          i = simple_strtoul(data, &cp, 10);
697          if (*cp != '-')          if (*cp != '-')
698                  return -EINVAL;                  return -EINVAL;
699          data = cp + 1;          data = cp + 1;
700          profile = ccs_assign_profile(i);          profile = ccs_assign_profile(head->w.ns, i);
701          if (!profile)          if (!profile)
702                  return -EINVAL;                  return -EINVAL;
703          cp = strchr(data, '=');          cp = strchr(data, '=');
# Line 647  static int ccs_write_profile(struct ccs_ Line 705  static int ccs_write_profile(struct ccs_
705                  return -EINVAL;                  return -EINVAL;
706          *cp++ = '\0';          *cp++ = '\0';
707          if (!strcmp(data, "COMMENT")) {          if (!strcmp(data, "COMMENT")) {
708                  const struct ccs_path_info *old_comment = profile->comment;                  static DEFINE_SPINLOCK(lock);
709                  profile->comment = ccs_get_name(cp);                  const struct ccs_path_info *new_comment = ccs_get_name(cp);
710                    const struct ccs_path_info *old_comment;
711                    if (!new_comment)
712                            return -ENOMEM;
713                    spin_lock(&lock);
714                    old_comment = profile->comment;
715                    profile->comment = new_comment;
716                    spin_unlock(&lock);
717                  ccs_put_name(old_comment);                  ccs_put_name(old_comment);
718                  return 0;                  return 0;
719          }          }
# Line 689  static void ccs_print_config(struct ccs_ Line 754  static void ccs_print_config(struct ccs_
754  static void ccs_read_profile(struct ccs_io_buffer *head)  static void ccs_read_profile(struct ccs_io_buffer *head)
755  {  {
756          u8 index;          u8 index;
757            struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
758                                                           namespace_list);
759          const struct ccs_profile *profile;          const struct ccs_profile *profile;
760            if (head->r.eof)
761                    return;
762  next:  next:
763          index = head->r.index;          index = head->r.index;
764          profile = ccs_profile_ptr[index];          profile = ns->profile_ptr[index];
765          switch (head->r.step) {          switch (head->r.step) {
766          case 0:          case 0:
767                  ccs_io_printf(head, "PROFILE_VERSION=%s\n", "20100903");                  ccs_print_namespace(head);
768                    ccs_io_printf(head, "PROFILE_VERSION=%u\n", 20100903);
769                  head->r.step++;                  head->r.step++;
770                  break;                  break;
771          case 1:          case 1:
772                  for ( ; head->r.index < CCS_MAX_PROFILES;                  for ( ; head->r.index < CCS_MAX_PROFILES; head->r.index++)
773                        head->r.index++)                          if (ns->profile_ptr[head->r.index])
                         if (ccs_profile_ptr[head->r.index])  
774                                  break;                                  break;
775                  if (head->r.index == CCS_MAX_PROFILES)                  if (head->r.index == CCS_MAX_PROFILES) {
776                            head->r.eof = true;
777                          return;                          return;
778                    }
779                  head->r.step++;                  head->r.step++;
780                  break;                  break;
781          case 2:          case 2:
782                  {                  {
783                          u8 i;                          u8 i;
784                          const struct ccs_path_info *comment = profile->comment;                          const struct ccs_path_info *comment = profile->comment;
785                            ccs_print_namespace(head);
786                          ccs_io_printf(head, "%u-COMMENT=", index);                          ccs_io_printf(head, "%u-COMMENT=", index);
787                          ccs_set_string(head, comment ? comment->name : "");                          ccs_set_string(head, comment ? comment->name : "");
788                          ccs_set_lf(head);                          ccs_set_lf(head);
789                            ccs_print_namespace(head);
790                          ccs_io_printf(head, "%u-PREFERENCE={ ", index);                          ccs_io_printf(head, "%u-PREFERENCE={ ", index);
791                          for (i = 0; i < CCS_MAX_PREF; i++)                          for (i = 0; i < CCS_MAX_PREF; i++)
792                                  ccs_io_printf(head, "%s=%u ",                                  ccs_io_printf(head, "%s=%u ",
793                                                ccs_pref_keywords[i],                                                ccs_pref_keywords[i],
794                                                profile->pref[i]);                                                profile->pref[i]);
795                          ccs_set_string(head, " }\n");                          ccs_set_string(head, "}\n");
796                          head->r.step++;                          head->r.step++;
797                  }                  }
798                  break;                  break;
799          case 3:          case 3:
800                  {                  {
801                            ccs_print_namespace(head);
802                          ccs_io_printf(head, "%u-%s", index, "CONFIG");                          ccs_io_printf(head, "%u-%s", index, "CONFIG");
803                          ccs_print_config(head, profile->default_config);                          ccs_print_config(head, profile->default_config);
804                          head->r.bit = 0;                          head->r.bit = 0;
# Line 738  next: Line 812  next:
812                          const u8 config = profile->config[i];                          const u8 config = profile->config[i];
813                          if (config == CCS_CONFIG_USE_DEFAULT)                          if (config == CCS_CONFIG_USE_DEFAULT)
814                                  continue;                                  continue;
815                            ccs_print_namespace(head);
816                          if (i < CCS_MAX_MAC_INDEX)                          if (i < CCS_MAX_MAC_INDEX)
817                                  ccs_io_printf(head, "%u-CONFIG::%s::%s", index,                                  ccs_io_printf(head, "%u-CONFIG::%s::%s", index,
818                                                ccs_category_keywords                                                ccs_category_keywords
# Line 784  static bool ccs_same_manager(const struc Line 859  static bool ccs_same_manager(const struc
859   *   *
860   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
861   */   */
862  static int ccs_update_manager_entry(const char *manager, const bool is_delete)  static inline int ccs_update_manager_entry(const char *manager,
863                                               const bool is_delete)
864  {  {
865          struct ccs_manager e = { };          struct ccs_manager e = { };
866            struct ccs_acl_param param = {
867                    /* .ns = &ccs_kernel_namespace, */
868                    .is_delete = is_delete,
869                    .list = &ccs_kernel_namespace.policy_list[CCS_ID_MANAGER],
870            };
871          int error = is_delete ? -ENOENT : -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
872          if (ccs_domain_def(manager)) {          if (ccs_domain_def(manager)) {
873                  if (!ccs_correct_domain(manager))                  if (!ccs_correct_domain(manager))
# Line 797  static int ccs_update_manager_entry(cons Line 878  static int ccs_update_manager_entry(cons
878                          return -EINVAL;                          return -EINVAL;
879          }          }
880          e.manager = ccs_get_name(manager);          e.manager = ccs_get_name(manager);
881          if (!e.manager)          if (e.manager) {
882                  return error;                  error = ccs_update_policy(&e.head, sizeof(e), &param,
883          error = ccs_update_policy(&e.head, sizeof(e), is_delete,                                            ccs_same_manager);
884                                    &ccs_policy_list[CCS_ID_MANAGER],                  ccs_put_name(e.manager);
885                                    ccs_same_manager);          }
         ccs_put_name(e.manager);  
886          return error;          return error;
887  }  }
888    
# Line 815  static int ccs_update_manager_entry(cons Line 895  static int ccs_update_manager_entry(cons
895   */   */
896  static int ccs_write_manager(struct ccs_io_buffer *head)  static int ccs_write_manager(struct ccs_io_buffer *head)
897  {  {
898          char *data = head->write_buf;          const char *data = head->write_buf;
         bool is_delete = ccs_str_starts(&data, "delete ");  
899          if (!strcmp(data, "manage_by_non_root")) {          if (!strcmp(data, "manage_by_non_root")) {
900                  ccs_manage_by_non_root = !is_delete;                  ccs_manage_by_non_root = !head->w.is_delete;
901                  return 0;                  return 0;
902          }          }
903          return ccs_update_manager_entry(data, is_delete);          return ccs_update_manager_entry(data, head->w.is_delete);
904  }  }
905    
906  /**  /**
# Line 837  static void ccs_read_manager(struct ccs_ Line 916  static void ccs_read_manager(struct ccs_
916  {  {
917          if (head->r.eof)          if (head->r.eof)
918                  return;                  return;
919          list_for_each_cookie(head->r.acl, &ccs_policy_list[CCS_ID_MANAGER]) {          list_for_each_cookie(head->r.acl, &ccs_kernel_namespace.
920                                 policy_list[CCS_ID_MANAGER]) {
921                  struct ccs_manager *ptr =                  struct ccs_manager *ptr =
922                          list_entry(head->r.acl, typeof(*ptr), head.list);                          list_entry(head->r.acl, typeof(*ptr), head.list);
923                  if (ptr->head.is_deleted)                  if (ptr->head.is_deleted)
# Line 873  static bool ccs_manager(void) Line 953  static bool ccs_manager(void)
953          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))
954                  return false;                  return false;
955          exe = ccs_get_exe();          exe = ccs_get_exe();
956          list_for_each_entry_srcu(ptr, &ccs_policy_list[CCS_ID_MANAGER],          list_for_each_entry_srcu(ptr, &ccs_kernel_namespace.
957                                   head.list, &ccs_ss) {                                   policy_list[CCS_ID_MANAGER], head.list,
958                                     &ccs_ss) {
959                  if (ptr->head.is_deleted)                  if (ptr->head.is_deleted)
960                          continue;                          continue;
961                  if (ptr->is_domain) {                  if (ptr->is_domain) {
# Line 903  static bool ccs_manager(void) Line 984  static bool ccs_manager(void)
984  }  }
985    
986  /**  /**
987   * ccs_select_one - Parse select command.   * ccs_select_domain - Parse select command.
988   *   *
989   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
990   * @data: String to parse.   * @data: String to parse.
# Line 912  static bool ccs_manager(void) Line 993  static bool ccs_manager(void)
993   *   *
994   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
995   */   */
996  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)
997  {  {
998          unsigned int pid;          unsigned int pid;
999          struct ccs_domain_info *domain = NULL;          struct ccs_domain_info *domain = NULL;
1000          bool global_pid = false;          bool global_pid = false;
1001          if (!strcmp(data, "execute")) {          if (strncmp(data, "select ", 7))
1002                  head->r.print_execute_only = true;                  return false;
1003                  return true;          data += 7;
         }  
1004          if (sscanf(data, "pid=%u", &pid) == 1 ||          if (sscanf(data, "pid=%u", &pid) == 1 ||
1005              (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {              (global_pid = true, sscanf(data, "global-pid=%u", &pid) == 1)) {
1006                  struct task_struct *p;                  struct task_struct *p;
# Line 938  static bool ccs_select_one(struct ccs_io Line 1018  static bool ccs_select_one(struct ccs_io
1018                          domain = ccs_task_domain(p);                          domain = ccs_task_domain(p);
1019                  ccs_tasklist_unlock();                  ccs_tasklist_unlock();
1020          } else if (!strncmp(data, "domain=", 7)) {          } else if (!strncmp(data, "domain=", 7)) {
1021                  if (ccs_domain_def(data + 7))                  if (*(data + 7) == '<')
1022                          domain = ccs_find_domain(data + 7);                          domain = ccs_find_domain(data + 7);
1023          } else          } else
1024                  return false;                  return false;
# Line 996  static bool ccs_same_task_acl(const stru Line 1076  static bool ccs_same_task_acl(const stru
1076   * @param: Pointer to "struct ccs_acl_param".   * @param: Pointer to "struct ccs_acl_param".
1077   *   *
1078   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1079     *
1080     * Caller holds ccs_read_lock().
1081   */   */
1082  static int ccs_write_task(struct ccs_acl_param *param)  static int ccs_write_task(struct ccs_acl_param *param)
1083  {  {
# Line 1044  static int ccs_write_task(struct ccs_acl Line 1126  static int ccs_write_task(struct ccs_acl
1126  /**  /**
1127   * ccs_write_domain2 - Write domain policy.   * ccs_write_domain2 - Write domain policy.
1128   *   *
1129     * @ns:        Pointer to "struct ccs_policy_namespace".
1130     * @list:      Pointer to "struct list_head [2]".
1131   * @data:      Policy to be interpreted.   * @data:      Policy to be interpreted.
  * @domain:    Pointer to "struct ccs_domain_info".  
1132   * @is_delete: True if it is a delete request.   * @is_delete: True if it is a delete request.
1133   *   *
1134   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1135     *
1136     * Caller holds ccs_read_lock().
1137   */   */
1138  static int ccs_write_domain2(char *data, struct ccs_domain_info *domain,  static int ccs_write_domain2(struct ccs_policy_namespace *ns,
1139                                 struct list_head list[2], char *data,
1140                               const bool is_delete)                               const bool is_delete)
1141  {  {
1142          struct ccs_acl_param param = {          struct ccs_acl_param param = {
1143                    .ns = ns,
1144                    .list = list,
1145                  .data = data,                  .data = data,
                 .domain = domain,  
1146                  .is_delete = is_delete,                  .is_delete = is_delete,
1147          };          };
1148          static const struct {          static const struct {
# Line 1067  static int ccs_write_domain2(char *data, Line 1154  static int ccs_write_domain2(char *data,
1154                  { "network unix ", ccs_write_unix_network },                  { "network unix ", ccs_write_unix_network },
1155                  { "misc ", ccs_write_misc },                  { "misc ", ccs_write_misc },
1156                  { "capability ", ccs_write_capability },                  { "capability ", ccs_write_capability },
1157                  { "ipc ", ccs_write_ipc },                  { "ipc signal ", ccs_write_ipc },
1158                  { "task ", ccs_write_task },                  { "task ", ccs_write_task },
1159          };          };
1160          u8 i;          u8 i;
# Line 1079  static int ccs_write_domain2(char *data, Line 1166  static int ccs_write_domain2(char *data,
1166          return -EINVAL;          return -EINVAL;
1167  }  }
1168    
1169    /**
1170     * ccs_delete_domain - Delete a domain.
1171     *
1172     * @domainname: The name of domain.
1173     *
1174     * Returns 0.
1175     */
1176    static int ccs_delete_domain(char *domainname)
1177    {
1178            struct ccs_domain_info *domain;
1179            struct ccs_path_info name;
1180            name.name = domainname;
1181            ccs_fill_path_info(&name);
1182            if (mutex_lock_interruptible(&ccs_policy_lock))
1183                    return 0;
1184            /* Is there an active domain? */
1185            list_for_each_entry_srcu(domain, &ccs_domain_list, list, &ccs_ss) {
1186                    /* Never delete ccs_kernel_domain. */
1187                    if (domain == &ccs_kernel_domain)
1188                            continue;
1189                    if (domain->is_deleted ||
1190                        ccs_pathcmp(domain->domainname, &name))
1191                            continue;
1192                    domain->is_deleted = true;
1193                    break;
1194            }
1195            mutex_unlock(&ccs_policy_lock);
1196            return 0;
1197    }
1198    
1199  /* String table for domain flags. */  /* String table for domain flags. */
1200  const char * const ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = {  const char * const ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = {
1201          [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 1208  const char * const ccs_dif[CCS_MAX_DOMAI
1208   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1209   *   *
1210   * Returns 0 on success, negative value otherwise.   * Returns 0 on success, negative value otherwise.
1211     *
1212     * Caller holds ccs_read_lock().
1213   */   */
1214  static int ccs_write_domain(struct ccs_io_buffer *head)  static int ccs_write_domain(struct ccs_io_buffer *head)
1215  {  {
1216          char *data = head->write_buf;          char *data = head->write_buf;
1217            struct ccs_policy_namespace *ns;
1218          struct ccs_domain_info *domain = head->w.domain;          struct ccs_domain_info *domain = head->w.domain;
1219          bool is_delete = false;          const bool is_delete = head->w.is_delete;
1220          bool is_select = false;          const bool is_select = !is_delete && ccs_str_starts(&data, "select ");
1221          unsigned int profile;          unsigned int profile;
1222          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)) {  
1223                  domain = NULL;                  domain = NULL;
1224                  if (is_delete)                  if (is_delete)
1225                          ccs_delete_domain(data);                          ccs_delete_domain(data);
1226                  else if (is_select)                  else if (is_select)
1227                          domain = ccs_find_domain(data);                          domain = ccs_find_domain(data);
1228                  else                  else
1229                          domain = ccs_assign_domain(data, 0, 0, false);                          domain = ccs_assign_domain(data, false);
1230                  head->w.domain = domain;                  head->w.domain = domain;
1231                  return 0;                  return 0;
1232          }          }
1233          if (!domain)          if (!domain)
1234                  return -EINVAL;                  return -EINVAL;
1235            ns = domain->ns;
1236          if (sscanf(data, "use_profile %u\n", &profile) == 1          if (sscanf(data, "use_profile %u\n", &profile) == 1
1237              && profile < CCS_MAX_PROFILES) {              && profile < CCS_MAX_PROFILES) {
1238                  if (!ccs_policy_loaded || ccs_profile_ptr[(u8) profile])                  if (!ccs_policy_loaded || ns->profile_ptr[(u8) profile])
1239                          if (!is_delete)                          if (!is_delete)
1240                                  domain->profile = (u8) profile;                                  domain->profile = (u8) profile;
1241                  return 0;                  return 0;
# Line 1142  static int ccs_write_domain(struct ccs_i Line 1253  static int ccs_write_domain(struct ccs_i
1253                  domain->flags[profile] = !is_delete;                  domain->flags[profile] = !is_delete;
1254                  return 0;                  return 0;
1255          }          }
1256          return ccs_write_domain2(data, domain, is_delete);          return ccs_write_domain2(ns, domain->acl_info_list, data, is_delete);
1257  }  }
1258    
1259  /**  /**
# Line 1156  static int ccs_write_domain(struct ccs_i Line 1267  static int ccs_write_domain(struct ccs_i
1267  static void ccs_print_name_union(struct ccs_io_buffer *head,  static void ccs_print_name_union(struct ccs_io_buffer *head,
1268                                   const struct ccs_name_union *ptr)                                   const struct ccs_name_union *ptr)
1269  {  {
1270          const bool cond = head->r.print_cond_part;          ccs_set_space(head);
         if (!cond)  
                 ccs_set_space(head);  
1271          if (ptr->is_group) {          if (ptr->is_group) {
1272                  ccs_set_string(head, "@");                  ccs_set_string(head, "@");
1273                  ccs_set_string(head, ptr->group->group_name->name);                  ccs_set_string(head, ptr->group->group_name->name);
1274          } else {          } else {
                 if (cond)  
                         ccs_set_string(head, "\"");  
1275                  ccs_set_string(head, ptr->filename->name);                  ccs_set_string(head, ptr->filename->name);
                 if (cond)  
                         ccs_set_string(head, "\"");  
1276          }          }
1277  }  }
1278    
1279  /**  /**
1280   * ccs_print_number_union - Print a ccs_number_union.   * ccs_print_name_union_quoted - Print a ccs_name_union with a quote.
1281     *
1282     * @head: Pointer to "struct ccs_io_buffer".
1283     * @ptr:  Pointer to "struct ccs_name_union".
1284     *
1285     * Returns nothing.
1286     */
1287    static void ccs_print_name_union_quoted(struct ccs_io_buffer *head,
1288                                            const struct ccs_name_union *ptr)
1289    {
1290            if (ptr->is_group) {
1291                    ccs_set_string(head, "@");
1292                    ccs_set_string(head, ptr->group->group_name->name);
1293            } else {
1294                    ccs_set_string(head, "\"");
1295                    ccs_set_string(head, ptr->filename->name);
1296                    ccs_set_string(head, "\"");
1297            }
1298    }
1299    
1300    /**
1301     * ccs_print_number_union_nospace - Print a ccs_number_union without a space.
1302   *   *
1303   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1304   * @ptr:  Pointer to "struct ccs_number_union".   * @ptr:  Pointer to "struct ccs_number_union".
1305   *   *
1306   * Returns nothing.   * Returns nothing.
1307   */   */
1308  static void ccs_print_number_union(struct ccs_io_buffer *head,  static void ccs_print_number_union_nospace(struct ccs_io_buffer *head,
1309                                     const struct ccs_number_union *ptr)                                             const struct ccs_number_union *ptr)
1310  {  {
         if (!head->r.print_cond_part)  
                 ccs_set_space(head);  
1311          if (ptr->is_group) {          if (ptr->is_group) {
1312                  ccs_set_string(head, "@");                  ccs_set_string(head, "@");
1313                  ccs_set_string(head, ptr->group->group_name->name);                  ccs_set_string(head, ptr->group->group_name->name);
# Line 1221  static void ccs_print_number_union(struc Line 1345  static void ccs_print_number_union(struc
1345  }  }
1346    
1347  /**  /**
1348     * ccs_print_number_union - Print a ccs_number_union.
1349     *
1350     * @head: Pointer to "struct ccs_io_buffer".
1351     * @ptr:  Pointer to "struct ccs_number_union".
1352     *
1353     * Returns nothing.
1354     */
1355    static void ccs_print_number_union(struct ccs_io_buffer *head,
1356                                       const struct ccs_number_union *ptr)
1357    {
1358            ccs_set_space(head);
1359            ccs_print_number_union_nospace(head, ptr);
1360    }
1361    
1362    /**
1363   * ccs_print_condition - Print condition part.   * ccs_print_condition - Print condition part.
1364   *   *
1365   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
# Line 1287  static bool ccs_print_condition(struct c Line 1426  static bool ccs_print_condition(struct c
1426                                  switch (left) {                                  switch (left) {
1427                                  case CCS_ARGV_ENTRY:                                  case CCS_ARGV_ENTRY:
1428                                          ccs_io_printf(head,                                          ccs_io_printf(head,
1429                                                        "exec.argv[%u]%s\"%s\"",                                                        "exec.argv[%lu]%s=\"",
1430                                                        argv->index,                                                        argv->index,
1431                                                        argv->is_not ?                                                        argv->is_not ? "!" : "");
1432                                                        "!=" : "=",                                          ccs_set_string(head,
1433                                                        argv->value->name);                                                         argv->value->name);
1434                                            ccs_set_string(head, "\"");
1435                                          argv++;                                          argv++;
1436                                          continue;                                          continue;
1437                                  case CCS_ENVP_ENTRY:                                  case CCS_ENVP_ENTRY:
1438                                          ccs_io_printf(head,                                          ccs_set_string(head, "exec.envp[\"");
1439                                                        "exec.envp[\"%s\"]%s",                                          ccs_set_string(head, envp->name->name);
1440                                                        envp->name->name,                                          ccs_io_printf(head, "\"]%s=",
1441                                                        envp->is_not ?                                                        envp->is_not ? "!" : "");
                                                       "!=" : "=");  
1442                                          if (envp->value) {                                          if (envp->value) {
1443                                                  ccs_set_string(head, "\"");                                                  ccs_set_string(head, "\"");
1444                                                  ccs_set_string(head, envp->                                                  ccs_set_string(head, envp->
# Line 1311  static bool ccs_print_condition(struct c Line 1450  static bool ccs_print_condition(struct c
1450                                          envp++;                                          envp++;
1451                                          continue;                                          continue;
1452                                  case CCS_NUMBER_UNION:                                  case CCS_NUMBER_UNION:
1453                                          ccs_print_number_union(head,                                          ccs_print_number_union_nospace
1454                                                                 numbers_p++);                                                  (head, numbers_p++);
1455                                          break;                                          break;
1456                                  default:                                  default:
1457                                          ccs_set_string(head,                                          ccs_set_string(head,
# Line 1322  static bool ccs_print_condition(struct c Line 1461  static bool ccs_print_condition(struct c
1461                                  ccs_set_string(head, match ? "=" : "!=");                                  ccs_set_string(head, match ? "=" : "!=");
1462                                  switch (right) {                                  switch (right) {
1463                                  case CCS_NAME_UNION:                                  case CCS_NAME_UNION:
1464                                          ccs_print_name_union(head, names_p++);                                          ccs_print_name_union_quoted
1465                                                    (head, names_p++);
1466                                          break;                                          break;
1467                                  case CCS_NUMBER_UNION:                                  case CCS_NUMBER_UNION:
1468                                          ccs_print_number_union(head,                                          ccs_print_number_union_nospace
1469                                                                 numbers_p++);                                                  (head, numbers_p++);
1470                                          break;                                          break;
1471                                  default:                                  default:
1472                                          ccs_set_string(head,                                          ccs_set_string(head,
# Line 1348  static bool ccs_print_condition(struct c Line 1488  static bool ccs_print_condition(struct c
1488                                        ccs_yesno(cond->grant_log ==                                        ccs_yesno(cond->grant_log ==
1489                                                  CCS_GRANTLOG_YES));                                                  CCS_GRANTLOG_YES));
1490                  if (cond->transit) {                  if (cond->transit) {
1491                          ccs_set_string(head, " auto_domain_transition=\"");                          const char *name = cond->transit->name;
1492                          ccs_set_string(head, cond->transit->name);                          ccs_set_string(head, *name == '<' ?
1493                                           " auto_namespace_transition=\"" :
1494                                           " auto_domain_transition=\"");
1495                            ccs_set_string(head, name);
1496                          ccs_set_string(head, "\"");                          ccs_set_string(head, "\"");
1497                  }                  }
1498                  ccs_set_lf(head);                  ccs_set_lf(head);
# Line 1359  static bool ccs_print_condition(struct c Line 1502  static bool ccs_print_condition(struct c
1502  }  }
1503    
1504  /**  /**
1505   * 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.  
1506   *   *
1507   * @head: Pointer to "struct ccs_io_buffer".   * @head:     Pointer to "struct ccs_io_buffer".
1508     * @category: Category name.
1509   *   *
1510   * Returns nothing.   * Returns nothing.
1511   */   */
1512  static void ccs_set_group(struct ccs_io_buffer *head)  static void ccs_set_group(struct ccs_io_buffer *head, const char *category)
1513  {  {
1514          if (head->type == CCS_EXCEPTIONPOLICY)          if (head->type == CCS_EXCEPTIONPOLICY) {
1515                  ccs_io_printf(head, "acl_group %u ", head->r.group_index);                  ccs_print_namespace(head);
1516                    ccs_io_printf(head, "acl_group %u ", head->r.acl_group_index);
1517            }
1518            ccs_set_string(head, category);
1519  }  }
1520    
1521  /**  /**
# Line 1399  static bool ccs_print_entry(struct ccs_i Line 1530  static bool ccs_print_entry(struct ccs_i
1530                              const struct ccs_acl_info *acl)                              const struct ccs_acl_info *acl)
1531  {  {
1532          const u8 acl_type = acl->type;          const u8 acl_type = acl->type;
1533            const bool may_trigger_transition = acl->cond && acl->cond->transit;
1534            bool first = true;
1535          u8 bit;          u8 bit;
1536          if (head->r.print_cond_part)          if (head->r.print_cond_part)
1537                  goto print_cond_part;                  goto print_cond_part;
1538          if (acl->is_deleted)          if (acl->is_deleted)
1539                  return true;                  return true;
 next:  
         bit = head->r.bit;  
1540          if (!ccs_flush(head))          if (!ccs_flush(head))
1541                  return false;                  return false;
1542          else if (acl_type == CCS_TYPE_PATH_ACL) {          else if (acl_type == CCS_TYPE_PATH_ACL) {
1543                  struct ccs_path_acl *ptr                  struct ccs_path_acl *ptr
1544                          = container_of(acl, typeof(*ptr), head);                          = container_of(acl, typeof(*ptr), head);
1545                  const u16 perm = ptr->perm;                  const u16 perm = ptr->perm;
1546                  for ( ; bit < CCS_MAX_PATH_OPERATION; bit++) {                  for (bit = 0; bit < CCS_MAX_PATH_OPERATION; bit++) {
1547                          if (!(perm & (1 << bit)))                          if (!(perm & (1 << bit)))
1548                                  continue;                                  continue;
1549                          if (head->r.print_execute_only &&                          if (head->r.print_transition_related_only &&
1550                              bit != CCS_TYPE_EXECUTE                              bit != CCS_TYPE_EXECUTE && !may_trigger_transition)
                             /* && bit != CCS_TYPE_TRANSIT */)  
1551                                  continue;                                  continue;
1552                          break;                          if (first) {
1553                                    ccs_set_group(head, "file ");
1554                                    first = false;
1555                            } else {
1556                                    ccs_set_slash(head);
1557                            }
1558                            ccs_set_string(head, ccs_path_keyword[bit]);
1559                  }                  }
1560                  if (bit >= CCS_MAX_PATH_OPERATION)                  if (first)
1561                          goto done;                          return true;
                 ccs_set_group(head);  
                 ccs_set_string(head, "file ");  
                 ccs_set_string(head, ccs_path_keyword[bit]);  
1562                  ccs_print_name_union(head, &ptr->name);                  ccs_print_name_union(head, &ptr->name);
1563          } else if (acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER ||          } else if (acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER ||
1564                     acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {                     acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {
1565                  struct ccs_handler_acl *ptr                  struct ccs_handler_acl *ptr
1566                          = container_of(acl, typeof(*ptr), head);                          = container_of(acl, typeof(*ptr), head);
1567                  ccs_set_group(head);                  ccs_set_group(head, "task ");
                 ccs_set_string(head, "task ");  
1568                  ccs_set_string(head, acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER                  ccs_set_string(head, acl_type == CCS_TYPE_AUTO_EXECUTE_HANDLER
1569                                 ? "auto_execute_handler " :                                 ? "auto_execute_handler " :
1570                                 "denied_execute_handler ");                                 "denied_execute_handler ");
# Line 1441  next: Line 1573  next:
1573                     acl_type == CCS_TYPE_MANUAL_TASK_ACL) {                     acl_type == CCS_TYPE_MANUAL_TASK_ACL) {
1574                  struct ccs_task_acl *ptr =                  struct ccs_task_acl *ptr =
1575                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1576                  ccs_set_group(head);                  ccs_set_group(head, "task ");
                 ccs_set_string(head, "task ");  
1577                  ccs_set_string(head, acl_type == CCS_TYPE_AUTO_TASK_ACL ?                  ccs_set_string(head, acl_type == CCS_TYPE_AUTO_TASK_ACL ?
1578                                 "auto_domain_transition " :                                 "auto_domain_transition " :
1579                                 "manual_domain_transition ");                                 "manual_domain_transition ");
1580                  ccs_set_string(head, ptr->domainname->name);                  ccs_set_string(head, ptr->domainname->name);
1581          } else if (head->r.print_execute_only) {          } else if (head->r.print_transition_related_only &&
1582                       !may_trigger_transition) {
1583                  return true;                  return true;
1584          } else if (acl_type == CCS_TYPE_MKDEV_ACL) {          } else if (acl_type == CCS_TYPE_MKDEV_ACL) {
1585                  struct ccs_mkdev_acl *ptr =                  struct ccs_mkdev_acl *ptr =
1586                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1587                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1588                  if (bit >= CCS_MAX_MKDEV_OPERATION)                  for (bit = 0; bit < CCS_MAX_MKDEV_OPERATION; bit++) {
1589                          goto done;                          if (!(perm & (1 << bit)))
1590                  ccs_set_group(head);                                  continue;
1591                  ccs_set_string(head, "file ");                          if (first) {
1592                  ccs_set_string(head, ccs_mac_keywords[ccs_pnnn2mac[bit]]);                                  ccs_set_group(head, "file ");
1593                                    first = false;
1594                            } else {
1595                                    ccs_set_slash(head);
1596                            }
1597                            ccs_set_string(head, ccs_mac_keywords
1598                                           [ccs_pnnn2mac[bit]]);
1599                    }
1600                    if (first)
1601                            return true;
1602                  ccs_print_name_union(head, &ptr->name);                  ccs_print_name_union(head, &ptr->name);
1603                  ccs_print_number_union(head, &ptr->mode);                  ccs_print_number_union(head, &ptr->mode);
1604                  ccs_print_number_union(head, &ptr->major);                  ccs_print_number_union(head, &ptr->major);
# Line 1465  next: Line 1606  next:
1606          } else if (acl_type == CCS_TYPE_PATH2_ACL) {          } else if (acl_type == CCS_TYPE_PATH2_ACL) {
1607                  struct ccs_path2_acl *ptr =                  struct ccs_path2_acl *ptr =
1608                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1609                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1610                  if (bit >= CCS_MAX_PATH2_OPERATION)                  for (bit = 0; bit < CCS_MAX_PATH2_OPERATION; bit++) {
1611                          goto done;                          if (!(perm & (1 << bit)))
1612                  ccs_set_group(head);                                  continue;
1613                  ccs_set_string(head, "file ");                          if (first) {
1614                  ccs_set_string(head, ccs_mac_keywords[ccs_pp2mac[bit]]);                                  ccs_set_group(head, "file ");
1615                                    first = false;
1616                            } else {
1617                                    ccs_set_slash(head);
1618                            }
1619                            ccs_set_string(head, ccs_mac_keywords
1620                                           [ccs_pp2mac[bit]]);
1621                    }
1622                    if (first)
1623                            return true;
1624                  ccs_print_name_union(head, &ptr->name1);                  ccs_print_name_union(head, &ptr->name1);
1625                  ccs_print_name_union(head, &ptr->name2);                  ccs_print_name_union(head, &ptr->name2);
1626          } else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {          } else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
1627                  struct ccs_path_number_acl *ptr =                  struct ccs_path_number_acl *ptr =
1628                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1629                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1630                  if (bit >= CCS_MAX_PATH_NUMBER_OPERATION)                  for (bit = 0; bit < CCS_MAX_PATH_NUMBER_OPERATION; bit++) {
1631                          goto done;                          if (!(perm & (1 << bit)))
1632                  ccs_set_group(head);                                  continue;
1633                  ccs_set_string(head, "file ");                          if (first) {
1634                  ccs_set_string(head, ccs_mac_keywords[ccs_pn2mac[bit]]);                                  ccs_set_group(head, "file ");
1635                                    first = false;
1636                            } else {
1637                                    ccs_set_slash(head);
1638                            }
1639                            ccs_set_string(head, ccs_mac_keywords
1640                                           [ccs_pn2mac[bit]]);
1641                    }
1642                    if (first)
1643                            return true;
1644                  ccs_print_name_union(head, &ptr->name);                  ccs_print_name_union(head, &ptr->name);
1645                  ccs_print_number_union(head, &ptr->number);                  ccs_print_number_union(head, &ptr->number);
1646          } else if (acl_type == CCS_TYPE_ENV_ACL) {          } else if (acl_type == CCS_TYPE_ENV_ACL) {
1647                  struct ccs_env_acl *ptr =                  struct ccs_env_acl *ptr =
1648                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1649                  ccs_set_group(head);                  ccs_set_group(head, "misc env ");
                 ccs_set_string(head, "misc env ");  
1650                  ccs_set_string(head, ptr->env->name);                  ccs_set_string(head, ptr->env->name);
1651          } else if (acl_type == CCS_TYPE_CAPABILITY_ACL) {          } else if (acl_type == CCS_TYPE_CAPABILITY_ACL) {
1652                  struct ccs_capability_acl *ptr =                  struct ccs_capability_acl *ptr =
1653                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1654                  ccs_set_group(head);                  ccs_set_group(head, "capability ");
1655                  ccs_set_string(head, "capability ");                  ccs_set_string(head, ccs_mac_keywords
1656                  ccs_set_string(head,                                 [ccs_c2mac[ptr->operation]]);
                                ccs_mac_keywords[ccs_c2mac[ptr->operation]]);  
1657          } else if (acl_type == CCS_TYPE_INET_ACL) {          } else if (acl_type == CCS_TYPE_INET_ACL) {
1658                  struct ccs_inet_acl *ptr =                  struct ccs_inet_acl *ptr =
1659                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1660                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1661                  if (bit >= CCS_MAX_NETWORK_OPERATION)                  for (bit = 0; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
1662                          goto done;                          if (!(perm & (1 << bit)))
1663                  ccs_set_group(head);                                  continue;
1664                  ccs_set_string(head, "network inet ");                          if (first) {
1665                  ccs_set_string(head, ccs_proto_keyword[ptr->protocol]);                                  ccs_set_group(head, "network inet ");
1666                  ccs_set_space(head);                                  ccs_set_string(head, ccs_proto_keyword
1667                  ccs_set_string(head, ccs_socket_keyword[bit]);                                                 [ptr->protocol]);
1668                                    ccs_set_space(head);
1669                                    first = false;
1670                            } else {
1671                                    ccs_set_slash(head);
1672                            }
1673                            ccs_set_string(head, ccs_socket_keyword[bit]);
1674                    }
1675                    if (first)
1676                            return true;
1677                  ccs_set_space(head);                  ccs_set_space(head);
1678                  switch (ptr->address_type) {                  if (ptr->address.group) {
                         char buf[128];  
                 case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP:  
1679                          ccs_set_string(head, "@");                          ccs_set_string(head, "@");
1680                          ccs_set_string(head,                          ccs_set_string(head,
1681                                         ptr->address.group->group_name->name);                                         ptr->address.group->group_name->name);
1682                          break;                  } else {
1683                  case CCS_IP_ADDRESS_TYPE_IPv4:                          char buf[128];
1684                          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);  
1685                          ccs_io_printf(head, "%s", buf);                          ccs_io_printf(head, "%s", buf);
                         break;  
1686                  }                  }
1687                  ccs_print_number_union(head, &ptr->port);                  ccs_print_number_union(head, &ptr->port);
1688          } else if (acl_type == CCS_TYPE_UNIX_ACL) {          } else if (acl_type == CCS_TYPE_UNIX_ACL) {
1689                  struct ccs_unix_acl *ptr =                  struct ccs_unix_acl *ptr =
1690                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1691                  bit = ccs_fns(ptr->perm, bit);                  const u8 perm = ptr->perm;
1692                  if (bit >= CCS_MAX_NETWORK_OPERATION)                  for (bit = 0; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
1693                          goto done;                          if (!(perm & (1 << bit)))
1694                  ccs_set_group(head);                                  continue;
1695                  ccs_set_string(head, "network unix ");                          if (first) {
1696                  ccs_set_string(head, ccs_proto_keyword[ptr->protocol]);                                  ccs_set_group(head, "network unix ");
1697                  ccs_set_space(head);                                  ccs_set_string(head, ccs_proto_keyword
1698                  ccs_set_string(head, ccs_socket_keyword[bit]);                                                 [ptr->protocol]);
1699                                    ccs_set_space(head);
1700                                    first = false;
1701                            } else {
1702                                    ccs_set_slash(head);
1703                            }
1704                            ccs_set_string(head, ccs_socket_keyword[bit]);
1705                    }
1706                    if (first)
1707                            return true;
1708                  ccs_print_name_union(head, &ptr->name);                  ccs_print_name_union(head, &ptr->name);
1709          } else if (acl_type == CCS_TYPE_SIGNAL_ACL) {          } else if (acl_type == CCS_TYPE_SIGNAL_ACL) {
1710                  struct ccs_signal_acl *ptr =                  struct ccs_signal_acl *ptr =
1711                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1712                  ccs_set_group(head);                  ccs_set_group(head, "ipc signal ");
1713                  ccs_set_string(head, "ipc signal ");                  ccs_print_number_union_nospace(head, &ptr->sig);
1714                  ccs_io_printf(head, "%u ", ptr->sig);                  ccs_set_space(head);
1715                  ccs_set_string(head, ptr->domainname->name);                  ccs_set_string(head, ptr->domainname->name);
1716          } else if (acl_type == CCS_TYPE_MOUNT_ACL) {          } else if (acl_type == CCS_TYPE_MOUNT_ACL) {
1717                  struct ccs_mount_acl *ptr =                  struct ccs_mount_acl *ptr =
1718                          container_of(acl, typeof(*ptr), head);                          container_of(acl, typeof(*ptr), head);
1719                  ccs_set_group(head);                  ccs_set_group(head, "file mount");
                 ccs_io_printf(head, "file mount");  
1720                  ccs_print_name_union(head, &ptr->dev_name);                  ccs_print_name_union(head, &ptr->dev_name);
1721                  ccs_print_name_union(head, &ptr->dir_name);                  ccs_print_name_union(head, &ptr->dir_name);
1722                  ccs_print_name_union(head, &ptr->fs_type);                  ccs_print_name_union(head, &ptr->fs_type);
1723                  ccs_print_number_union(head, &ptr->flags);                  ccs_print_number_union(head, &ptr->flags);
1724          }          }
         head->r.bit = bit + 1;  
1725          if (acl->cond) {          if (acl->cond) {
1726                  head->r.print_cond_part = true;                  head->r.print_cond_part = true;
1727                  head->r.cond_step = 0;                  head->r.cond_step = 0;
# Line 1570  print_cond_part: Line 1734  print_cond_part:
1734          } else {          } else {
1735                  ccs_set_lf(head);                  ccs_set_lf(head);
1736          }          }
         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;  
1737          return true;          return true;
1738  }  }
1739    
1740  /**  /**
1741   * ccs_read_domain2 - Read domain policy.   * ccs_read_domain2 - Read domain policy.
1742   *   *
1743   * @head:   Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1744   * @domain: Pointer to "struct ccs_domain_info".   * @list: Pointer to "struct list_head".
  * @index:  Index number.  
1745   *   *
1746   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1747   *   *
1748   * Caller holds ccs_read_lock().   * Caller holds ccs_read_lock().
1749   */   */
1750  static bool ccs_read_domain2(struct ccs_io_buffer *head,  static bool ccs_read_domain2(struct ccs_io_buffer *head,
1751                               struct ccs_domain_info *domain,                               struct list_head *list)
                              const u8 index)  
1752  {  {
1753          list_for_each_cookie(head->r.acl, &domain->acl_info_list[index]) {          list_for_each_cookie(head->r.acl, list) {
1754                  struct ccs_acl_info *ptr =                  struct ccs_acl_info *ptr =
1755                          list_entry(head->r.acl, typeof(*ptr), list);                          list_entry(head->r.acl, typeof(*ptr), list);
1756                  if (!ccs_print_entry(head, ptr))                  if (!ccs_print_entry(head, ptr))
# Line 1644  static void ccs_read_domain(struct ccs_i Line 1795  static void ccs_read_domain(struct ccs_i
1795                          ccs_set_lf(head);                          ccs_set_lf(head);
1796                          /* fall through */                          /* fall through */
1797                  case 1:                  case 1:
1798                          if (!ccs_read_domain2(head, domain, 0))                          if (!ccs_read_domain2(head, &domain->acl_info_list[0]))
1799                                  return;                                  return;
1800                          head->r.step++;                          head->r.step++;
1801                          /* fall through */                          /* fall through */
1802                  case 2:                  case 2:
1803                          if (!ccs_read_domain2(head, domain, 1))                          if (!ccs_read_domain2(head, &domain->acl_info_list[1]))
1804                                  return;                                  return;
1805                          head->r.step++;                          head->r.step++;
1806                          if (!ccs_set_lf(head))                          if (!ccs_set_lf(head))
# Line 1692  static int ccs_write_domain_profile(stru Line 1843  static int ccs_write_domain_profile(stru
1843          if (profile >= CCS_MAX_PROFILES)          if (profile >= CCS_MAX_PROFILES)
1844                  return -EINVAL;                  return -EINVAL;
1845          domain = ccs_find_domain(cp + 1);          domain = ccs_find_domain(cp + 1);
1846          if (domain && (!ccs_policy_loaded || ccs_profile_ptr[(u8) profile]))          if (domain && (!ccs_policy_loaded ||
1847                           head->w.ns->profile_ptr[(u8) profile]))
1848                  domain->profile = (u8) profile;                  domain->profile = (u8) profile;
1849          return 0;          return 0;
1850  }  }
# Line 1807  static void ccs_read_pid(struct ccs_io_b Line 1959  static void ccs_read_pid(struct ccs_io_b
1959    
1960  /* String table for domain transition control keywords. */  /* String table for domain transition control keywords. */
1961  static const char * const ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {  static const char * const ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {
1962            [CCS_TRANSITION_CONTROL_NO_NAMESPACE]  = "no_move_namespace ",
1963            [CCS_TRANSITION_CONTROL_NAMESPACE]     = "move_namespace ",
1964          [CCS_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ",          [CCS_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ",
1965          [CCS_TRANSITION_CONTROL_INITIALIZE]    = "initialize_domain ",          [CCS_TRANSITION_CONTROL_INITIALIZE]    = "initialize_domain ",
1966          [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 1983  static const char * const ccs_group_name
1983   */   */
1984  static int ccs_write_exception(struct ccs_io_buffer *head)  static int ccs_write_exception(struct ccs_io_buffer *head)
1985  {  {
1986          char *data = head->write_buf;          const bool is_delete = head->w.is_delete;
1987          const bool is_delete = ccs_str_starts(&data, "delete ");          struct ccs_acl_param param = {
1988          u8 i;                  .ns = head->w.ns,
1989          static const struct {                  .is_delete = is_delete,
1990                  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 },  
1991          };          };
1992          for (i = 0; i < 2; i++)          u8 i;
1993                  if (ccs_str_starts(&data, ccs_callback[i].keyword))          if (ccs_str_starts(&param.data, "aggregator "))
1994                          return ccs_callback[i].write(data, is_delete);                  return ccs_write_aggregator(&param);
1995            if (ccs_str_starts(&param.data, "deny_autobind "))
1996                    return ccs_write_reserved_port(&param);
1997          for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)          for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)
1998                  if (ccs_str_starts(&data, ccs_transition_type[i]))                  if (ccs_str_starts(&param.data, ccs_transition_type[i]))
1999                          return ccs_write_transition_control(data, is_delete,                          return ccs_write_transition_control(&param, i);
                                                             i);  
2000          for (i = 0; i < CCS_MAX_GROUP; i++)          for (i = 0; i < CCS_MAX_GROUP; i++)
2001                  if (ccs_str_starts(&data, ccs_group_name[i]))                  if (ccs_str_starts(&param.data, ccs_group_name[i]))
2002                          return ccs_write_group(data, is_delete, i);                          return ccs_write_group(&param, i);
2003          if (ccs_str_starts(&data, "acl_group ")) {          if (ccs_str_starts(&param.data, "acl_group ")) {
2004                  unsigned int group;                  unsigned int group;
2005                  if (sscanf(data, "%u", &group) == 1 &&                  char *data;
2006                      group < CCS_MAX_ACL_GROUPS) {                  group = simple_strtoul(param.data, &data, 10);
2007                          data = strchr(data, ' ');                  if (group < CCS_MAX_ACL_GROUPS && *data++ == ' ')
2008                          if (data)                          return ccs_write_domain2(head->w.ns,
2009                                  return ccs_write_domain2(data + 1,                                                   head->w.ns->acl_group[group],
2010                                                           &ccs_acl_group[group],                                                   data, is_delete);
                                                          is_delete);  
                 }  
2011          }          }
2012          return -EINVAL;          return -EINVAL;
2013  }  }
# Line 1875  static int ccs_write_exception(struct cc Line 2024  static int ccs_write_exception(struct cc
2024   */   */
2025  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)
2026  {  {
2027          list_for_each_cookie(head->r.group, &ccs_group_list[idx]) {          struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
2028                                                           namespace_list);
2029            struct list_head *list = &ns->group_list[idx];
2030            list_for_each_cookie(head->r.group, list) {
2031                  struct ccs_group *group =                  struct ccs_group *group =
2032                          list_entry(head->r.group, typeof(*group), head.list);                          list_entry(head->r.group, typeof(*group), head.list);
2033                  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 2037  static bool ccs_read_group(struct ccs_io
2037                                  continue;                                  continue;
2038                          if (!ccs_flush(head))                          if (!ccs_flush(head))
2039                                  return false;                                  return false;
2040                            ccs_print_namespace(head);
2041                          ccs_set_string(head, ccs_group_name[idx]);                          ccs_set_string(head, ccs_group_name[idx]);
2042                          ccs_set_string(head, group->group_name->name);                          ccs_set_string(head, group->group_name->name);
2043                          if (idx == CCS_PATH_GROUP) {                          if (idx == CCS_PATH_GROUP) {
# Line 1901  static bool ccs_read_group(struct ccs_io Line 2054  static bool ccs_read_group(struct ccs_io
2054                                  struct ccs_address_group *member =                                  struct ccs_address_group *member =
2055                                          container_of(ptr, typeof(*member),                                          container_of(ptr, typeof(*member),
2056                                                       head);                                                       head);
2057                                  if (member->is_ipv6)                                  ccs_print_ip(buffer, sizeof(buffer),
2058                                          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);  
2059                                  ccs_io_printf(head, " %s", buffer);                                  ccs_io_printf(head, " %s", buffer);
2060                          }                          }
2061                          ccs_set_lf(head);                          ccs_set_lf(head);
# Line 1931  static bool ccs_read_group(struct ccs_io Line 2078  static bool ccs_read_group(struct ccs_io
2078   */   */
2079  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)
2080  {  {
2081          list_for_each_cookie(head->r.acl, &ccs_policy_list[idx]) {          struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
2082                                                           namespace_list);
2083            struct list_head *list = &ns->policy_list[idx];
2084            list_for_each_cookie(head->r.acl, list) {
2085                  struct ccs_acl_head *acl =                  struct ccs_acl_head *acl =
2086                          container_of(head->r.acl, typeof(*acl), list);                          container_of(head->r.acl, typeof(*acl), list);
2087                  if (acl->is_deleted)                  if (acl->is_deleted)
2088                          continue;                          continue;
2089                    if (head->r.print_transition_related_only &&
2090                        idx != CCS_ID_TRANSITION_CONTROL)
2091                            continue;
2092                  if (!ccs_flush(head))                  if (!ccs_flush(head))
2093                          return false;                          return false;
2094                  switch (idx) {                  switch (idx) {
# Line 1943  static bool ccs_read_policy(struct ccs_i Line 2096  static bool ccs_read_policy(struct ccs_i
2096                          {                          {
2097                                  struct ccs_transition_control *ptr =                                  struct ccs_transition_control *ptr =
2098                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
2099                                    ccs_print_namespace(head);
2100                                  ccs_set_string(head,                                  ccs_set_string(head,
2101                                                 ccs_transition_type[ptr->type]);                                                 ccs_transition_type[ptr->type]);
2102                                  ccs_set_string(head, ptr->program ?                                  ccs_set_string(head, ptr->program ?
# Line 1956  static bool ccs_read_policy(struct ccs_i Line 2110  static bool ccs_read_policy(struct ccs_i
2110                          {                          {
2111                                  struct ccs_aggregator *ptr =                                  struct ccs_aggregator *ptr =
2112                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
2113                                    ccs_print_namespace(head);
2114                                  ccs_set_string(head, "aggregator ");                                  ccs_set_string(head, "aggregator ");
2115                                  ccs_set_string(head, ptr->original_name->name);                                  ccs_set_string(head, ptr->original_name->name);
2116                                  ccs_set_space(head);                                  ccs_set_space(head);
# Line 1967  static bool ccs_read_policy(struct ccs_i Line 2122  static bool ccs_read_policy(struct ccs_i
2122                          {                          {
2123                                  struct ccs_reserved *ptr =                                  struct ccs_reserved *ptr =
2124                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
2125                                  const u16 min_port = ptr->min_port;                                  ccs_print_namespace(head);
                                 const u16 max_port = ptr->max_port;  
2126                                  ccs_set_string(head, "deny_autobind ");                                  ccs_set_string(head, "deny_autobind ");
2127                                  ccs_io_printf(head, "%u", min_port);                                  ccs_print_number_union_nospace(head,
2128                                  if (min_port != max_port)                                                                 &ptr->port);
                                         ccs_io_printf(head, "-%u", max_port);  
2129                          }                          }
2130                          break;                          break;
2131                  default:                  default:
# Line 1995  static bool ccs_read_policy(struct ccs_i Line 2148  static bool ccs_read_policy(struct ccs_i
2148   */   */
2149  static void ccs_read_exception(struct ccs_io_buffer *head)  static void ccs_read_exception(struct ccs_io_buffer *head)
2150  {  {
2151            struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
2152                                                           namespace_list);
2153          if (head->r.eof)          if (head->r.eof)
2154                  return;                  return;
2155          while (head->r.step < CCS_MAX_POLICY &&          while (head->r.step < CCS_MAX_POLICY &&
# Line 2009  static void ccs_read_exception(struct cc Line 2164  static void ccs_read_exception(struct cc
2164                  return;                  return;
2165          while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP          while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP
2166                 + CCS_MAX_ACL_GROUPS * 2) {                 + CCS_MAX_ACL_GROUPS * 2) {
2167                  head->r.group_index = (head->r.step - CCS_MAX_POLICY                  head->r.acl_group_index = (head->r.step - CCS_MAX_POLICY
2168                                         - CCS_MAX_GROUP) / 2;                                             - CCS_MAX_GROUP) / 2;
2169                  if (!ccs_read_domain2(head,                  if (!ccs_read_domain2(head, &ns->acl_group
2170                                        &ccs_acl_group[head->r.group_index],                                        [head->r.acl_group_index]
2171                                        head->r.step & 1))                                        [head->r.step & 1]))
2172                          return;                          return;
2173                  head->r.step++;                  head->r.step++;
2174          }          }
# Line 2029  static DECLARE_WAIT_QUEUE_HEAD(ccs_answe Line 2184  static DECLARE_WAIT_QUEUE_HEAD(ccs_answe
2184  struct ccs_query {  struct ccs_query {
2185          struct list_head list;          struct list_head list;
2186          char *query;          char *query;
2187          int query_len;          size_t query_len;
2188          unsigned int serial;          unsigned int serial;
2189          int timer;          u8 timer;
2190          int answer;          u8 answer;
2191          u8 retry;          u8 retry;
2192  };  };
2193    
# Line 2116  static void ccs_add_entry(char *header) Line 2271  static void ccs_add_entry(char *header)
2271          if (symlink)          if (symlink)
2272                  ccs_addprintf(buffer, len, "%s", symlink);                  ccs_addprintf(buffer, len, "%s", symlink);
2273          ccs_normalize_line(buffer);          ccs_normalize_line(buffer);
2274          if (!ccs_write_domain2(buffer, ccs_current_domain(), false))          {
2275                  ccs_update_stat(CCS_STAT_POLICY_UPDATES);                  struct ccs_domain_info *domain = ccs_current_domain();
2276                    if (!ccs_write_domain2(domain->ns, domain->acl_info_list,
2277                                           buffer, false))
2278                            ccs_update_stat(CCS_STAT_POLICY_UPDATES);
2279            }
2280          kfree(buffer);          kfree(buffer);
2281  }  }
2282    
# Line 2170  int ccs_supervisor(struct ccs_request_in Line 2329  int ccs_supervisor(struct ccs_request_in
2329                  goto out;                  goto out;
2330          case CCS_CONFIG_LEARNING:          case CCS_CONFIG_LEARNING:
2331                  error = 0;                  error = 0;
2332                  /* Check mac_learning_entry parameter. */                  /* Check max_learning_entry parameter. */
2333                  if (ccs_domain_quota_ok(r))                  if (ccs_domain_quota_ok(r))
2334                          break;                          break;
2335                  /* fall through */                  /* fall through */
# Line 2280  static int ccs_poll_query(struct file *f Line 2439  static int ccs_poll_query(struct file *f
2439  static void ccs_read_query(struct ccs_io_buffer *head)  static void ccs_read_query(struct ccs_io_buffer *head)
2440  {  {
2441          struct list_head *tmp;          struct list_head *tmp;
2442          int pos = 0;          unsigned int pos = 0;
2443          int len = 0;          size_t len = 0;
2444          char *buf;          char *buf;
2445          if (head->r.w_pos)          if (head->r.w_pos)
2446                  return;                  return;
# Line 2318  static void ccs_read_query(struct ccs_io Line 2477  static void ccs_read_query(struct ccs_io
2477                   * can change, but I don't care.                   * can change, but I don't care.
2478                   */                   */
2479                  if (len == ptr->query_len)                  if (len == ptr->query_len)
2480                          snprintf(buf, len + 32, "Q%u-%hu\n%s", ptr->serial,                          snprintf(buf, len + 31, "Q%u-%hu\n%s", ptr->serial,
2481                                   ptr->retry, ptr->query);                                   ptr->retry, ptr->query);
2482                  break;                  break;
2483          }          }
# Line 2359  static int ccs_write_answer(struct ccs_i Line 2518  static int ccs_write_answer(struct ccs_i
2518                  if (ptr->serial != serial)                  if (ptr->serial != serial)
2519                          continue;                          continue;
2520                  if (!ptr->answer)                  if (!ptr->answer)
2521                          ptr->answer = answer;                          ptr->answer = (u8) answer;
2522                  break;                  break;
2523          }          }
2524          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
# Line 2378  static void ccs_read_version(struct ccs_ Line 2537  static void ccs_read_version(struct ccs_
2537  {  {
2538          if (head->r.eof)          if (head->r.eof)
2539                  return;                  return;
2540          ccs_set_string(head, "1.8.0");          ccs_set_string(head, "1.8.2-pre");
2541          head->r.eof = true;          head->r.eof = true;
2542  }  }
2543    
2544  /* String table for /proc/ccs/meminfo interface. */  /* String table for /proc/ccs/stat interface. */
2545  static const char * const ccs_policy_headers[CCS_MAX_POLICY_STAT] = {  static const char * const ccs_policy_headers[CCS_MAX_POLICY_STAT] = {
2546          [CCS_STAT_POLICY_UPDATES]    = "update:",          [CCS_STAT_POLICY_UPDATES]    = "update:",
2547          [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 2549  static const char * const ccs_policy_hea
2549          [CCS_STAT_POLICY_ENFORCING]  = "violation in enforcing mode:",          [CCS_STAT_POLICY_ENFORCING]  = "violation in enforcing mode:",
2550  };  };
2551    
2552  /* String table for /proc/ccs/meminfo interface. */  /* String table for /proc/ccs/stat interface. */
2553  static const char * const ccs_memory_headers[CCS_MAX_MEMORY_STAT] = {  static const char * const ccs_memory_headers[CCS_MAX_MEMORY_STAT] = {
2554          [CCS_MEMORY_POLICY] = "policy:",          [CCS_MEMORY_POLICY]     = "policy:",
2555          [CCS_MEMORY_AUDIT]  = "audit log:",          [CCS_MEMORY_AUDIT]      = "audit log:",
2556          [CCS_MEMORY_QUERY]  = "query message:",          [CCS_MEMORY_QUERY]      = "query message:",
2557  };  };
2558    
2559  /* Timestamp counter for last updated. */  /* Timestamp counter for last updated. */
# Line 2475  static int ccs_write_stat(struct ccs_io_ Line 2634  static int ccs_write_stat(struct ccs_io_
2634          if (ccs_str_starts(&data, "Memory used by "))          if (ccs_str_starts(&data, "Memory used by "))
2635                  for (i = 0; i < CCS_MAX_MEMORY_STAT; i++)                  for (i = 0; i < CCS_MAX_MEMORY_STAT; i++)
2636                          if (ccs_str_starts(&data, ccs_memory_headers[i]))                          if (ccs_str_starts(&data, ccs_memory_headers[i]))
2637                                  sscanf(data, "%u", &ccs_memory_quota[i]);                                  ccs_memory_quota[i] =
2638          return 0;                                          simple_strtoul(data, NULL, 10);
 }  
   
 /* 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]);  
2639          return 0;          return 0;
2640  }  }
2641    
# Line 2543  int ccs_open_control(const u8 type, stru Line 2652  int ccs_open_control(const u8 type, stru
2652          struct ccs_io_buffer *head = kzalloc(sizeof(*head), CCS_GFP_FLAGS);          struct ccs_io_buffer *head = kzalloc(sizeof(*head), CCS_GFP_FLAGS);
2653          if (!head)          if (!head)
2654                  return -ENOMEM;                  return -ENOMEM;
2655            head->original_ns = ccs_current_namespace();
2656          mutex_init(&head->io_sem);          mutex_init(&head->io_sem);
2657          head->type = type;          head->type = type;
2658          switch (type) {          switch (type) {
# Line 2582  int ccs_open_control(const u8 type, stru Line 2692  int ccs_open_control(const u8 type, stru
2692                  head->read = ccs_read_stat;                  head->read = ccs_read_stat;
2693                  head->readbuf_size = 1024;                  head->readbuf_size = 1024;
2694                  break;                  break;
         case CCS_MEMINFO: /* /proc/ccs/meminfo */  
                 head->write = ccs_write_memory_quota;  
                 head->read = ccs_read_memory_counter;  
                 head->readbuf_size = 512;  
                 break;  
2695          case CCS_PROFILE: /* /proc/ccs/profile */          case CCS_PROFILE: /* /proc/ccs/profile */
2696                  head->write = ccs_write_profile;                  head->write = ccs_write_profile;
2697                  head->read = ccs_read_profile;                  head->read = ccs_read_profile;
# Line 2640  int ccs_open_control(const u8 type, stru Line 2745  int ccs_open_control(const u8 type, stru
2745           */           */
2746          if (type == CCS_QUERY)          if (type == CCS_QUERY)
2747                  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();  
2748          file->private_data = head;          file->private_data = head;
2749            ccs_notify_gc(head, true);
2750          return 0;          return 0;
2751  }  }
2752    
# Line 2668  int ccs_poll_control(struct file *file, Line 2771  int ccs_poll_control(struct file *file,
2771  }  }
2772    
2773  /**  /**
2774     * ccs_move_namespace_cursor - Print namespace delimiter if needed.
2775     *
2776     * @head: Pointer to "struct ccs_io_buffer".
2777     *
2778     * Returns nothing.
2779     */
2780    static inline void ccs_move_namespace_cursor(struct ccs_io_buffer *head)
2781    {
2782            struct list_head *ns;
2783            if (head->type != CCS_EXCEPTIONPOLICY && head->type != CCS_PROFILE)
2784                    return;
2785            /*
2786             * If this is the first read, or reading previous namespace finished
2787             * and has more namespaces to read, update the namespace cursor.
2788             */
2789            ns = head->r.ns;
2790            if (!ns || (head->r.eof && ns->next != &ccs_namespace_list)) {
2791                    /* Clearing is OK because ccs_flush() returned true. */
2792                    memset(&head->r, 0, sizeof(head->r));
2793                    head->r.ns = ns ? ns->next : ccs_namespace_list.next;
2794            }
2795    }
2796    
2797    /**
2798     * ccs_has_more_namespace - Check for unread namespaces.
2799     *
2800     * @head: Pointer to "struct ccs_io_buffer".
2801     *
2802     * Returns true if we have more entries to print, false otherwise.
2803     */
2804    static inline bool ccs_has_more_namespace(struct ccs_io_buffer *head)
2805    {
2806            return (head->type == CCS_EXCEPTIONPOLICY ||
2807                    head->type == CCS_PROFILE) && head->r.eof &&
2808                    head->r.ns->next != &ccs_namespace_list;
2809    }
2810    
2811    /**
2812   * ccs_read_control - read() for /proc/ccs/ interface.   * ccs_read_control - read() for /proc/ccs/ interface.
2813   *   *
2814   * @file:       Pointer to "struct file".   * @file:       Pointer to "struct file".
# Line 2676  int ccs_poll_control(struct file *file, Line 2817  int ccs_poll_control(struct file *file,
2817   *   *
2818   * Returns bytes read on success, negative value otherwise.   * Returns bytes read on success, negative value otherwise.
2819   */   */
2820  int ccs_read_control(struct file *file, char __user *buffer,  ssize_t ccs_read_control(struct file *file, char __user *buffer,
2821                       const int buffer_len)                           const size_t buffer_len)
2822  {  {
2823          int len;          int len;
2824          struct ccs_io_buffer *head = file->private_data;          struct ccs_io_buffer *head = file->private_data;
# Line 2693  int ccs_read_control(struct file *file, Line 2834  int ccs_read_control(struct file *file,
2834          idx = ccs_read_lock();          idx = ccs_read_lock();
2835          if (ccs_flush(head))          if (ccs_flush(head))
2836                  /* Call the policy handler. */                  /* Call the policy handler. */
2837                  head->read(head);                  do {
2838          ccs_flush(head);                          ccs_move_namespace_cursor(head);
2839                            head->read(head);
2840                    } while (ccs_flush(head) && ccs_has_more_namespace(head));
2841          ccs_read_unlock(idx);          ccs_read_unlock(idx);
2842          len = head->read_user_buf - buffer;          len = head->read_user_buf - buffer;
2843          mutex_unlock(&head->io_sem);          mutex_unlock(&head->io_sem);
# Line 2710  int ccs_read_control(struct file *file, Line 2853  int ccs_read_control(struct file *file,
2853   *   *
2854   * Returns @buffer_len on success, negative value otherwise.   * Returns @buffer_len on success, negative value otherwise.
2855   */   */
2856  int ccs_write_control(struct file *file, const char __user *buffer,  ssize_t ccs_write_control(struct file *file, const char __user *buffer,
2857                        const int buffer_len)                            const size_t buffer_len)
2858  {  {
2859          struct ccs_io_buffer *head = file->private_data;          struct ccs_io_buffer *head = file->private_data;
2860          int error = buffer_len;          int error = buffer_len;
2861          int avail_len = buffer_len;          size_t avail_len = buffer_len;
2862          char *cp0 = head->write_buf;          char *cp0 = head->write_buf;
2863          int idx;          int idx;
2864          if (!head->write)          if (!head->write)
# Line 2725  int ccs_write_control(struct file *file, Line 2868  int ccs_write_control(struct file *file,
2868          if (mutex_lock_interruptible(&head->io_sem))          if (mutex_lock_interruptible(&head->io_sem))
2869                  return -EINTR;                  return -EINTR;
2870          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;  
         }  
2871          /* Read a line and dispatch it to the policy handler. */          /* Read a line and dispatch it to the policy handler. */
2872          while (avail_len > 0) {          while (avail_len > 0) {
2873                  char c;                  char c;
# Line 2760  int ccs_write_control(struct file *file, Line 2896  int ccs_write_control(struct file *file,
2896                  cp0[head->w.avail - 1] = '\0';                  cp0[head->w.avail - 1] = '\0';
2897                  head->w.avail = 0;                  head->w.avail = 0;
2898                  ccs_normalize_line(cp0);                  ccs_normalize_line(cp0);
2899                  if (head->write(head))                  if (!strcmp(cp0, "reset")) {
2900                            head->w.ns = head->original_ns;
2901                            head->w.domain = NULL;
2902                            memset(&head->r, 0, sizeof(head->r));
2903                          continue;                          continue;
2904                    }
2905                    /* Don't allow updating policies by non manager programs. */
2906                    switch (head->type) {
2907                    case CCS_PROCESS_STATUS:
2908                            /* This does not write anything. */
2909                            break;
2910                    case CCS_DOMAINPOLICY:
2911                            if (ccs_select_domain(head, cp0))
2912                                    continue;
2913                            /* fall through */
2914                    case CCS_EXCEPTIONPOLICY:
2915                            if (!strcmp(cp0, "select transition_only")) {
2916                                    head->r.print_transition_related_only = true;
2917                                    continue;
2918                            }
2919                            /* fall through */
2920                    default:
2921                            if (!ccs_manager()) {
2922                                    error = -EPERM;
2923                                    goto out;
2924                            }
2925                    }
2926                    /* Delete request? */
2927                    head->w.is_delete = !strncmp(cp0, "delete ", 7);
2928                    if (head->w.is_delete)
2929                            memmove(cp0, cp0 + 7, strlen(cp0 + 7) + 1);
2930                    /* Selecting namespace to update. */
2931                    if (head->type == CCS_EXCEPTIONPOLICY ||
2932                        head->type == CCS_PROFILE) {
2933                            if (*cp0 == '<') {
2934                                    char *cp = strchr(cp0, ' ');
2935                                    if (cp) {
2936                                            *cp++ = '\0';
2937                                            head->w.ns = ccs_assign_namespace(cp0);
2938                                            memmove(cp0, cp, strlen(cp) + 1);
2939                                    } else
2940                                            head->w.ns = NULL;
2941                            } else
2942                                    head->w.ns = head->original_ns;
2943                            /* Don't allow updating if namespace is invalid. */
2944                            if (!head->w.ns) {
2945                                    error = -ENOENT;
2946                                    goto out;
2947                            }
2948                    }
2949                    {
2950                            /* Do the update. */
2951                            const int ret = head->write(head);
2952                            if (ret == -EPERM) {
2953                                    error = -EPERM;
2954                                    break;
2955                            }
2956                            /* Do not update statistics if not updated. */
2957                            if (ret)
2958                                    continue;
2959                    }
2960                    /* Update statistics. */
2961                  switch (head->type) {                  switch (head->type) {
2962                  case CCS_DOMAINPOLICY:                  case CCS_DOMAINPOLICY:
2963                  case CCS_EXCEPTIONPOLICY:                  case CCS_EXCEPTIONPOLICY:
2964                  case CCS_DOMAIN_STATUS:                  case CCS_DOMAIN_STATUS:
2965                  case CCS_MEMINFO:                  case CCS_STAT:
2966                  case CCS_PROFILE:                  case CCS_PROFILE:
2967                  case CCS_MANAGER:                  case CCS_MANAGER:
2968                          ccs_update_stat(CCS_STAT_POLICY_UPDATES);                          ccs_update_stat(CCS_STAT_POLICY_UPDATES);
2969                            break;
2970                    default:
2971                            break;
2972                  }                  }
2973          }          }
2974    out:
2975          ccs_read_unlock(idx);          ccs_read_unlock(idx);
2976          mutex_unlock(&head->io_sem);          mutex_unlock(&head->io_sem);
2977          return error;          return error;
# Line 2787  int ccs_write_control(struct file *file, Line 2987  int ccs_write_control(struct file *file,
2987  int ccs_close_control(struct file *file)  int ccs_close_control(struct file *file)
2988  {  {
2989          struct ccs_io_buffer *head = file->private_data;          struct ccs_io_buffer *head = file->private_data;
2990          const bool is_write = head->write_buf != NULL;          file->private_data = NULL;
         const u8 type = head->type;  
2991          /*          /*
2992           * If the file is /proc/ccs/query, decrement the observer counter.           * If the file is /proc/ccs/query, decrement the observer counter.
2993           */           */
2994          if (type == CCS_QUERY) {          if (head->type == CCS_QUERY &&
2995                  if (atomic_dec_and_test(&ccs_query_observers))              atomic_dec_and_test(&ccs_query_observers))
2996                          wake_up_all(&ccs_answer_wait);                  wake_up_all(&ccs_answer_wait);
2997          } 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();  
2998          return 0;          return 0;
2999  }  }
3000    
# Line 2820  void __init ccs_policy_io_init(void) Line 3007  void __init ccs_policy_io_init(void)
3007  {  {
3008          ccsecurity_ops.check_profile = ccs_check_profile;          ccsecurity_ops.check_profile = ccs_check_profile;
3009  }  }
3010    
3011    #ifdef CONFIG_CCSECURITY_USE_BUILTIN_POLICY
3012    /**
3013     * ccs_load_builtin_policy - Load built-in policy.
3014     *
3015     * Returns nothing.
3016     */
3017    void __init ccs_load_builtin_policy(void)
3018    {
3019            /*
3020             * This include file is manually created and contains built-in policy
3021             * named "ccs_builtin_profile", "ccs_builtin_exception_policy",
3022             * "ccs_builtin_domain_policy", "ccs_builtin_manager",
3023             * "ccs_builtin_stat" in the form of "static char [] __initdata".
3024             */
3025    #include "builtin-policy.h"
3026            struct ccs_io_buffer head;
3027            u8 i;
3028            const int idx = ccs_read_lock();
3029            for (i = 0; i < 5; i++) {
3030                    char *start = "";
3031                    memset(&head, 0, sizeof(head));
3032                    switch (i) {
3033                    case 0:
3034                            start = ccs_builtin_profile;
3035                            head.write = ccs_write_profile;
3036                            break;
3037                    case 1:
3038                            start = ccs_builtin_exception_policy;
3039                            head.write = ccs_write_exception;
3040                            break;
3041                    case 2:
3042                            start = ccs_builtin_domain_policy;
3043                            head.write = ccs_write_domain;
3044                            break;
3045                    case 3:
3046                            start = ccs_builtin_manager;
3047                            head.write = ccs_write_manager;
3048                            break;
3049                    case 4:
3050                            start = ccs_builtin_stat;
3051                            head.write = ccs_write_stat;
3052                            break;
3053                    }
3054                    while (1) {
3055                            char *end = strchr(start, '\n');
3056                            if (!end)
3057                                    break;
3058                            *end = '\0';
3059                            ccs_normalize_line(start);
3060                            head.write_buf = start;
3061                            head.write(&head);
3062                            start = end + 1;
3063                    }
3064            }
3065            ccs_read_unlock(idx);
3066    #ifdef CONFIG_CCSECURITY_ACTIVATE_FROM_THE_BEGINNING
3067            ccs_check_profile();
3068    #endif
3069    }
3070    #endif

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

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