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

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 5055 by kumaneko, Mon May 23 08:25:05 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/05/22
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/05/22\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, NULL);
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_NAMESPACE]     = "move_namespace ",
1963            [CCS_TRANSITION_CONTROL_NO_NAMESPACE]  = "no_move_namespace ",
1964            [CCS_TRANSITION_CONTROL_INITIALIZE]    = "initialize_domain ",
1965          [CCS_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ",          [CCS_TRANSITION_CONTROL_NO_INITIALIZE] = "no_initialize_domain ",
1966          [CCS_TRANSITION_CONTROL_INITIALIZE]    = "initialize_domain ",          [CCS_TRANSITION_CONTROL_INITIALIZE]    = "initialize_domain ",
1967          [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 1984  static const char * const ccs_group_name
1984   */   */
1985  static int ccs_write_exception(struct ccs_io_buffer *head)  static int ccs_write_exception(struct ccs_io_buffer *head)
1986  {  {
1987          char *data = head->write_buf;          const bool is_delete = head->w.is_delete;
1988          const bool is_delete = ccs_str_starts(&data, "delete ");          struct ccs_acl_param param = {
1989          u8 i;                  .ns = head->w.ns,
1990          static const struct {                  .is_delete = is_delete,
1991                  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 },  
1992          };          };
1993          for (i = 0; i < 2; i++)          u8 i;
1994                  if (ccs_str_starts(&data, ccs_callback[i].keyword))          if (ccs_str_starts(&param.data, "aggregator "))
1995                          return ccs_callback[i].write(data, is_delete);                  return ccs_write_aggregator(&param);
1996            if (ccs_str_starts(&param.data, "deny_autobind "))
1997                    return ccs_write_reserved_port(&param);
1998          for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)          for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++)
1999                  if (ccs_str_starts(&data, ccs_transition_type[i]))                  if (ccs_str_starts(&param.data, ccs_transition_type[i]))
2000                          return ccs_write_transition_control(data, is_delete,                          return ccs_write_transition_control(&param, i);
                                                             i);  
2001          for (i = 0; i < CCS_MAX_GROUP; i++)          for (i = 0; i < CCS_MAX_GROUP; i++)
2002                  if (ccs_str_starts(&data, ccs_group_name[i]))                  if (ccs_str_starts(&param.data, ccs_group_name[i]))
2003                          return ccs_write_group(data, is_delete, i);                          return ccs_write_group(&param, i);
2004          if (ccs_str_starts(&data, "acl_group ")) {          if (ccs_str_starts(&param.data, "acl_group ")) {
2005                  unsigned int group;                  unsigned int group;
2006                  if (sscanf(data, "%u", &group) == 1 &&                  char *data;
2007                      group < CCS_MAX_ACL_GROUPS) {                  group = simple_strtoul(param.data, &data, 10);
2008                          data = strchr(data, ' ');                  if (group < CCS_MAX_ACL_GROUPS && *data++ == ' ')
2009                          if (data)                          return ccs_write_domain2(head->w.ns,
2010                                  return ccs_write_domain2(data + 1,                                                   head->w.ns->acl_group[group],
2011                                                           &ccs_acl_group[group],                                                   data, is_delete);
                                                          is_delete);  
                 }  
2012          }          }
2013          return -EINVAL;          return -EINVAL;
2014  }  }
# Line 1875  static int ccs_write_exception(struct cc Line 2025  static int ccs_write_exception(struct cc
2025   */   */
2026  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)
2027  {  {
2028          list_for_each_cookie(head->r.group, &ccs_group_list[idx]) {          struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
2029                                                           namespace_list);
2030            struct list_head *list = &ns->group_list[idx];
2031            list_for_each_cookie(head->r.group, list) {
2032                  struct ccs_group *group =                  struct ccs_group *group =
2033                          list_entry(head->r.group, typeof(*group), head.list);                          list_entry(head->r.group, typeof(*group), head.list);
2034                  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 2038  static bool ccs_read_group(struct ccs_io
2038                                  continue;                                  continue;
2039                          if (!ccs_flush(head))                          if (!ccs_flush(head))
2040                                  return false;                                  return false;
2041                            ccs_print_namespace(head);
2042                          ccs_set_string(head, ccs_group_name[idx]);                          ccs_set_string(head, ccs_group_name[idx]);
2043                          ccs_set_string(head, group->group_name->name);                          ccs_set_string(head, group->group_name->name);
2044                          if (idx == CCS_PATH_GROUP) {                          if (idx == CCS_PATH_GROUP) {
# Line 1901  static bool ccs_read_group(struct ccs_io Line 2055  static bool ccs_read_group(struct ccs_io
2055                                  struct ccs_address_group *member =                                  struct ccs_address_group *member =
2056                                          container_of(ptr, typeof(*member),                                          container_of(ptr, typeof(*member),
2057                                                       head);                                                       head);
2058                                  if (member->is_ipv6)                                  ccs_print_ip(buffer, sizeof(buffer),
2059                                          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);  
2060                                  ccs_io_printf(head, " %s", buffer);                                  ccs_io_printf(head, " %s", buffer);
2061                          }                          }
2062                          ccs_set_lf(head);                          ccs_set_lf(head);
# Line 1931  static bool ccs_read_group(struct ccs_io Line 2079  static bool ccs_read_group(struct ccs_io
2079   */   */
2080  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)
2081  {  {
2082          list_for_each_cookie(head->r.acl, &ccs_policy_list[idx]) {          struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
2083                                                           namespace_list);
2084            struct list_head *list = &ns->policy_list[idx];
2085            list_for_each_cookie(head->r.acl, list) {
2086                  struct ccs_acl_head *acl =                  struct ccs_acl_head *acl =
2087                          container_of(head->r.acl, typeof(*acl), list);                          container_of(head->r.acl, typeof(*acl), list);
2088                  if (acl->is_deleted)                  if (acl->is_deleted)
2089                          continue;                          continue;
2090                    if (head->r.print_transition_related_only &&
2091                        idx != CCS_ID_TRANSITION_CONTROL)
2092                            continue;
2093                  if (!ccs_flush(head))                  if (!ccs_flush(head))
2094                          return false;                          return false;
2095                  switch (idx) {                  switch (idx) {
# Line 1943  static bool ccs_read_policy(struct ccs_i Line 2097  static bool ccs_read_policy(struct ccs_i
2097                          {                          {
2098                                  struct ccs_transition_control *ptr =                                  struct ccs_transition_control *ptr =
2099                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
2100                                    ccs_print_namespace(head);
2101                                  ccs_set_string(head,                                  ccs_set_string(head,
2102                                                 ccs_transition_type[ptr->type]);                                                 ccs_transition_type[ptr->type]);
2103                                  ccs_set_string(head, ptr->program ?                                  ccs_set_string(head, ptr->program ?
# Line 1956  static bool ccs_read_policy(struct ccs_i Line 2111  static bool ccs_read_policy(struct ccs_i
2111                          {                          {
2112                                  struct ccs_aggregator *ptr =                                  struct ccs_aggregator *ptr =
2113                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
2114                                    ccs_print_namespace(head);
2115                                  ccs_set_string(head, "aggregator ");                                  ccs_set_string(head, "aggregator ");
2116                                  ccs_set_string(head, ptr->original_name->name);                                  ccs_set_string(head, ptr->original_name->name);
2117                                  ccs_set_space(head);                                  ccs_set_space(head);
# Line 1967  static bool ccs_read_policy(struct ccs_i Line 2123  static bool ccs_read_policy(struct ccs_i
2123                          {                          {
2124                                  struct ccs_reserved *ptr =                                  struct ccs_reserved *ptr =
2125                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
2126                                  const u16 min_port = ptr->min_port;                                  ccs_print_namespace(head);
                                 const u16 max_port = ptr->max_port;  
2127                                  ccs_set_string(head, "deny_autobind ");                                  ccs_set_string(head, "deny_autobind ");
2128                                  ccs_io_printf(head, "%u", min_port);                                  ccs_print_number_union_nospace(head,
2129                                  if (min_port != max_port)                                                                 &ptr->port);
                                         ccs_io_printf(head, "-%u", max_port);  
2130                          }                          }
2131                          break;                          break;
2132                  default:                  default:
# Line 1995  static bool ccs_read_policy(struct ccs_i Line 2149  static bool ccs_read_policy(struct ccs_i
2149   */   */
2150  static void ccs_read_exception(struct ccs_io_buffer *head)  static void ccs_read_exception(struct ccs_io_buffer *head)
2151  {  {
2152            struct ccs_policy_namespace *ns = container_of(head->r.ns, typeof(*ns),
2153                                                           namespace_list);
2154          if (head->r.eof)          if (head->r.eof)
2155                  return;                  return;
2156          while (head->r.step < CCS_MAX_POLICY &&          while (head->r.step < CCS_MAX_POLICY &&
# Line 2009  static void ccs_read_exception(struct cc Line 2165  static void ccs_read_exception(struct cc
2165                  return;                  return;
2166          while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP          while (head->r.step < CCS_MAX_POLICY + CCS_MAX_GROUP
2167                 + CCS_MAX_ACL_GROUPS * 2) {                 + CCS_MAX_ACL_GROUPS * 2) {
2168                  head->r.group_index = (head->r.step - CCS_MAX_POLICY                  head->r.acl_group_index = (head->r.step - CCS_MAX_POLICY
2169                                         - CCS_MAX_GROUP) / 2;                                             - CCS_MAX_GROUP) / 2;
2170                  if (!ccs_read_domain2(head,                  if (!ccs_read_domain2(head, &ns->acl_group
2171                                        &ccs_acl_group[head->r.group_index],                                        [head->r.acl_group_index]
2172                                        head->r.step & 1))                                        [head->r.step & 1]))
2173                          return;                          return;
2174                  head->r.step++;                  head->r.step++;
2175          }          }
# Line 2029  static DECLARE_WAIT_QUEUE_HEAD(ccs_answe Line 2185  static DECLARE_WAIT_QUEUE_HEAD(ccs_answe
2185  struct ccs_query {  struct ccs_query {
2186          struct list_head list;          struct list_head list;
2187          char *query;          char *query;
2188          int query_len;          size_t query_len;
2189          unsigned int serial;          unsigned int serial;
2190          int timer;          u8 timer;
2191          int answer;          u8 answer;
2192          u8 retry;          u8 retry;
2193  };  };
2194    
# Line 2116  static void ccs_add_entry(char *header) Line 2272  static void ccs_add_entry(char *header)
2272          if (symlink)          if (symlink)
2273                  ccs_addprintf(buffer, len, "%s", symlink);                  ccs_addprintf(buffer, len, "%s", symlink);
2274          ccs_normalize_line(buffer);          ccs_normalize_line(buffer);
2275          if (!ccs_write_domain2(buffer, ccs_current_domain(), false))          {
2276                  ccs_update_stat(CCS_STAT_POLICY_UPDATES);                  struct ccs_domain_info *domain = ccs_current_domain();
2277                    if (!ccs_write_domain2(domain->ns, domain->acl_info_list,
2278                                           buffer, false))
2279                            ccs_update_stat(CCS_STAT_POLICY_UPDATES);
2280            }
2281          kfree(buffer);          kfree(buffer);
2282  }  }
2283    
# Line 2170  int ccs_supervisor(struct ccs_request_in Line 2330  int ccs_supervisor(struct ccs_request_in
2330                  goto out;                  goto out;
2331          case CCS_CONFIG_LEARNING:          case CCS_CONFIG_LEARNING:
2332                  error = 0;                  error = 0;
2333                  /* Check mac_learning_entry parameter. */                  /* Check max_learning_entry parameter. */
2334                  if (ccs_domain_quota_ok(r))                  if (ccs_domain_quota_ok(r))
2335                          break;                          break;
2336                  /* fall through */                  /* fall through */
# Line 2280  static int ccs_poll_query(struct file *f Line 2440  static int ccs_poll_query(struct file *f
2440  static void ccs_read_query(struct ccs_io_buffer *head)  static void ccs_read_query(struct ccs_io_buffer *head)
2441  {  {
2442          struct list_head *tmp;          struct list_head *tmp;
2443          int pos = 0;          unsigned int pos = 0;
2444          int len = 0;          size_t len = 0;
2445          char *buf;          char *buf;
2446          if (head->r.w_pos)          if (head->r.w_pos)
2447                  return;                  return;
# Line 2318  static void ccs_read_query(struct ccs_io Line 2478  static void ccs_read_query(struct ccs_io
2478                   * can change, but I don't care.                   * can change, but I don't care.
2479                   */                   */
2480                  if (len == ptr->query_len)                  if (len == ptr->query_len)
2481                          snprintf(buf, len + 32, "Q%u-%hu\n%s", ptr->serial,                          snprintf(buf, len + 31, "Q%u-%hu\n%s", ptr->serial,
2482                                   ptr->retry, ptr->query);                                   ptr->retry, ptr->query);
2483                  break;                  break;
2484          }          }
# Line 2359  static int ccs_write_answer(struct ccs_i Line 2519  static int ccs_write_answer(struct ccs_i
2519                  if (ptr->serial != serial)                  if (ptr->serial != serial)
2520                          continue;                          continue;
2521                  if (!ptr->answer)                  if (!ptr->answer)
2522                          ptr->answer = answer;                          ptr->answer = (u8) answer;
2523                  break;                  break;
2524          }          }
2525          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
# Line 2378  static void ccs_read_version(struct ccs_ Line 2538  static void ccs_read_version(struct ccs_
2538  {  {
2539          if (head->r.eof)          if (head->r.eof)
2540                  return;                  return;
2541          ccs_set_string(head, "1.8.0");          ccs_set_string(head, "1.8.2-pre");
2542          head->r.eof = true;          head->r.eof = true;
2543  }  }
2544    
2545  /* String table for /proc/ccs/meminfo interface. */  /* String table for /proc/ccs/stat interface. */
2546  static const char * const ccs_policy_headers[CCS_MAX_POLICY_STAT] = {  static const char * const ccs_policy_headers[CCS_MAX_POLICY_STAT] = {
2547          [CCS_STAT_POLICY_UPDATES]    = "update:",          [CCS_STAT_POLICY_UPDATES]    = "update:",
2548          [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 2550  static const char * const ccs_policy_hea
2550          [CCS_STAT_POLICY_ENFORCING]  = "violation in enforcing mode:",          [CCS_STAT_POLICY_ENFORCING]  = "violation in enforcing mode:",
2551  };  };
2552    
2553  /* String table for /proc/ccs/meminfo interface. */  /* String table for /proc/ccs/stat interface. */
2554  static const char * const ccs_memory_headers[CCS_MAX_MEMORY_STAT] = {  static const char * const ccs_memory_headers[CCS_MAX_MEMORY_STAT] = {
2555          [CCS_MEMORY_POLICY] = "policy:",          [CCS_MEMORY_POLICY]     = "policy:",
2556          [CCS_MEMORY_AUDIT]  = "audit log:",          [CCS_MEMORY_AUDIT]      = "audit log:",
2557          [CCS_MEMORY_QUERY]  = "query message:",          [CCS_MEMORY_QUERY]      = "query message:",
2558  };  };
2559    
2560  /* Timestamp counter for last updated. */  /* Timestamp counter for last updated. */
# Line 2475  static int ccs_write_stat(struct ccs_io_ Line 2635  static int ccs_write_stat(struct ccs_io_
2635          if (ccs_str_starts(&data, "Memory used by "))          if (ccs_str_starts(&data, "Memory used by "))
2636                  for (i = 0; i < CCS_MAX_MEMORY_STAT; i++)                  for (i = 0; i < CCS_MAX_MEMORY_STAT; i++)
2637                          if (ccs_str_starts(&data, ccs_memory_headers[i]))                          if (ccs_str_starts(&data, ccs_memory_headers[i]))
2638                                  sscanf(data, "%u", &ccs_memory_quota[i]);                                  ccs_memory_quota[i] =
2639          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]);  
2640          return 0;          return 0;
2641  }  }
2642    
# Line 2543  int ccs_open_control(const u8 type, stru Line 2653  int ccs_open_control(const u8 type, stru
2653          struct ccs_io_buffer *head = kzalloc(sizeof(*head), CCS_GFP_FLAGS);          struct ccs_io_buffer *head = kzalloc(sizeof(*head), CCS_GFP_FLAGS);
2654          if (!head)          if (!head)
2655                  return -ENOMEM;                  return -ENOMEM;
2656            head->original_ns = ccs_current_namespace();
2657          mutex_init(&head->io_sem);          mutex_init(&head->io_sem);
2658          head->type = type;          head->type = type;
2659          switch (type) {          switch (type) {
# Line 2582  int ccs_open_control(const u8 type, stru Line 2693  int ccs_open_control(const u8 type, stru
2693                  head->read = ccs_read_stat;                  head->read = ccs_read_stat;
2694                  head->readbuf_size = 1024;                  head->readbuf_size = 1024;
2695                  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;  
2696          case CCS_PROFILE: /* /proc/ccs/profile */          case CCS_PROFILE: /* /proc/ccs/profile */
2697                  head->write = ccs_write_profile;                  head->write = ccs_write_profile;
2698                  head->read = ccs_read_profile;                  head->read = ccs_read_profile;
# Line 2640  int ccs_open_control(const u8 type, stru Line 2746  int ccs_open_control(const u8 type, stru
2746           */           */
2747          if (type == CCS_QUERY)          if (type == CCS_QUERY)
2748                  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();  
2749          file->private_data = head;          file->private_data = head;
2750            ccs_notify_gc(head, true);
2751          return 0;          return 0;
2752  }  }
2753    
# Line 2668  int ccs_poll_control(struct file *file, Line 2772  int ccs_poll_control(struct file *file,
2772  }  }
2773    
2774  /**  /**
2775     * ccs_move_namespace_cursor - Print namespace delimiter if needed.
2776     *
2777     * @head: Pointer to "struct ccs_io_buffer".
2778     *
2779     * Returns nothing.
2780     */
2781    static inline void ccs_move_namespace_cursor(struct ccs_io_buffer *head)
2782    {
2783            struct list_head *ns;
2784            if (head->type != CCS_EXCEPTIONPOLICY && head->type != CCS_PROFILE)
2785                    return;
2786            /*
2787             * If this is the first read, or reading previous namespace finished
2788             * and has more namespaces to read, update the namespace cursor.
2789             */
2790            ns = head->r.ns;
2791            if (!ns || (head->r.eof && ns->next != &ccs_namespace_list)) {
2792                    /* Clearing is OK because ccs_flush() returned true. */
2793                    memset(&head->r, 0, sizeof(head->r));
2794                    head->r.ns = ns ? ns->next : ccs_namespace_list.next;
2795            }
2796    }
2797    
2798    /**
2799     * ccs_has_more_namespace - Check for unread namespaces.
2800     *
2801     * @head: Pointer to "struct ccs_io_buffer".
2802     *
2803     * Returns true if we have more entries to print, false otherwise.
2804     */
2805    static inline bool ccs_has_more_namespace(struct ccs_io_buffer *head)
2806    {
2807            return (head->type == CCS_EXCEPTIONPOLICY ||
2808                    head->type == CCS_PROFILE) && head->r.eof &&
2809                    head->r.ns->next != &ccs_namespace_list;
2810    }
2811    
2812    /**
2813   * ccs_read_control - read() for /proc/ccs/ interface.   * ccs_read_control - read() for /proc/ccs/ interface.
2814   *   *
2815   * @file:       Pointer to "struct file".   * @file:       Pointer to "struct file".
# Line 2676  int ccs_poll_control(struct file *file, Line 2818  int ccs_poll_control(struct file *file,
2818   *   *
2819   * Returns bytes read on success, negative value otherwise.   * Returns bytes read on success, negative value otherwise.
2820   */   */
2821  int ccs_read_control(struct file *file, char __user *buffer,  ssize_t ccs_read_control(struct file *file, char __user *buffer,
2822                       const int buffer_len)                           const size_t buffer_len)
2823  {  {
2824          int len;          int len;
2825          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 2835  int ccs_read_control(struct file *file,
2835          idx = ccs_read_lock();          idx = ccs_read_lock();
2836          if (ccs_flush(head))          if (ccs_flush(head))
2837                  /* Call the policy handler. */                  /* Call the policy handler. */
2838                  head->read(head);                  do {
2839          ccs_flush(head);                          ccs_move_namespace_cursor(head);
2840                            head->read(head);
2841                    } while (ccs_flush(head) && ccs_has_more_namespace(head));
2842          ccs_read_unlock(idx);          ccs_read_unlock(idx);
2843          len = head->read_user_buf - buffer;          len = head->read_user_buf - buffer;
2844          mutex_unlock(&head->io_sem);          mutex_unlock(&head->io_sem);
# Line 2710  int ccs_read_control(struct file *file, Line 2854  int ccs_read_control(struct file *file,
2854   *   *
2855   * Returns @buffer_len on success, negative value otherwise.   * Returns @buffer_len on success, negative value otherwise.
2856   */   */
2857  int ccs_write_control(struct file *file, const char __user *buffer,  ssize_t ccs_write_control(struct file *file, const char __user *buffer,
2858                        const int buffer_len)                            const size_t buffer_len)
2859  {  {
2860          struct ccs_io_buffer *head = file->private_data;          struct ccs_io_buffer *head = file->private_data;
2861          int error = buffer_len;          int error = buffer_len;
2862          int avail_len = buffer_len;          size_t avail_len = buffer_len;
2863          char *cp0 = head->write_buf;          char *cp0 = head->write_buf;
2864          int idx;          int idx;
2865          if (!head->write)          if (!head->write)
# Line 2725  int ccs_write_control(struct file *file, Line 2869  int ccs_write_control(struct file *file,
2869          if (mutex_lock_interruptible(&head->io_sem))          if (mutex_lock_interruptible(&head->io_sem))
2870                  return -EINTR;                  return -EINTR;
2871          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;  
         }  
2872          /* Read a line and dispatch it to the policy handler. */          /* Read a line and dispatch it to the policy handler. */
2873          while (avail_len > 0) {          while (avail_len > 0) {
2874                  char c;                  char c;
# Line 2760  int ccs_write_control(struct file *file, Line 2897  int ccs_write_control(struct file *file,
2897                  cp0[head->w.avail - 1] = '\0';                  cp0[head->w.avail - 1] = '\0';
2898                  head->w.avail = 0;                  head->w.avail = 0;
2899                  ccs_normalize_line(cp0);                  ccs_normalize_line(cp0);
2900                  if (head->write(head))                  if (!strcmp(cp0, "reset")) {
2901                            head->w.ns = head->original_ns;
2902                            head->w.domain = NULL;
2903                            memset(&head->r, 0, sizeof(head->r));
2904                          continue;                          continue;
2905                    }
2906                    /* Don't allow updating policies by non manager programs. */
2907                    switch (head->type) {
2908                    case CCS_PROCESS_STATUS:
2909                            /* This does not write anything. */
2910                            break;
2911                    case CCS_DOMAINPOLICY:
2912                            if (ccs_select_domain(head, cp0))
2913                                    continue;
2914                            /* fall through */
2915                    case CCS_EXCEPTIONPOLICY:
2916                            if (!strcmp(cp0, "select transition_only")) {
2917                                    head->r.print_transition_related_only = true;
2918                                    continue;
2919                            }
2920                            /* fall through */
2921                    default:
2922                            if (!ccs_manager()) {
2923                                    error = -EPERM;
2924                                    goto out;
2925                            }
2926                    }
2927                    /* Delete request? */
2928                    head->w.is_delete = !strncmp(cp0, "delete ", 7);
2929                    if (head->w.is_delete)
2930                            memmove(cp0, cp0 + 7, strlen(cp0 + 7) + 1);
2931                    /* Selecting namespace to update. */
2932                    if (head->type == CCS_EXCEPTIONPOLICY ||
2933                        head->type == CCS_PROFILE) {
2934                            if (*cp0 == '<') {
2935                                    char *cp = strchr(cp0, ' ');
2936                                    if (cp) {
2937                                            *cp++ = '\0';
2938                                            head->w.ns = ccs_assign_namespace(cp0);
2939                                            memmove(cp0, cp, strlen(cp) + 1);
2940                                    } else
2941                                            head->w.ns = NULL;
2942                            } else
2943                                    head->w.ns = head->original_ns;
2944                            /* Don't allow updating if namespace is invalid. */
2945                            if (!head->w.ns) {
2946                                    error = -ENOENT;
2947                                    goto out;
2948                            }
2949                    }
2950                    {
2951                            /* Do the update. */
2952                            const int ret = head->write(head);
2953                            if (ret == -EPERM) {
2954                                    error = -EPERM;
2955                                    break;
2956                            }
2957                            /* Do not update statistics if not updated. */
2958                            if (ret)
2959                                    continue;
2960                    }
2961                    /* Update statistics. */
2962                  switch (head->type) {                  switch (head->type) {
2963                  case CCS_DOMAINPOLICY:                  case CCS_DOMAINPOLICY:
2964                  case CCS_EXCEPTIONPOLICY:                  case CCS_EXCEPTIONPOLICY:
2965                  case CCS_DOMAIN_STATUS:                  case CCS_DOMAIN_STATUS:
2966                  case CCS_MEMINFO:                  case CCS_STAT:
2967                  case CCS_PROFILE:                  case CCS_PROFILE:
2968                  case CCS_MANAGER:                  case CCS_MANAGER:
2969                          ccs_update_stat(CCS_STAT_POLICY_UPDATES);                          ccs_update_stat(CCS_STAT_POLICY_UPDATES);
2970                            break;
2971                    default:
2972                            break;
2973                  }                  }
2974          }          }
2975    out:
2976          ccs_read_unlock(idx);          ccs_read_unlock(idx);
2977          mutex_unlock(&head->io_sem);          mutex_unlock(&head->io_sem);
2978          return error;          return error;
# Line 2787  int ccs_write_control(struct file *file, Line 2988  int ccs_write_control(struct file *file,
2988  int ccs_close_control(struct file *file)  int ccs_close_control(struct file *file)
2989  {  {
2990          struct ccs_io_buffer *head = file->private_data;          struct ccs_io_buffer *head = file->private_data;
2991          const bool is_write = head->write_buf != NULL;          file->private_data = NULL;
         const u8 type = head->type;  
2992          /*          /*
2993           * If the file is /proc/ccs/query, decrement the observer counter.           * If the file is /proc/ccs/query, decrement the observer counter.
2994           */           */
2995          if (type == CCS_QUERY) {          if (head->type == CCS_QUERY &&
2996                  if (atomic_dec_and_test(&ccs_query_observers))              atomic_dec_and_test(&ccs_query_observers))
2997                          wake_up_all(&ccs_answer_wait);                  wake_up_all(&ccs_answer_wait);
2998          } 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();  
2999          return 0;          return 0;
3000  }  }
3001    
# Line 2820  void __init ccs_policy_io_init(void) Line 3008  void __init ccs_policy_io_init(void)
3008  {  {
3009          ccsecurity_ops.check_profile = ccs_check_profile;          ccsecurity_ops.check_profile = ccs_check_profile;
3010  }  }
3011    
3012    #ifdef CONFIG_CCSECURITY_USE_BUILTIN_POLICY
3013    /**
3014     * ccs_load_builtin_policy - Load built-in policy.
3015     *
3016     * Returns nothing.
3017     */
3018    void __init ccs_load_builtin_policy(void)
3019    {
3020            /*
3021             * This include file is manually created and contains built-in policy
3022             * named "ccs_builtin_profile", "ccs_builtin_exception_policy",
3023             * "ccs_builtin_domain_policy", "ccs_builtin_manager",
3024             * "ccs_builtin_stat" in the form of "static char [] __initdata".
3025             */
3026    #include "builtin-policy.h"
3027            struct ccs_io_buffer head;
3028            u8 i;
3029            const int idx = ccs_read_lock();
3030            for (i = 0; i < 5; i++) {
3031                    char *start = "";
3032                    memset(&head, 0, sizeof(head));
3033                    switch (i) {
3034                    case 0:
3035                            start = ccs_builtin_profile;
3036                            head.write = ccs_write_profile;
3037                            break;
3038                    case 1:
3039                            start = ccs_builtin_exception_policy;
3040                            head.write = ccs_write_exception;
3041                            break;
3042                    case 2:
3043                            start = ccs_builtin_domain_policy;
3044                            head.write = ccs_write_domain;
3045                            break;
3046                    case 3:
3047                            start = ccs_builtin_manager;
3048                            head.write = ccs_write_manager;
3049                            break;
3050                    case 4:
3051                            start = ccs_builtin_stat;
3052                            head.write = ccs_write_stat;
3053                            break;
3054                    }
3055                    while (1) {
3056                            char *end = strchr(start, '\n');
3057                            if (!end)
3058                                    break;
3059                            *end = '\0';
3060                            ccs_normalize_line(start);
3061                            head.write_buf = start;
3062                            head.write(&head);
3063                            start = end + 1;
3064                    }
3065            }
3066            ccs_read_unlock(idx);
3067    #ifdef CONFIG_CCSECURITY_ACTIVATE_FROM_THE_BEGINNING
3068            ccs_check_profile();
3069    #endif
3070    }
3071    #endif

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

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