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

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 3693 by kumaneko, Sun May 23 08:05:44 2010 UTC revision 3752 by kumaneko, Fri Jun 11 05:46:17 2010 UTC
# Line 3  Line 3 
3   *   *
4   * Copyright (C) 2005-2010  NTT DATA CORPORATION   * Copyright (C) 2005-2010  NTT DATA CORPORATION
5   *   *
6   * Version: 1.7.2   2010/04/01   * Version: 1.7.2+   2010/06/04
7   *   *
8   * This file is applicable to both 2.4.30 and 2.6.11 and later.   * This file is applicable to both 2.4.30 and 2.6.11 and later.
9   * See README.ccs for ChangeLog.   * See README.ccs for ChangeLog.
# Line 40  static unsigned int ccs_profile_version; Line 40  static unsigned int ccs_profile_version;
40  static struct ccs_profile *ccs_profile_ptr[CCS_MAX_PROFILES];  static struct ccs_profile *ccs_profile_ptr[CCS_MAX_PROFILES];
41    
42  /* String table for functionality that takes 4 modes. */  /* String table for functionality that takes 4 modes. */
43  static const char *ccs_mode_4[4] = {  static const char *ccs_mode[CCS_CONFIG_MAX_MODE] = {
44          "disabled", "learning", "permissive", "enforcing"          [CCS_CONFIG_DISABLED] = "disabled",
45            [CCS_CONFIG_LEARNING] = "learning",
46            [CCS_CONFIG_PERMISSIVE] = "permissive",
47            [CCS_CONFIG_ENFORCING] = "enforcing"
48  };  };
49    
50  /* String table for /proc/ccs/profile */  /* String table for /proc/ccs/profile */
# Line 246  bool ccs_io_printf(struct ccs_io_buffer Line 249  bool ccs_io_printf(struct ccs_io_buffer
249  }  }
250    
251  /**  /**
252   * ccs_find_or_assign_new_profile - Create a new profile.   * ccs_assign_profile - Create a new profile.
253   *   *
254   * @profile: Profile number to create.   * @profile: Profile number to create.
255   *   *
256   * Returns pointer to "struct ccs_profile" on success, NULL otherwise.   * Returns pointer to "struct ccs_profile" on success, NULL otherwise.
257   */   */
258  static struct ccs_profile *ccs_find_or_assign_new_profile(const unsigned int  static struct ccs_profile *ccs_assign_profile(const unsigned int profile)
                                                           profile)  
259  {  {
260          struct ccs_profile *ptr;          struct ccs_profile *ptr;
261          struct ccs_profile *entry;          struct ccs_profile *entry;
# Line 305  static void ccs_check_profile(void) Line 307  static void ccs_check_profile(void)
307          if (ccs_profile_version != 20090903)          if (ccs_profile_version != 20090903)
308                  panic("Profile version %u is not supported.\n",                  panic("Profile version %u is not supported.\n",
309                        ccs_profile_version);                        ccs_profile_version);
310          printk(KERN_INFO "CCSecurity: 1.7.2   2010/04/01\n");          printk(KERN_INFO "CCSecurity: 1.7.2+   2010/06/04\n");
311          printk(KERN_INFO "Mandatory Access Control activated.\n");          printk(KERN_INFO "Mandatory Access Control activated.\n");
312  }  }
313    
# Line 325  struct ccs_profile *ccs_profile(const u8 Line 327  struct ccs_profile *ccs_profile(const u8
327          return ptr;          return ptr;
328  }  }
329    
330  /**  static s8 ccs_find_yesno(const char *string, const char *find)
  * ccs_write_profile - Write profile table.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  *  
  * Returns 0 on success, negative value otherwise.  
  */  
 static int ccs_write_profile(struct ccs_io_buffer *head)  
331  {  {
332          char *data = head->write_buf;          const char *cp = strstr(string, find);
333          unsigned int i;          if (cp) {
334          int value;                  cp += strlen(find);
335          int mode;                  if (strncmp(cp, "=yes", 4))
336          u8 config;                          return 1;
337          bool use_default = false;                  else if (strncmp(cp, "=no", 3))
338          char *cp;                          return 0;
         struct ccs_profile *profile;  
         if (sscanf(data, "PROFILE_VERSION=%u", &ccs_profile_version) == 1)  
                 return 0;  
         i = simple_strtoul(data, &cp, 10);  
         if (data == cp) {  
                 profile = &ccs_default_profile;  
         } else {  
                 if (*cp != '-')  
                         return -EINVAL;  
                 data = cp + 1;  
                 profile = ccs_find_or_assign_new_profile(i);  
                 if (!profile)  
                         return -EINVAL;  
339          }          }
340          cp = strchr(data, '=');          return -1;
341          if (!cp)  }
342                  return -EINVAL;  
343          *cp++ = '\0';  static void ccs_set_bool(bool *b, const char *string, const char *find)
344          if (profile != &ccs_default_profile)  {
345                  use_default = strstr(cp, "use_default") != NULL;          switch (ccs_find_yesno(string, find)) {
346          if (strstr(cp, "verbose=yes"))          case 1:
347                  value = 1;                  *b = true;
348          else if (strstr(cp, "verbose=no"))                  break;
349                  value = 0;          case 0:
350          else                  *b = false;
351                  value = -1;                  break;
352          if (!strcmp(data, CCS_KEYWORD_PREFERENCE_AUDIT)) {          }
353  #ifdef CONFIG_CCSECURITY_AUDIT  }
354                  char *cp2;  
355  #endif  static void ccs_set_uint(unsigned int *i, const char *string, const char *find)
356    {
357            const char *cp = strstr(string, find);
358            if (cp)
359                    sscanf(cp + strlen(find), "=%u", i);
360    }
361    
362    static void ccs_set_pref(const char *cp, const char *data,
363                             struct ccs_profile *profile, const bool use_default)
364    {
365            struct ccs_preference **pref;
366            bool *verbose;
367            if (!strcmp(data, "audit")) {
368                  if (use_default) {                  if (use_default) {
369                          profile->audit = &ccs_default_profile.preference;                          pref = &profile->audit;
370                          return 0;                          goto set_default;
371                  }                  }
372                  profile->audit = &profile->preference;                  profile->audit = &profile->preference;
373  #ifdef CONFIG_CCSECURITY_AUDIT  #ifdef CONFIG_CCSECURITY_AUDIT
374                  cp2 = strstr(cp, "max_grant_log=");                  ccs_set_uint(&profile->preference.audit_max_grant_log, cp,
375                  if (cp2)                               "max_grant_log");
376                          sscanf(cp2 + 14, "%u",                  ccs_set_uint(&profile->preference.audit_max_reject_log, cp,
377                                 &profile->preference.audit_max_grant_log);                               "max_reject_log");
                 cp2 = strstr(cp, "max_reject_log=");  
                 if (cp2)  
                         sscanf(cp2 + 15, "%u",  
                                &profile->preference.audit_max_reject_log);  
378  #endif  #endif
379                  if (strstr(cp, "task_info=yes"))                  ccs_set_bool(&profile->preference.audit_task_info, cp,
380                          profile->preference.audit_task_info = true;                               "task_info");
381                  else if (strstr(cp, "task_info=no"))                  ccs_set_bool(&profile->preference.audit_path_info, cp,
382                          profile->preference.audit_task_info = false;                               "path_info");
383                  if (strstr(cp, "path_info=yes"))                  return;
                         profile->preference.audit_path_info = true;  
                 else if (strstr(cp, "path_info=no"))  
                         profile->preference.audit_path_info = false;  
                 return 0;  
384          }          }
385          if (!strcmp(data, CCS_KEYWORD_PREFERENCE_ENFORCING)) {          if (!strcmp(data, "enforcing")) {
                 char *cp2;  
386                  if (use_default) {                  if (use_default) {
387                          profile->enforcing = &ccs_default_profile.preference;                          pref = &profile->enforcing;
388                          return 0;                          goto set_default;
389                  }                  }
390                  profile->enforcing = &profile->preference;                  profile->enforcing = &profile->preference;
391                  if (value >= 0)                  ccs_set_uint(&profile->preference.enforcing_penalty, cp,
392                          profile->preference.enforcing_verbose = value;                               "penalty");
393                  cp2 = strstr(cp, "penalty=");                  verbose = &profile->preference.enforcing_verbose;
394                  if (cp2)                  goto set_verbose;
                         sscanf(cp2 + 8, "%u",  
                                &profile->preference.enforcing_penalty);  
                 return 0;  
395          }          }
396          if (!strcmp(data, CCS_KEYWORD_PREFERENCE_PERMISSIVE)) {          if (!strcmp(data, "permissive")) {
397                  if (use_default) {                  if (use_default) {
398                          profile->permissive = &ccs_default_profile.preference;                          pref = &profile->permissive;
399                          return 0;                          goto set_default;
400                  }                  }
401                  profile->permissive = &profile->preference;                  profile->permissive = &profile->preference;
402                  if (value >= 0)                  verbose = &profile->preference.permissive_verbose;
403                          profile->preference.permissive_verbose = value;                  goto set_verbose;
                 return 0;  
404          }          }
405          if (!strcmp(data, CCS_KEYWORD_PREFERENCE_LEARNING)) {          if (!strcmp(data, "learning")) {
                 char *cp2;  
406                  if (use_default) {                  if (use_default) {
407                          profile->learning = &ccs_default_profile.preference;                          pref = &profile->learning;
408                          return 0;                          goto set_default;
409                  }                  }
410                  profile->learning = &profile->preference;                  profile->learning = &profile->preference;
411                  if (value >= 0)                  ccs_set_uint(&profile->preference.learning_max_entry, cp,
412                          profile->preference.learning_verbose = value;                               "max_entry");
413                  cp2 = strstr(cp, "max_entry=");                  ccs_set_bool(&profile->preference.learning_exec_realpath, cp,
414                  if (cp2)                               "exec.realpath");
415                          sscanf(cp2 + 10, "%u",                  ccs_set_bool(&profile->preference.learning_exec_argv0, cp,
416                                 &profile->preference.learning_max_entry);                               "exec.argv0");
417                  if (strstr(cp, "exec.realpath=yes"))                  ccs_set_bool(&profile->preference.learning_symlink_target, cp,
418                          profile->preference.learning_exec_realpath = true;                               "symlink.target");
419                  else if (strstr(cp, "exec.realpath=no"))                  verbose = &profile->preference.learning_verbose;
420                          profile->preference.learning_exec_realpath = false;                  goto set_verbose;
421                  if (strstr(cp, "exec.argv0=yes"))          }
422                          profile->preference.learning_exec_argv0 = true;          return;
423                  else if (strstr(cp, "exec.argv0=no"))   set_default:
424                          profile->preference.learning_exec_argv0 = false;          *pref = &ccs_default_profile.preference;
425                  if (strstr(cp, "symlink.target=yes"))          return;
426                          profile->preference.learning_symlink_target = true;   set_verbose:
427                  else if (strstr(cp, "symlink.target=no"))          ccs_set_bool(verbose, cp, "verbose");
428                          profile->preference.learning_symlink_target = false;  }
429                  return 0;  
430          }  static int ccs_set_mode(const char *cp, char *data,
431          if (profile == &ccs_default_profile)                          struct ccs_profile *profile, const bool use_default)
432                  return -EINVAL;  {
433          if (!strcmp(data, "COMMENT")) {          u8 i;
434                  const struct ccs_path_info *old_comment = profile->comment;          u8 config;
                 profile->comment = ccs_get_name(cp);  
                 ccs_put_name(old_comment);  
                 return 0;  
         }  
435          if (!strcmp(data, "CONFIG")) {          if (!strcmp(data, "CONFIG")) {
436                  i = CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX                  i = CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
437                          + CCS_MAX_MAC_CATEGORY_INDEX;                          + CCS_MAX_MAC_CATEGORY_INDEX;
# Line 478  static int ccs_write_profile(struct ccs_ Line 454  static int ccs_write_profile(struct ccs_
454          if (use_default) {          if (use_default) {
455                  config = CCS_CONFIG_USE_DEFAULT;                  config = CCS_CONFIG_USE_DEFAULT;
456          } else {          } else {
457                  for (mode = 3; mode >= 0; mode--)                  u8 mode;
458                          if (strstr(cp, ccs_mode_4[mode]))                  for (mode = 0; mode < CCS_CONFIG_MAX_MODE; mode--)
459                            if (strstr(cp, ccs_mode[mode]))
460                                  /*                                  /*
461                                   * Update lower 3 bits in order to distinguish                                   * Update lower 3 bits in order to distinguish
462                                   * 'config' from 'CCS_CONFIG_USE_DEAFULT'.                                   * 'config' from 'CCS_CONFIG_USE_DEAFULT'.
# Line 487  static int ccs_write_profile(struct ccs_ Line 464  static int ccs_write_profile(struct ccs_
464                                  config = (config & ~7) | mode;                                  config = (config & ~7) | mode;
465  #ifdef CONFIG_CCSECURITY_AUDIT  #ifdef CONFIG_CCSECURITY_AUDIT
466                  if (config != CCS_CONFIG_USE_DEFAULT) {                  if (config != CCS_CONFIG_USE_DEFAULT) {
467                          if (strstr(cp, "grant_log=yes"))                          switch (ccs_find_yesno(cp, "grant_log")) {
468                            case 1:
469                                  config |= CCS_CONFIG_WANT_GRANT_LOG;                                  config |= CCS_CONFIG_WANT_GRANT_LOG;
470                          else if (strstr(cp, "grant_log=no"))                                  break;
471                            case 0:
472                                  config &= ~CCS_CONFIG_WANT_GRANT_LOG;                                  config &= ~CCS_CONFIG_WANT_GRANT_LOG;
473                          if (strstr(cp, "reject_log=yes"))                                  break;
474                            }
475                            switch (ccs_find_yesno(cp, "reject_log")) {
476                            case 1:
477                                  config |= CCS_CONFIG_WANT_REJECT_LOG;                                  config |= CCS_CONFIG_WANT_REJECT_LOG;
478                          else if (strstr(cp, "reject_log=no"))                                  break;
479                            case 0:
480                                  config &= ~CCS_CONFIG_WANT_REJECT_LOG;                                  config &= ~CCS_CONFIG_WANT_REJECT_LOG;
481                                    break;
482                            }
483                  }                  }
484  #endif  #endif
485          }          }
# Line 506  static int ccs_write_profile(struct ccs_ Line 491  static int ccs_write_profile(struct ccs_
491          return 0;          return 0;
492  }  }
493    
494    /**
495     * ccs_write_profile - Write profile table.
496     *
497     * @head: Pointer to "struct ccs_io_buffer".
498     *
499     * Returns 0 on success, negative value otherwise.
500     */
501    static int ccs_write_profile(struct ccs_io_buffer *head)
502    {
503            char *data = head->write_buf;
504            bool use_default = false;
505            char *cp;
506            int i;
507            struct ccs_profile *profile;
508            if (sscanf(data, "PROFILE_VERSION=%u", &ccs_profile_version) == 1)
509                    return 0;
510            i = simple_strtoul(data, &cp, 10);
511            if (data == cp) {
512                    profile = &ccs_default_profile;
513            } else {
514                    if (*cp != '-')
515                            return -EINVAL;
516                    data = cp + 1;
517                    profile = ccs_assign_profile(i);
518                    if (!profile)
519                            return -EINVAL;
520            }
521            cp = strchr(data, '=');
522            if (!cp)
523                    return -EINVAL;
524            *cp++ = '\0';
525            if (profile != &ccs_default_profile)
526                    use_default = strstr(cp, "use_default") != NULL;
527            if (ccs_str_starts(&data, "PREFERENCE::")) {
528                    ccs_set_pref(cp, data, profile, use_default);
529                    return 0;
530            }
531            if (profile == &ccs_default_profile)
532                    return -EINVAL;
533            if (!strcmp(data, "COMMENT")) {
534                    const struct ccs_path_info *old_comment = profile->comment;
535                    profile->comment = ccs_get_name(cp);
536                    ccs_put_name(old_comment);
537                    return 0;
538            }
539            return ccs_set_mode(cp, data, profile, use_default);
540    }
541    
542  static bool ccs_print_preference(struct ccs_io_buffer *head, const int idx)  static bool ccs_print_preference(struct ccs_io_buffer *head, const int idx)
543  {  {
544          struct ccs_preference *pref = &ccs_default_profile.preference;          struct ccs_preference *pref = &ccs_default_profile.preference;
# Line 521  static bool ccs_print_preference(struct Line 554  static bool ccs_print_preference(struct
554                  if (pref == &ccs_default_profile.preference)                  if (pref == &ccs_default_profile.preference)
555                          pref = NULL;                          pref = NULL;
556          }          }
557          if (pref && !ccs_io_printf(head, "%s%s={ "          if (pref && !ccs_io_printf(head, "%sPREFERENCE::%s={ "
558  #ifdef CONFIG_CCSECURITY_AUDIT  #ifdef CONFIG_CCSECURITY_AUDIT
559                                     "max_grant_log=%u max_reject_log=%u "                                     "max_grant_log=%u max_reject_log=%u "
560  #endif  #endif
561                                     "task_info=%s path_info=%s }\n", buffer,                                     "task_info=%s path_info=%s }\n", buffer,
562                                     CCS_KEYWORD_PREFERENCE_AUDIT,                                     "audit",
563  #ifdef CONFIG_CCSECURITY_AUDIT  #ifdef CONFIG_CCSECURITY_AUDIT
564                                     pref->audit_max_grant_log,                                     pref->audit_max_grant_log,
565                                     pref->audit_max_reject_log,                                     pref->audit_max_reject_log,
# Line 539  static bool ccs_print_preference(struct Line 572  static bool ccs_print_preference(struct
572                  if (pref == &ccs_default_profile.preference)                  if (pref == &ccs_default_profile.preference)
573                          pref = NULL;                          pref = NULL;
574          }          }
575          if (pref && !ccs_io_printf(head, "%s%s={ "          if (pref && !ccs_io_printf(head, "%sPREFERENCE::%s={ "
576                                     "verbose=%s max_entry=%u exec.realpath=%s "                                     "verbose=%s max_entry=%u exec.realpath=%s "
577                                     "exec.argv0=%s symlink.target=%s }\n",                                     "exec.argv0=%s symlink.target=%s }\n",
578                                     buffer, CCS_KEYWORD_PREFERENCE_LEARNING,                                     buffer, "learning",
579                                     ccs_yesno(pref->learning_verbose),                                     ccs_yesno(pref->learning_verbose),
580                                     pref->learning_max_entry,                                     pref->learning_max_entry,
581                                     ccs_yesno(pref->learning_exec_realpath),                                     ccs_yesno(pref->learning_exec_realpath),
# Line 554  static bool ccs_print_preference(struct Line 587  static bool ccs_print_preference(struct
587                  if (pref == &ccs_default_profile.preference)                  if (pref == &ccs_default_profile.preference)
588                          pref = NULL;                          pref = NULL;
589          }          }
590          if (pref && !ccs_io_printf(head, "%s%s={ verbose=%s }\n", buffer,          if (pref && !ccs_io_printf(head, "%sPREFERENCE::%s={ verbose=%s }\n",
591                                     CCS_KEYWORD_PREFERENCE_PERMISSIVE,                                     buffer, "permissive",
592                                     ccs_yesno(pref->permissive_verbose)))                                     ccs_yesno(pref->permissive_verbose)))
593                  return false;                  return false;
594          if (profile) {          if (profile) {
# Line 563  static bool ccs_print_preference(struct Line 596  static bool ccs_print_preference(struct
596                  if (pref == &ccs_default_profile.preference)                  if (pref == &ccs_default_profile.preference)
597                          pref = NULL;                          pref = NULL;
598          }          }
599          return !pref || ccs_io_printf(head, "%s%s={ verbose=%s penalty=%u }\n",          return !pref || ccs_io_printf(head, "%sPREFERENCE::%s={ verbose=%s "
600                                        buffer, CCS_KEYWORD_PREFERENCE_ENFORCING,                                        "penalty=%u }\n", buffer, "enforcing",
601                                        ccs_yesno(pref->enforcing_verbose),                                        ccs_yesno(pref->enforcing_verbose),
602                                        pref->enforcing_penalty);                                        pref->enforcing_penalty);
603  }  }
# Line 605  static void ccs_read_profile(struct ccs_ Line 638  static void ccs_read_profile(struct ccs_
638  #ifdef CONFIG_CCSECURITY_AUDIT  #ifdef CONFIG_CCSECURITY_AUDIT
639                  if (!ccs_io_printf(head, "%u-%s%s={ mode=%s "                  if (!ccs_io_printf(head, "%u-%s%s={ mode=%s "
640                                     "grant_log=%s reject_log=%s }\n", index,                                     "grant_log=%s reject_log=%s }\n", index,
641                                     "CONFIG", "", ccs_mode_4[config & 3],                                     "CONFIG", "", ccs_mode[config & 3],
642                                     ccs_yesno(config &                                     ccs_yesno(config &
643                                               CCS_CONFIG_WANT_GRANT_LOG),                                               CCS_CONFIG_WANT_GRANT_LOG),
644                                     ccs_yesno(config &                                     ccs_yesno(config &
# Line 613  static void ccs_read_profile(struct ccs_ Line 646  static void ccs_read_profile(struct ccs_
646                          goto out;                          goto out;
647  #else  #else
648                  if (!ccs_io_printf(head, "%u-%s%s={ mode=%s }\n", index,                  if (!ccs_io_printf(head, "%u-%s%s={ mode=%s }\n", index,
649                                     "CONFIG", "", ccs_mode_4[config & 3]))                                     "CONFIG", "", ccs_mode[config & 3]))
650                          goto out;                          goto out;
651  #endif  #endif
652                  for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX                  for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
# Line 632  static void ccs_read_profile(struct ccs_ Line 665  static void ccs_read_profile(struct ccs_
665                                             "grant_log=%s reject_log=%s }\n",                                             "grant_log=%s reject_log=%s }\n",
666                                             index, "CONFIG::",                                             index, "CONFIG::",
667                                             ccs_mac_keywords[i],                                             ccs_mac_keywords[i],
668                                             ccs_mode_4[config & 3], g, r))                                             ccs_mode[config & 3], g, r))
669                                  goto out;                                  goto out;
670  #else  #else
671                          if (!ccs_io_printf(head, "%u-%s%s={ mode=%s }\n",                          if (!ccs_io_printf(head, "%u-%s%s={ mode=%s }\n",
672                                             index, "CONFIG::",                                             index, "CONFIG::",
673                                             ccs_mac_keywords[i],                                             ccs_mac_keywords[i],
674                                             ccs_mode_4[config & 3]))                                             ccs_mode[config & 3]))
675                                  goto out;                                  goto out;
676  #endif  #endif
677                  }                  }
# Line 654  static void ccs_read_profile(struct ccs_ Line 687  static void ccs_read_profile(struct ccs_
687  }  }
688    
689  static bool ccs_same_manager_entry(const struct ccs_acl_head *a,  static bool ccs_same_manager_entry(const struct ccs_acl_head *a,
690                                        const struct ccs_acl_head *b)                                     const struct ccs_acl_head *b)
691  {  {
692          return container_of(a, struct ccs_manager, head)->manager          return container_of(a, struct ccs_manager, head)->manager
693                  == container_of(b, struct ccs_manager, head)->manager;                  == container_of(b, struct ccs_manager, head)->manager;
# Line 677  static int ccs_update_manager_entry(cons Line 710  static int ccs_update_manager_entry(cons
710                          return -EINVAL;                          return -EINVAL;
711                  e.is_domain = true;                  e.is_domain = true;
712          } else {          } else {
713                  if (!ccs_correct_path(manager, 1, -1, -1))                  if (!ccs_correct_path(manager))
714                          return -EINVAL;                          return -EINVAL;
715          }          }
716          e.manager = ccs_get_name(manager);          e.manager = ccs_get_name(manager);
# Line 753  static bool ccs_manager(void) Line 786  static bool ccs_manager(void)
786                  return true;                  return true;
787          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))
788                  return false;                  return false;
         list_for_each_entry_rcu(ptr, &ccs_policy_list[CCS_ID_MANAGER],  
                                 head.list) {  
                 if (!ptr->head.is_deleted && ptr->is_domain  
                     && !ccs_pathcmp(domainname, ptr->manager)) {  
                         /* Set manager flag. */  
                         task->ccs_flags |= CCS_TASK_IS_MANAGER;  
                         return true;  
                 }  
         }  
789          exe = ccs_get_exe();          exe = ccs_get_exe();
         if (!exe)  
                 return false;  
790          list_for_each_entry_rcu(ptr, &ccs_policy_list[CCS_ID_MANAGER],          list_for_each_entry_rcu(ptr, &ccs_policy_list[CCS_ID_MANAGER],
791                                  head.list) {                                  head.list) {
792                  if (!ptr->head.is_deleted && !ptr->is_domain                  if (ptr->head.is_deleted)
793                      && !strcmp(exe, ptr->manager->name)) {                          continue;
794                          found = true;                  if (ptr->is_domain) {
795                          /* Set manager flag. */                          if (ccs_pathcmp(domainname, ptr->manager))
796                          task->ccs_flags |= CCS_TASK_IS_MANAGER;                                  continue;
797                          break;                  } else {
798                            if (!exe || strcmp(exe, ptr->manager->name))
799                                    continue;
800                  }                  }
801                    /* Set manager flag. */
802                    task->ccs_flags |= CCS_TASK_IS_MANAGER;
803                    found = true;
804                    break;
805          }          }
806          if (!found) { /* Reduce error messages. */          if (!found) { /* Reduce error messages. */
807                  static pid_t ccs_last_pid;                  static pid_t ccs_last_pid;
# Line 799  static bool ccs_manager(void) Line 827  static bool ccs_manager(void)
827  static char *ccs_find_condition_part(char *data)  static char *ccs_find_condition_part(char *data)
828  {  {
829          char *cp = strstr(data, " if ");          char *cp = strstr(data, " if ");
830          if (cp) {          if (!cp)
                 while (1) {  
                         char *cp2 = strstr(cp + 3, " if ");  
                         if (!cp2)  
                                 break;  
                         cp = cp2;  
                 }  
                 *cp++ = '\0';  
         } else {  
831                  cp = strstr(data, " ; set ");                  cp = strstr(data, " ; set ");
832                  if (cp)          if (cp)
833                          *cp++ = '\0';                  *cp++ = '\0';
         }  
834          return cp;          return cp;
835  }  }
836    
# Line 881  static bool ccs_select_one(struct ccs_io Line 900  static bool ccs_select_one(struct ccs_io
900  }  }
901    
902  static int ccs_write_domain2(char *data, struct ccs_domain_info *domain,  static int ccs_write_domain2(char *data, struct ccs_domain_info *domain,
903                               struct ccs_condition *cond, const bool is_delete)                               const bool is_delete)
904  {  {
         u8 i;  
905          static const struct {          static const struct {
906                  const char *keyword;                  const char *keyword;
907                  int (*write) (char *, struct ccs_domain_info *,                  int (*write) (char *, struct ccs_domain_info *,
# Line 897  static int ccs_write_domain2(char *data, Line 915  static int ccs_write_domain2(char *data,
915          };          };
916          int (*write) (char *, struct ccs_domain_info *, struct ccs_condition *,          int (*write) (char *, struct ccs_domain_info *, struct ccs_condition *,
917                        const bool) = ccs_write_file;                        const bool) = ccs_write_file;
918            int error;
919            u8 i;
920            struct ccs_condition *cond = NULL;
921            char *cp = ccs_find_condition_part(data);
922            if (cp) {
923                    cond = ccs_get_condition(cp);
924                    if (!cond)
925                            return -EINVAL;
926            }
927          for (i = 0; i < 5; i++) {          for (i = 0; i < 5; i++) {
928                  if (!ccs_str_starts(&data, ccs_callback[i].keyword))                  if (!ccs_str_starts(&data, ccs_callback[i].keyword))
929                          continue;                          continue;
930                  write = ccs_callback[i].write;                  write = ccs_callback[i].write;
931                  break;                  break;
932          }          }
933          return write(data, domain, cond, is_delete);          error = write(data, domain, cond, is_delete);
934            if (cond)
935                    ccs_put_condition(cond);
936            return error;
937  }  }
938    
939    static const char *ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = {
940            [CCS_DIF_QUOTA_WARNED] = CCS_KEYWORD_QUOTA_EXCEEDED "\n",
941            [CCS_DIF_IGNORE_GLOBAL] = CCS_KEYWORD_IGNORE_GLOBAL "\n",
942            [CCS_DIF_IGNORE_GLOBAL_ALLOW_READ]
943            = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n",
944            [CCS_DIF_IGNORE_GLOBAL_ALLOW_ENV]
945            = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_ENV "\n",
946            [CCS_DIF_TRANSITION_FAILED] = CCS_KEYWORD_TRANSITION_FAILED "\n"
947    };
948            
949  /**  /**
950   * ccs_write_domain - Write domain policy.   * ccs_write_domain - Write domain policy.
951   *   *
# Line 920  static int ccs_write_domain(struct ccs_i Line 960  static int ccs_write_domain(struct ccs_i
960          bool is_delete = false;          bool is_delete = false;
961          bool is_select = false;          bool is_select = false;
962          unsigned int profile;          unsigned int profile;
         struct ccs_condition *cond = NULL;  
         char *cp;  
         int error;  
963          if (ccs_str_starts(&data, CCS_KEYWORD_DELETE))          if (ccs_str_starts(&data, CCS_KEYWORD_DELETE))
964                  is_delete = true;                  is_delete = true;
965          else if (ccs_str_starts(&data, CCS_KEYWORD_SELECT))          else if (ccs_str_starts(&data, CCS_KEYWORD_SELECT))
# Line 939  static int ccs_write_domain(struct ccs_i Line 976  static int ccs_write_domain(struct ccs_i
976                  else if (is_select)                  else if (is_select)
977                          domain = ccs_find_domain(data);                          domain = ccs_find_domain(data);
978                  else                  else
979                          domain = ccs_find_or_assign_new_domain(data, 0);                          domain = ccs_assign_domain(data, 0);
980                  head->write_var1 = domain;                  head->write_var1 = domain;
981                  return 0;                  return 0;
982          }          }
# Line 952  static int ccs_write_domain(struct ccs_i Line 989  static int ccs_write_domain(struct ccs_i
989                          domain->profile = (u8) profile;                          domain->profile = (u8) profile;
990                  return 0;                  return 0;
991          }          }
992          if (!strcmp(data, CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {          for (profile = 0; profile < CCS_MAX_DOMAIN_INFO_FLAGS; profile++) {
993                  domain->ignore_global_allow_read = !is_delete;                  const char *cp = ccs_dif[profile];
994                  return 0;                  if (strncmp(data, cp, strlen(cp) - 1))
995          }                          continue;
996          if (!strcmp(data, CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_ENV)) {                  domain->flags[profile] = !is_delete;
                 domain->ignore_global_allow_env = !is_delete;  
                 return 0;  
         }  
         if (!strcmp(data, CCS_KEYWORD_QUOTA_EXCEEDED)) {  
                 domain->quota_warned = !is_delete;  
                 return 0;  
         }  
         if (!strcmp(data, CCS_KEYWORD_TRANSITION_FAILED)) {  
                 domain->domain_transition_failed = !is_delete;  
997                  return 0;                  return 0;
998          }          }
999          cp = ccs_find_condition_part(data);          return ccs_write_domain2(data, domain, is_delete);
         if (cp) {  
                 cond = ccs_get_condition(cp);  
                 if (!cond)  
                         return -EINVAL;  
         }  
         error = ccs_write_domain2(data, domain, cond, is_delete);  
         if (cond)  
                 ccs_put_condition(cond);  
         return error;  
1000  }  }
1001    
1002  /**  /**
# Line 1082  static bool ccs_print_number_union_commo Line 1101  static bool ccs_print_number_union_commo
1101   *   *
1102   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1103   */   */
1104  bool ccs_print_number_union(struct ccs_io_buffer *head,  static bool ccs_print_number_union(struct ccs_io_buffer *head,
1105                              const struct ccs_number_union *ptr)                                     const struct ccs_number_union *ptr)
1106  {  {
1107          return ccs_print_number_union_common(head, ptr, true);          return ccs_print_number_union_common(head, ptr, true);
1108  }  }
# Line 1106  static bool ccs_print_number_union_nospa Line 1125  static bool ccs_print_number_union_nospa
1125   * ccs_print_condition - Print condition part.   * ccs_print_condition - Print condition part.
1126   *   *
1127   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1128   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". Maybe NULL.
1129   *   *
1130   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1131   */   */
# Line 1206  static bool ccs_print_condition(struct c Line 1225  static bool ccs_print_condition(struct c
1225                                     cond->post_state[j]))                                     cond->post_state[j]))
1226                          goto out;                          goto out;
1227          }          }
1228            if (i & (1 << 4)) {
1229                    if (!ccs_io_printf(head, " audit=%s",
1230                                       ccs_yesno(cond->post_state[4])))
1231                            goto out;
1232            }
1233   no_condition:   no_condition:
1234          if (ccs_io_printf(head, "\n"))          if (ccs_io_printf(head, "\n"))
1235                  return true;                  return true;
# Line 1218  static bool ccs_print_condition(struct c Line 1242  static bool ccs_print_condition(struct c
1242   *   *
1243   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1244   * @ptr:  Pointer to "struct ccs_path_acl".   * @ptr:  Pointer to "struct ccs_path_acl".
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
1245   *   *
1246   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1247   */   */
1248  static bool ccs_print_path_acl(struct ccs_io_buffer *head,  static bool ccs_print_path_acl(struct ccs_io_buffer *head,
1249                                 struct ccs_path_acl *ptr,                                 struct ccs_path_acl *ptr)
                                const struct ccs_condition *cond)  
1250  {  {
1251          int pos;          int pos;
1252          u8 bit;          u8 bit;
# Line 1242  static bool ccs_print_path_acl(struct cc Line 1264  static bool ccs_print_path_acl(struct cc
1264                  pos = head->read_avail;                  pos = head->read_avail;
1265                  if (!ccs_io_printf(head, "allow_%s", ccs_path2keyword(bit)) ||                  if (!ccs_io_printf(head, "allow_%s", ccs_path2keyword(bit)) ||
1266                      !ccs_print_name_union(head, &ptr->name) ||                      !ccs_print_name_union(head, &ptr->name) ||
1267                      !ccs_print_condition(head, cond)) {                      !ccs_print_condition(head, ptr->head.cond)) {
1268                          head->read_bit = bit;                          head->read_bit = bit;
1269                          head->read_avail = pos;                          head->read_avail = pos;
1270                          return false;                          return false;
# Line 1257  static bool ccs_print_path_acl(struct cc Line 1279  static bool ccs_print_path_acl(struct cc
1279   *   *
1280   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1281   * @ptr:  Pointer to "struct ccs_path_number3_acl".   * @ptr:  Pointer to "struct ccs_path_number3_acl".
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
1282   *   *
1283   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1284   */   */
1285  static bool ccs_print_path_number3_acl(struct ccs_io_buffer *head,  static bool ccs_print_path_number3_acl(struct ccs_io_buffer *head,
1286                                         struct ccs_path_number3_acl *ptr,                                         struct ccs_path_number3_acl *ptr)
                                        const struct ccs_condition *cond)  
1287  {  {
1288          int pos;          int pos;
1289          u8 bit;          u8 bit;
# Line 1279  static bool ccs_print_path_number3_acl(s Line 1299  static bool ccs_print_path_number3_acl(s
1299                      !ccs_print_number_union(head, &ptr->mode) ||                      !ccs_print_number_union(head, &ptr->mode) ||
1300                      !ccs_print_number_union(head, &ptr->major) ||                      !ccs_print_number_union(head, &ptr->major) ||
1301                      !ccs_print_number_union(head, &ptr->minor) ||                      !ccs_print_number_union(head, &ptr->minor) ||
1302                      !ccs_print_condition(head, cond)) {                      !ccs_print_condition(head, ptr->head.cond)) {
1303                          head->read_bit = bit;                          head->read_bit = bit;
1304                          head->read_avail = pos;                          head->read_avail = pos;
1305                          return false;                          return false;
# Line 1294  static bool ccs_print_path_number3_acl(s Line 1314  static bool ccs_print_path_number3_acl(s
1314   *   *
1315   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1316   * @ptr:  Pointer to "struct ccs_path2_acl".   * @ptr:  Pointer to "struct ccs_path2_acl".
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
1317   *   *
1318   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1319   */   */
1320  static bool ccs_print_path2_acl(struct ccs_io_buffer *head,  static bool ccs_print_path2_acl(struct ccs_io_buffer *head,
1321                                  struct ccs_path2_acl *ptr,                                  struct ccs_path2_acl *ptr)
                                 const struct ccs_condition *cond)  
1322  {  {
1323          int pos;          int pos;
1324          u8 bit;          u8 bit;
# Line 1313  static bool ccs_print_path2_acl(struct c Line 1331  static bool ccs_print_path2_acl(struct c
1331                                     ccs_path22keyword(bit)) ||                                     ccs_path22keyword(bit)) ||
1332                      !ccs_print_name_union(head, &ptr->name1) ||                      !ccs_print_name_union(head, &ptr->name1) ||
1333                      !ccs_print_name_union(head, &ptr->name2) ||                      !ccs_print_name_union(head, &ptr->name2) ||
1334                      !ccs_print_condition(head, cond)) {                      !ccs_print_condition(head, ptr->head.cond)) {
1335                          head->read_bit = bit;                          head->read_bit = bit;
1336                          head->read_avail = pos;                          head->read_avail = pos;
1337                          return false;                          return false;
# Line 1328  static bool ccs_print_path2_acl(struct c Line 1346  static bool ccs_print_path2_acl(struct c
1346   *   *
1347   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1348   * @ptr:  Pointer to "struct ccs_path_number_acl".   * @ptr:  Pointer to "struct ccs_path_number_acl".
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
1349   *   *
1350   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1351   */   */
1352  static bool ccs_print_path_number_acl(struct ccs_io_buffer *head,  static bool ccs_print_path_number_acl(struct ccs_io_buffer *head,
1353                                        struct ccs_path_number_acl *ptr,                                        struct ccs_path_number_acl *ptr)
                                       const struct ccs_condition *cond)  
1354  {  {
1355          int pos;          int pos;
1356          u8 bit;          u8 bit;
# Line 1348  static bool ccs_print_path_number_acl(st Line 1364  static bool ccs_print_path_number_acl(st
1364                                     ccs_path_number2keyword(bit)) ||                                     ccs_path_number2keyword(bit)) ||
1365                      !ccs_print_name_union(head, &ptr->name) ||                      !ccs_print_name_union(head, &ptr->name) ||
1366                      !ccs_print_number_union(head, &ptr->number) ||                      !ccs_print_number_union(head, &ptr->number) ||
1367                      !ccs_print_condition(head, cond)) {                      !ccs_print_condition(head, ptr->head.cond)) {
1368                          head->read_bit = bit;                          head->read_bit = bit;
1369                          head->read_avail = pos;                          head->read_avail = pos;
1370                          return false;                          return false;
# Line 1363  static bool ccs_print_path_number_acl(st Line 1379  static bool ccs_print_path_number_acl(st
1379   *   *
1380   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1381   * @ptr:  Pointer to "struct ccs_env_acl".   * @ptr:  Pointer to "struct ccs_env_acl".
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
1382   *   *
1383   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1384   */   */
1385  static bool ccs_print_env_acl(struct ccs_io_buffer *head,  static bool ccs_print_env_acl(struct ccs_io_buffer *head,
1386                                struct ccs_env_acl *ptr,                                struct ccs_env_acl *ptr)
                               const struct ccs_condition *cond)  
1387  {  {
1388          const int pos = head->read_avail;          const int pos = head->read_avail;
1389          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_ENV "%s", ptr->env->name) ||          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_ENV "%s", ptr->env->name) ||
1390              !ccs_print_condition(head, cond)) {              !ccs_print_condition(head, ptr->head.cond)) {
1391                  head->read_avail = pos;                  head->read_avail = pos;
1392                  return false;                  return false;
1393          }          }
# Line 1385  static bool ccs_print_env_acl(struct ccs Line 1399  static bool ccs_print_env_acl(struct ccs
1399   *   *
1400   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1401   * @ptr:  Pointer to "struct ccs_capability_acl".   * @ptr:  Pointer to "struct ccs_capability_acl".
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
1402   *   *
1403   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1404   */   */
1405  static bool ccs_print_capability_acl(struct ccs_io_buffer *head,  static bool ccs_print_capability_acl(struct ccs_io_buffer *head,
1406                                       struct ccs_capability_acl *ptr,                                       struct ccs_capability_acl *ptr)
                                      const struct ccs_condition *cond)  
1407  {  {
1408          const int pos = head->read_avail;          const int pos = head->read_avail;
1409          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CAPABILITY "%s",          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CAPABILITY "%s",
1410                             ccs_cap2keyword(ptr->operation)) ||                             ccs_cap2keyword(ptr->operation)) ||
1411              !ccs_print_condition(head, cond)) {              !ccs_print_condition(head, ptr->head.cond)) {
1412                  head->read_avail = pos;                  head->read_avail = pos;
1413                  return false;                  return false;
1414          }          }
# Line 1408  static bool ccs_print_capability_acl(str Line 1420  static bool ccs_print_capability_acl(str
1420   *   *
1421   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1422   * @ptr:  Pointer to "struct ccs_ip_network_acl".   * @ptr:  Pointer to "struct ccs_ip_network_acl".
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
1423   *   *
1424   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1425   */   */
1426  static bool ccs_print_network_acl(struct ccs_io_buffer *head,  static bool ccs_print_network_acl(struct ccs_io_buffer *head,
1427                                    struct ccs_ip_network_acl *ptr,                                    struct ccs_ip_network_acl *ptr)
                                   const struct ccs_condition *cond)  
1428  {  {
1429          int pos;          int pos;
1430          u8 bit;          u8 bit;
1431          const u16 perm = ptr->perm;          const u8 perm = ptr->perm;
1432          char buf[128];          char buf[128];
1433          for (bit = head->read_bit; bit < CCS_MAX_NETWORK_OPERATION; bit++) {          for (bit = head->read_bit; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
1434                  const char *w[2] = { "", "" };                  const char *w[2] = { "", "" };
# Line 1444  static bool ccs_print_network_acl(struct Line 1454  static bool ccs_print_network_acl(struct
1454                  if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s %s%s",                  if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s %s%s",
1455                                     ccs_net2keyword(bit), w[0], w[1]) ||                                     ccs_net2keyword(bit), w[0], w[1]) ||
1456                      !ccs_print_number_union(head, &ptr->port) ||                      !ccs_print_number_union(head, &ptr->port) ||
1457                      !ccs_print_condition(head, cond))                      !ccs_print_condition(head, ptr->head.cond))
1458                          goto out;                          goto out;
1459          }          }
1460          head->read_bit = 0;          head->read_bit = 0;
# Line 1460  static bool ccs_print_network_acl(struct Line 1470  static bool ccs_print_network_acl(struct
1470   *   *
1471   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1472   * @ptr:  Pointer to "struct signale_acl".   * @ptr:  Pointer to "struct signale_acl".
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
1473   *   *
1474   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1475   */   */
1476  static bool ccs_print_signal_acl(struct ccs_io_buffer *head,  static bool ccs_print_signal_acl(struct ccs_io_buffer *head,
1477                                   struct ccs_signal_acl *ptr,                                   struct ccs_signal_acl *ptr)
                                  const struct ccs_condition *cond)  
1478  {  {
1479          const int pos = head->read_avail;          const int pos = head->read_avail;
1480          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_SIGNAL "%u %s",          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_SIGNAL "%u %s",
1481                             ptr->sig, ptr->domainname->name) ||                             ptr->sig, ptr->domainname->name) ||
1482              !ccs_print_condition(head, cond)) {              !ccs_print_condition(head, ptr->head.cond)) {
1483                  head->read_avail = pos;                  head->read_avail = pos;
1484                  return false;                  return false;
1485          }          }
# Line 1479  static bool ccs_print_signal_acl(struct Line 1487  static bool ccs_print_signal_acl(struct
1487  }  }
1488    
1489  /**  /**
1490   * ccs_print_execute_handler_record - Print an execute handler ACL entry.   * ccs_print_execute_handler - Print an execute handler ACL entry.
1491   *   *
1492   * @head:    Pointer to "struct ccs_io_buffer".   * @head:    Pointer to "struct ccs_io_buffer".
1493   * @keyword: Name of the keyword.   * @keyword: Name of the keyword.
1494   * @ptr:     Pointer to "struct ccs_execute_handler_record".   * @ptr:     Pointer to "struct ccs_execute_handler".
1495   *   *
1496   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1497   */   */
1498  static bool ccs_print_execute_handler_record(struct ccs_io_buffer *head,  static bool ccs_print_execute_handler(struct ccs_io_buffer *head,
1499                                               const char *keyword,                                        const char *keyword,
1500                                               struct ccs_execute_handler_record                                        struct ccs_execute_handler *ptr)
                                              *ptr)  
1501  {  {
1502          return ccs_io_printf(head, "%s %s\n", keyword, ptr->handler->name);          const int pos = head->read_avail;
1503            if (!ccs_io_printf(head, "%s %s", keyword, ptr->handler->name) ||
1504                !ccs_print_condition(head, ptr->head.cond)) {
1505                    head->read_avail = pos;
1506                    return false;
1507            }
1508            return true;
1509  }  }
1510    
1511  /**  /**
# Line 1500  static bool ccs_print_execute_handler_re Line 1513  static bool ccs_print_execute_handler_re
1513   *   *
1514   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1515   * @ptr:  Pointer to "struct ccs_mount_acl".   * @ptr:  Pointer to "struct ccs_mount_acl".
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
1516   *   *
1517   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1518   */   */
1519  static bool ccs_print_mount_acl(struct ccs_io_buffer *head,  static bool ccs_print_mount_acl(struct ccs_io_buffer *head,
1520                                  struct ccs_mount_acl *ptr,                                  struct ccs_mount_acl *ptr)
                                 const struct ccs_condition *cond)  
1521  {  {
1522          const int pos = head->read_avail;          const int pos = head->read_avail;
1523          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_MOUNT) ||          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_MOUNT) ||
# Line 1514  static bool ccs_print_mount_acl(struct c Line 1525  static bool ccs_print_mount_acl(struct c
1525              !ccs_print_name_union(head, &ptr->dir_name) ||              !ccs_print_name_union(head, &ptr->dir_name) ||
1526              !ccs_print_name_union(head, &ptr->fs_type) ||              !ccs_print_name_union(head, &ptr->fs_type) ||
1527              !ccs_print_number_union(head, &ptr->flags) ||              !ccs_print_number_union(head, &ptr->flags) ||
1528              !ccs_print_condition(head, cond)) {              !ccs_print_condition(head, ptr->head.cond)) {
1529                  head->read_avail = pos;                  head->read_avail = pos;
1530                  return false;                  return false;
1531          }          }
# Line 1532  static bool ccs_print_mount_acl(struct c Line 1543  static bool ccs_print_mount_acl(struct c
1543  static bool ccs_print_entry(struct ccs_io_buffer *head,  static bool ccs_print_entry(struct ccs_io_buffer *head,
1544                              struct ccs_acl_info *ptr)                              struct ccs_acl_info *ptr)
1545  {  {
         const struct ccs_condition *cond = ptr->cond;  
1546          const u8 acl_type = ptr->type;          const u8 acl_type = ptr->type;
1547          if (ptr->is_deleted)          if (ptr->is_deleted)
1548                  return true;                  return true;
1549          if (acl_type == CCS_TYPE_PATH_ACL) {          if (acl_type == CCS_TYPE_PATH_ACL) {
1550                  struct ccs_path_acl *acl                  struct ccs_path_acl *acl
1551                          = container_of(ptr, struct ccs_path_acl, head);                          = container_of(ptr, typeof(*acl), head);
1552                  return ccs_print_path_acl(head, acl, cond);                  return ccs_print_path_acl(head, acl);
1553          }          }
1554          if (acl_type == CCS_TYPE_EXECUTE_HANDLER) {          if (acl_type == CCS_TYPE_EXECUTE_HANDLER ||
1555                  struct ccs_execute_handler_record *acl              acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {
1556                          = container_of(ptr, struct ccs_execute_handler_record,                  struct ccs_execute_handler *acl
1557                                         head);                          = container_of(ptr, typeof(*acl), head);
1558                  const char *keyword = CCS_KEYWORD_EXECUTE_HANDLER;                  const char *keyword = acl_type == CCS_TYPE_EXECUTE_HANDLER ?
1559                  return ccs_print_execute_handler_record(head, keyword, acl);                          CCS_KEYWORD_EXECUTE_HANDLER :
1560          }                          CCS_KEYWORD_DENIED_EXECUTE_HANDLER;
1561          if (acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {                  return ccs_print_execute_handler(head, keyword, acl);
                 struct ccs_execute_handler_record *acl  
                         = container_of(ptr, struct ccs_execute_handler_record,  
                                        head);  
                 const char *keyword = CCS_KEYWORD_DENIED_EXECUTE_HANDLER;  
                 return ccs_print_execute_handler_record(head, keyword, acl);  
1562          }          }
1563          if (head->read_execute_only)          if (head->read_execute_only)
1564                  return true;                  return true;
1565          if (acl_type == CCS_TYPE_PATH_NUMBER3_ACL) {          if (acl_type == CCS_TYPE_PATH_NUMBER3_ACL) {
1566                  struct ccs_path_number3_acl *acl                  struct ccs_path_number3_acl *acl
1567                          = container_of(ptr, struct ccs_path_number3_acl, head);                          = container_of(ptr, typeof(*acl), head);
1568                  return ccs_print_path_number3_acl(head, acl, cond);                  return ccs_print_path_number3_acl(head, acl);
1569          }          }
1570          if (acl_type == CCS_TYPE_PATH2_ACL) {          if (acl_type == CCS_TYPE_PATH2_ACL) {
1571                  struct ccs_path2_acl *acl                  struct ccs_path2_acl *acl
1572                          = container_of(ptr, struct ccs_path2_acl, head);                          = container_of(ptr, typeof(*acl), head);
1573                  return ccs_print_path2_acl(head, acl, cond);                  return ccs_print_path2_acl(head, acl);
1574          }          }
1575          if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {          if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
1576                  struct ccs_path_number_acl *acl                  struct ccs_path_number_acl *acl
1577                          = container_of(ptr, struct ccs_path_number_acl, head);                          = container_of(ptr, typeof(*acl), head);
1578                  return ccs_print_path_number_acl(head, acl, cond);                  return ccs_print_path_number_acl(head, acl);
1579          }          }
1580          if (acl_type == CCS_TYPE_ENV_ACL) {          if (acl_type == CCS_TYPE_ENV_ACL) {
1581                  struct ccs_env_acl *acl                  struct ccs_env_acl *acl
1582                          = container_of(ptr, struct ccs_env_acl, head);                          = container_of(ptr, typeof(*acl), head);
1583                  return ccs_print_env_acl(head, acl, cond);                  return ccs_print_env_acl(head, acl);
1584          }          }
1585          if (acl_type == CCS_TYPE_CAPABILITY_ACL) {          if (acl_type == CCS_TYPE_CAPABILITY_ACL) {
1586                  struct ccs_capability_acl *acl                  struct ccs_capability_acl *acl
1587                          = container_of(ptr, struct ccs_capability_acl, head);                          = container_of(ptr, typeof(*acl), head);
1588                  return ccs_print_capability_acl(head, acl, cond);                  return ccs_print_capability_acl(head, acl);
1589          }          }
1590          if (acl_type == CCS_TYPE_IP_NETWORK_ACL) {          if (acl_type == CCS_TYPE_IP_NETWORK_ACL) {
1591                  struct ccs_ip_network_acl *acl                  struct ccs_ip_network_acl *acl
1592                          = container_of(ptr, struct ccs_ip_network_acl, head);                          = container_of(ptr, typeof(*acl), head);
1593                  return ccs_print_network_acl(head, acl, cond);                  return ccs_print_network_acl(head, acl);
1594          }          }
1595          if (acl_type == CCS_TYPE_SIGNAL_ACL) {          if (acl_type == CCS_TYPE_SIGNAL_ACL) {
1596                  struct ccs_signal_acl *acl                  struct ccs_signal_acl *acl
1597                          = container_of(ptr, struct ccs_signal_acl, head);                          = container_of(ptr, typeof(*acl), head);
1598                  return ccs_print_signal_acl(head, acl, cond);                  return ccs_print_signal_acl(head, acl);
1599          }          }
1600          if (acl_type == CCS_TYPE_MOUNT_ACL) {          if (acl_type == CCS_TYPE_MOUNT_ACL) {
1601                  struct ccs_mount_acl *acl                  struct ccs_mount_acl *acl
1602                          = container_of(ptr, struct ccs_mount_acl, head);                          = container_of(ptr, typeof(*acl), head);
1603                  return ccs_print_mount_acl(head, acl, cond);                  return ccs_print_mount_acl(head, acl);
1604          }          }
1605          BUG(); /* This must not happen. */          BUG(); /* This must not happen. */
1606          return false;          return false;
1607  }  }
1608    
1609  /**  /**
1610     * ccs_read_domain2 - Read domain policy.
1611     *
1612     * @head:   Pointer to "struct ccs_io_buffer".
1613     * @domain: Pointer to "struct ccs_domain_info".
1614     *
1615     * Caller holds ccs_read_lock().
1616     *
1617     * Returns true on success, false otherwise.
1618     */
1619    static bool ccs_read_domain2(struct ccs_io_buffer *head,
1620                                 struct ccs_domain_info *domain)
1621    {
1622            struct list_head *pos;
1623            /* Print ACL entries in the domain. */
1624            list_for_each_cookie(pos, head->read_var2, &domain->acl_info_list) {
1625                    struct ccs_acl_info *ptr
1626                            = list_entry(pos, struct ccs_acl_info, list);
1627                    if (!ccs_print_entry(head, ptr))
1628                            return false;
1629            }
1630            return true;
1631    }
1632    
1633    /**
1634   * ccs_read_domain - Read domain policy.   * ccs_read_domain - Read domain policy.
1635   *   *
1636   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
# Line 1610  static bool ccs_print_entry(struct ccs_i Line 1639  static bool ccs_print_entry(struct ccs_i
1639   */   */
1640  static void ccs_read_domain(struct ccs_io_buffer *head)  static void ccs_read_domain(struct ccs_io_buffer *head)
1641  {  {
1642          struct list_head *dpos;          struct list_head *pos;
         struct list_head *apos;  
1643          if (head->read_eof)          if (head->read_eof)
1644                  return;                  return;
1645          if (head->read_step == 0)          list_for_each_cookie(pos, head->read_var1, &ccs_domain_list) {
1646                  head->read_step = 1;                  struct ccs_domain_info *domain =
1647          list_for_each_cookie(dpos, head->read_var1, &ccs_domain_list) {                          list_entry(pos, struct ccs_domain_info, list);
1648                  struct ccs_domain_info *domain;                  switch (head->read_step) {
1649                  const char *quota_exceeded = "";                          u8 i;
1650                  const char *transition_failed = "";                          const char *w[CCS_MAX_DOMAIN_INFO_FLAGS];
1651                  const char *ignore_global_allow_read = "";                  case 0:
1652                  const char *ignore_global_allow_env = "";                          if (domain->is_deleted && !head->read_single_domain)
1653                  domain = list_entry(dpos, struct ccs_domain_info, list);                                  continue;
1654                  if (head->read_step != 1)                          /* Print domainname and flags. */
1655                          goto acl_loop;                          for (i = 0; i < CCS_MAX_DOMAIN_INFO_FLAGS; i++)
1656                  if (domain->is_deleted && !head->read_single_domain)                                  w[i] = domain->flags[i] ? ccs_dif[i] : "";
1657                          continue;                          if (!ccs_io_printf(head, "%s\n" CCS_KEYWORD_USE_PROFILE
1658                  /* Print domainname and flags. */                                             "%u\n%s%s%s%s%s\n",
1659                  if (domain->quota_warned)                                             domain->domainname->name,
1660                          quota_exceeded = CCS_KEYWORD_QUOTA_EXCEEDED "\n";                                             domain->profile,
1661                  if (domain->domain_transition_failed)                                             w[CCS_DIF_QUOTA_WARNED],
1662                          transition_failed = CCS_KEYWORD_TRANSITION_FAILED "\n";                                             w[CCS_DIF_IGNORE_GLOBAL],
1663                  if (domain->ignore_global_allow_read)                                             w[CCS_DIF_IGNORE_GLOBAL_ALLOW_READ],
1664                          ignore_global_allow_read                                             w[CCS_DIF_IGNORE_GLOBAL_ALLOW_ENV],
1665                                  = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";                                             w[CCS_DIF_TRANSITION_FAILED]))
1666                  if (domain->ignore_global_allow_env)                                  return;
1667                          ignore_global_allow_env                          head->read_step++;
1668                                  = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_ENV "\n";                          /* fall through */
1669                  if (!ccs_io_printf(head, "%s\n" CCS_KEYWORD_USE_PROFILE "%u\n"                  case 1:
1670                                     "%s%s%s%s\n", domain->domainname->name,                          if (!ccs_read_domain2(head, domain))
1671                                     domain->profile, quota_exceeded,                                  return;
1672                                     transition_failed,                          head->read_step++;
1673                                     ignore_global_allow_read,                          /* fall through */
1674                                     ignore_global_allow_env))                  case 2:
1675                          return;                          if (!ccs_io_printf(head, "\n"))
                 head->read_step = 2;  
  acl_loop:  
                 if (head->read_step == 3)  
                         goto tail_mark;  
                 /* Print ACL entries in the domain. */  
                 list_for_each_cookie(apos, head->read_var2,  
                                      &domain->acl_info_list) {  
                         struct ccs_acl_info *ptr  
                                 = list_entry(apos, struct ccs_acl_info, list);  
                         if (!ccs_print_entry(head, ptr))  
1676                                  return;                                  return;
1677                            head->read_step = 0;
1678                            if (head->read_single_domain)
1679                                    goto out;
1680                  }                  }
                 head->read_step = 3;  
  tail_mark:  
                 if (!ccs_io_printf(head, "\n"))  
                         return;  
                 head->read_step = 1;  
                 if (head->read_single_domain)  
                         break;  
1681          }          }
1682     out:
1683          head->read_eof = true;          head->read_eof = true;
1684  }  }
1685    
# Line 1808  static void ccs_read_pid(struct ccs_io_b Line 1823  static void ccs_read_pid(struct ccs_io_b
1823                                (u8) (ccs_flags >> 8));                                (u8) (ccs_flags >> 8));
1824  }  }
1825    
1826    static const char *ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {
1827            [CCS_TRANSITION_CONTROL_INITIALIZE] = CCS_KEYWORD_INITIALIZE_DOMAIN,
1828            [CCS_TRANSITION_CONTROL_NO_INITIALIZE]
1829            = CCS_KEYWORD_NO_INITIALIZE_DOMAIN,
1830            [CCS_TRANSITION_CONTROL_KEEP] = CCS_KEYWORD_KEEP_DOMAIN,
1831            [CCS_TRANSITION_CONTROL_NO_KEEP] = CCS_KEYWORD_NO_KEEP_DOMAIN
1832    };
1833    
1834    static const char *ccs_group_name[CCS_MAX_GROUP] = {
1835            [CCS_PATH_GROUP] = CCS_KEYWORD_PATH_GROUP,
1836            [CCS_NUMBER_GROUP] = CCS_KEYWORD_NUMBER_GROUP,
1837            [CCS_ADDRESS_GROUP] = CCS_KEYWORD_ADDRESS_GROUP
1838    };
1839    
1840  /**  /**
1841   * ccs_write_exception - Write exception policy.   * ccs_write_exception - Write exception policy.
1842   *   *
# Line 1822  static int ccs_write_exception(struct cc Line 1851  static int ccs_write_exception(struct cc
1851          u8 i;          u8 i;
1852          static const struct {          static const struct {
1853                  const char *keyword;                  const char *keyword;
1854                  int (*write) (char *, const bool, const u8);                  int (*write) (char *, const bool);
1855          } ccs_callback[10] = {          } ccs_callback[4] = {
                 { CCS_KEYWORD_NO_KEEP_DOMAIN, ccs_write_domain_keeper },  
                 { CCS_KEYWORD_NO_INITIALIZE_DOMAIN,  
                   ccs_write_domain_initializer },  
                 { CCS_KEYWORD_KEEP_DOMAIN, ccs_write_domain_keeper },  
                 { CCS_KEYWORD_INITIALIZE_DOMAIN,  
                   ccs_write_domain_initializer },  
1856                  { CCS_KEYWORD_AGGREGATOR, ccs_write_aggregator },                  { CCS_KEYWORD_AGGREGATOR, ccs_write_aggregator },
                 { CCS_KEYWORD_ALLOW_READ, ccs_write_global_read },  
                 { CCS_KEYWORD_ALLOW_ENV, ccs_write_global_env },  
1857                  { CCS_KEYWORD_FILE_PATTERN, ccs_write_pattern },                  { CCS_KEYWORD_FILE_PATTERN, ccs_write_pattern },
1858                  { CCS_KEYWORD_DENY_REWRITE, ccs_write_no_rewrite },                  { CCS_KEYWORD_DENY_REWRITE, ccs_write_no_rewrite },
1859                  { CCS_KEYWORD_DENY_AUTOBIND, ccs_write_reserved_port }                  { CCS_KEYWORD_DENY_AUTOBIND, ccs_write_reserved_port }
1860          };          };
1861          static const char *ccs_name[CCS_MAX_GROUP] = {          for (i = 0; i < 4; i++) {
                 [CCS_PATH_GROUP] = CCS_KEYWORD_PATH_GROUP,  
                 [CCS_NUMBER_GROUP] = CCS_KEYWORD_NUMBER_GROUP,  
                 [CCS_ADDRESS_GROUP] = CCS_KEYWORD_ADDRESS_GROUP  
         };  
         for (i = 0; i < 10; i++) {  
1862                  if (ccs_str_starts(&data, ccs_callback[i].keyword))                  if (ccs_str_starts(&data, ccs_callback[i].keyword))
1863                          return ccs_callback[i].write(data, is_delete, i < 2);                          return ccs_callback[i].write(data, is_delete);
1864            }
1865            for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++) {
1866                    if (ccs_str_starts(&data, ccs_transition_type[i]))
1867                            return ccs_write_transition_control(data, is_delete,
1868                                                                i);
1869          }          }
1870          for (i = 0; i < CCS_MAX_GROUP; i++) {          for (i = 0; i < CCS_MAX_GROUP; i++) {
1871                  if (ccs_str_starts(&data, ccs_name[i]))                  if (ccs_str_starts(&data, ccs_group_name[i]))
1872                          return ccs_write_group(data, is_delete, i);                          return ccs_write_group(data, is_delete, i);
1873          }          }
1874          return -EINVAL;          return ccs_write_domain2(data, &ccs_global_domain, is_delete);
1875  }  }
1876    
1877  /**  /**
# Line 1868  static bool ccs_read_group(struct ccs_io Line 1889  static bool ccs_read_group(struct ccs_io
1889          struct list_head *gpos;          struct list_head *gpos;
1890          struct list_head *mpos;          struct list_head *mpos;
1891          const char *w[3] = { "", "", "" };          const char *w[3] = { "", "", "" };
1892          if (idx == CCS_PATH_GROUP)          w[0] = ccs_group_name[idx];
                 w[0] = CCS_KEYWORD_PATH_GROUP;  
         else if (idx == CCS_NUMBER_GROUP)  
                 w[0] = CCS_KEYWORD_NUMBER_GROUP;  
         else if (idx == CCS_ADDRESS_GROUP)  
                 w[0] = CCS_KEYWORD_ADDRESS_GROUP;  
1893          list_for_each_cookie(gpos, head->read_var1, &ccs_group_list[idx]) {          list_for_each_cookie(gpos, head->read_var1, &ccs_group_list[idx]) {
1894                  struct ccs_group *group =                  struct ccs_group *group =
1895                          list_entry(gpos, struct ccs_group, head.list);                          list_entry(gpos, struct ccs_group, head.list);
# Line 1937  static bool ccs_read_policy(struct ccs_i Line 1953  static bool ccs_read_policy(struct ccs_i
1953                  if (acl->is_deleted)                  if (acl->is_deleted)
1954                          continue;                          continue;
1955                  switch (idx) {                  switch (idx) {
1956                  case CCS_ID_DOMAIN_KEEPER:                  case CCS_ID_TRANSITION_CONTROL:
                         {  
                                 struct ccs_domain_keeper *ptr =  
                                         container_of(acl, typeof(*ptr), head);  
                                 w[0] = ptr->is_not ?  
                                         CCS_KEYWORD_NO_KEEP_DOMAIN :  
                                         CCS_KEYWORD_KEEP_DOMAIN;  
                                 if (ptr->program) {  
                                         w[1] = ptr->program->name;  
                                         w[2] = " from ";  
                                 }  
                                 w[3] = ptr->domainname->name;  
                         }  
                         break;  
                 case CCS_ID_DOMAIN_INITIALIZER:  
1957                          {                          {
1958                                  struct ccs_domain_initializer *ptr =                                  struct ccs_transition_control *ptr =
1959                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
1960                                  w[0] = ptr->is_not ?                                  w[0] = ccs_transition_type[ptr->type];
1961                                          CCS_KEYWORD_NO_INITIALIZE_DOMAIN :                                  w[1] = ptr->program ? ptr->program->name
1962                                          CCS_KEYWORD_INITIALIZE_DOMAIN;                                          : "any";
1963                                  w[1] = ptr->program->name;                                  w[2] = " from ";
1964                                  if (ptr->domainname) {                                  w[3] = ptr->domainname ? ptr->domainname->name
1965                                          w[2] = " from ";                                          : "any";
                                         w[3] = ptr->domainname->name;  
                                 }  
1966                          }                          }
1967                          break;                          break;
1968                  case CCS_ID_AGGREGATOR:                  case CCS_ID_AGGREGATOR:
# Line 1975  static bool ccs_read_policy(struct ccs_i Line 1975  static bool ccs_read_policy(struct ccs_i
1975                                  w[3] = ptr->aggregated_name->name;                                  w[3] = ptr->aggregated_name->name;
1976                          }                          }
1977                          break;                          break;
                 case CCS_ID_GLOBAL_READ:  
                         {  
                                 struct ccs_global_read *ptr =  
                                         container_of(acl, typeof(*ptr), head);  
                                 w[0] = CCS_KEYWORD_ALLOW_READ;  
                                 w[1] = ptr->filename->name;  
                         }  
                         break;  
1978                  case CCS_ID_PATTERN:                  case CCS_ID_PATTERN:
1979                          {                          {
1980                                  struct ccs_pattern *ptr =                                  struct ccs_pattern *ptr =
# Line 1999  static bool ccs_read_policy(struct ccs_i Line 1991  static bool ccs_read_policy(struct ccs_i
1991                                  w[1] = ptr->pattern->name;                                  w[1] = ptr->pattern->name;
1992                          }                          }
1993                          break;                          break;
                 case CCS_ID_GLOBAL_ENV:  
                         {  
                                 struct ccs_global_env *ptr =  
                                         container_of(acl, typeof(*ptr), head);  
                                 w[0] = CCS_KEYWORD_ALLOW_ENV;  
                                 w[1] = ptr->env->name;  
                         }  
                         break;  
1994                  case CCS_ID_RESERVEDPORT:                  case CCS_ID_RESERVEDPORT:
1995                          {                          {
1996                                  struct ccs_reserved *ptr =                                  struct ccs_reserved *ptr =
# Line 2021  static bool ccs_read_policy(struct ccs_i Line 2005  static bool ccs_read_policy(struct ccs_i
2005                                  w[1] = buffer;                                  w[1] = buffer;
2006                          }                          }
2007                          break;                          break;
2008                    default:
2009                            continue;
2010                  }                  }
2011                  if (!ccs_io_printf(head, "%s%s%s%s\n", w[0], w[1], w[2], w[3]))                  if (!ccs_io_printf(head, "%s%s%s%s\n", w[0], w[1], w[2], w[3]))
2012                          return false;                          return false;
# Line 2028  static bool ccs_read_policy(struct ccs_i Line 2014  static bool ccs_read_policy(struct ccs_i
2014          return true;          return true;
2015  }  }
2016    
2017    static void ccs_read_global_domain(struct ccs_io_buffer *head)
2018    {
2019            if (!head->read_eof)
2020                    head->read_eof = ccs_read_domain2(head, &ccs_global_domain);
2021    }
2022    
2023  /**  /**
2024   * ccs_read_exception - Read exception policy.   * ccs_read_exception - Read exception policy.
2025   *   *
# Line 2047  static void ccs_read_exception(struct cc Line 2039  static void ccs_read_exception(struct cc
2039          while (head->read_step < CCS_MAX_POLICY + CCS_MAX_GROUP &&          while (head->read_step < CCS_MAX_POLICY + CCS_MAX_GROUP &&
2040                 ccs_read_group(head, head->read_step - CCS_MAX_POLICY))                 ccs_read_group(head, head->read_step - CCS_MAX_POLICY))
2041                  head->read_step++;                  head->read_step++;
2042          head->read_eof = head->read_step == CCS_MAX_POLICY + CCS_MAX_GROUP;          if (head->read_step < CCS_MAX_POLICY + CCS_MAX_GROUP)
2043                    return;
2044            head->read = ccs_read_global_domain;
2045  }  }
2046    
2047  /**  /**
# Line 2103  static bool ccs_get_argv0(struct ccs_exe Line 2097  static bool ccs_get_argv0(struct ccs_exe
2097          return false;          return false;
2098  }  }
2099    
 /**  
  * ccs_get_execute_condition - Get condition part for execute requests.  
  *  
  * @ee: Pointer to "struct ccs_execve".  
  *  
  * Returns pointer to "struct ccs_condition" on success, NULL otherwise.  
  */  
 static struct ccs_condition *ccs_get_execute_condition(struct ccs_execve  
                                                        *ee)  
 {  
         struct ccs_condition *cond;  
         char *buf;  
         int len = 256;  
         char *realpath = NULL;  
         char *argv0 = NULL;  
         const struct ccs_profile *profile = ccs_profile(ccs_current_domain()->  
                                                         profile);  
         if (profile->learning->learning_exec_realpath) {  
                 struct file *file = ee->bprm->file;  
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)  
                 struct path path = { file->f_vfsmnt, file->f_dentry };  
                 realpath = ccs_realpath_from_path(&path);  
 #else  
                 realpath = ccs_realpath_from_path(&file->f_path);  
 #endif  
                 if (realpath)  
                         len += strlen(realpath) + 17;  
         }  
         if (profile->learning->learning_exec_argv0) {  
                 if (ccs_get_argv0(ee)) {  
                         argv0 = ee->tmp;  
                         len += strlen(argv0) + 16;  
                 }  
         }  
         buf = kmalloc(len, CCS_GFP_FLAGS);  
         if (!buf) {  
                 kfree(realpath);  
                 return NULL;  
         }  
         snprintf(buf, len - 1, "if");  
         if (current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER) {  
                 const int pos = strlen(buf);  
                 snprintf(buf + pos, len - pos - 1,  
                          " task.type=execute_handler");  
         }  
         if (realpath) {  
                 const int pos = strlen(buf);  
                 snprintf(buf + pos, len - pos - 1, " exec.realpath=\"%s\"",  
                          realpath);  
                 kfree(realpath);  
         }  
         if (argv0) {  
                 const int pos = strlen(buf);  
                 snprintf(buf + pos, len - pos - 1, " exec.argv[0]=\"%s\"",  
                          argv0);  
         }  
         cond = ccs_get_condition(buf);  
         kfree(buf);  
         return cond;  
 }  
   
 /**  
  * ccs_get_symlink_condition - Get condition part for symlink requests.  
  *  
  * @r: Pointer to "struct ccs_request_info".  
  *  
  * Returns pointer to "struct ccs_condition" on success, NULL otherwise.  
  */  
 static struct ccs_condition *ccs_get_symlink_condition(struct ccs_request_info  
                                                        *r)  
 {  
         struct ccs_condition *cond;  
         char *buf;  
         int len = 256;  
         const char *symlink = NULL;  
         const struct ccs_profile *profile = ccs_profile(r->profile);  
         if (profile->learning->learning_symlink_target) {  
                 symlink = r->obj->symlink_target->name;  
                 len += strlen(symlink) + 18;  
         }  
         buf = kmalloc(len, CCS_GFP_FLAGS);  
         if (!buf)  
                 return NULL;  
         snprintf(buf, len - 1, "if");  
         if (current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER) {  
                 const int pos = strlen(buf);  
                 snprintf(buf + pos, len - pos - 1,  
                          " task.type=execute_handler");  
         }  
         if (symlink) {  
                 const int pos = strlen(buf);  
                 snprintf(buf + pos, len - pos - 1, " symlink.target=\"%s\"",  
                          symlink);  
         }  
         cond = ccs_get_condition(buf);  
         kfree(buf);  
         return cond;  
 }  
   
2100  /* Wait queue for ccs_query_list. */  /* Wait queue for ccs_query_list. */
2101  static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);  static DECLARE_WAIT_QUEUE_HEAD(ccs_query_wait);
2102    
# Line 2224  static LIST_HEAD(ccs_query_list); Line 2119  static LIST_HEAD(ccs_query_list);
2119  /* Number of "struct file" referring /proc/ccs/query interface. */  /* Number of "struct file" referring /proc/ccs/query interface. */
2120  static atomic_t ccs_query_observers = ATOMIC_INIT(0);  static atomic_t ccs_query_observers = ATOMIC_INIT(0);
2121    
2122    static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
2123    {
2124            va_list args;
2125            const int pos = strlen(buffer);
2126            va_start(args, fmt);
2127            vsnprintf(buffer + pos, len - pos - 1, fmt, args);
2128            va_end(args);
2129    }
2130                            
2131  /**  /**
2132   * ccs_supervisor - Ask for the supervisor's decision.   * ccs_supervisor - Ask for the supervisor's decision.
2133   *   *
2134   * @r:       Pointer to "struct ccs_request_info".   * @r:   Pointer to "struct ccs_request_info".
2135   * @fmt:     The printf()'s format string, followed by parameters.   * @fmt: The printf()'s format string, followed by parameters.
2136   *   *
2137   * Returns 0 if the supervisor decided to permit the access request which   * Returns 0 if the supervisor decided to permit the access request which
2138   * violated the policy in enforcing mode, CCS_RETRY_REQUEST if the supervisor   * violated the policy in enforcing mode, CCS_RETRY_REQUEST if the supervisor
# Line 2246  int ccs_supervisor(struct ccs_request_in Line 2150  int ccs_supervisor(struct ccs_request_in
2150          bool quota_exceeded = false;          bool quota_exceeded = false;
2151          char *header;          char *header;
2152          struct ccs_domain_info * const domain = ccs_current_domain();          struct ccs_domain_info * const domain = ccs_current_domain();
2153          switch (r->mode) {          va_start(args, fmt);
2154            len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 80;
2155            va_end(args);
2156            if (r->mode == CCS_CONFIG_LEARNING) {
2157                  char *buffer;                  char *buffer;
2158                  struct ccs_condition *cond;                  char *realpath = NULL;
2159          case CCS_CONFIG_LEARNING:                  char *argv0 = NULL;
2160                    const char *symlink = NULL;
2161                    const struct ccs_preference *pref;
2162                  if (!ccs_domain_quota_ok(r))                  if (!ccs_domain_quota_ok(r))
2163                          return 0;                          return 0;
2164                  va_start(args, fmt);                  pref = ccs_profile(r->profile)->learning;
2165                  len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 4;                  if (r->param_type == CCS_TYPE_PATH_ACL &&
2166                  va_end(args);                      r->param.path.operation == CCS_TYPE_EXECUTE) {
2167                            if (pref->learning_exec_realpath) {
2168                                    struct file *file = r->ee->bprm->file;
2169    #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
2170                                    struct path path = { file->f_vfsmnt,
2171                                                         file->f_dentry };
2172                                    realpath = ccs_realpath_from_path(&path);
2173    #else
2174                                    realpath = ccs_realpath_from_path(&file->
2175                                                                      f_path);
2176    #endif
2177                                    if (realpath)
2178                                            len += strlen(realpath);
2179                            }
2180                            if (pref->learning_exec_argv0) {
2181                                    if (ccs_get_argv0(r->ee)) {
2182                                            argv0 = r->ee->tmp;
2183                                            len += strlen(argv0);
2184                                    }
2185                            }
2186                    }
2187                    if (r->param_type == CCS_TYPE_PATH_ACL &&
2188                        r->param.path.operation == CCS_TYPE_SYMLINK &&
2189                        pref->learning_symlink_target) {
2190                            symlink = r->obj->symlink_target->name;
2191                            len += strlen(symlink);
2192                    }
2193                  buffer = kmalloc(len, CCS_GFP_FLAGS);                  buffer = kmalloc(len, CCS_GFP_FLAGS);
2194                  if (!buffer)                  if (buffer) {
2195                          return 0;                          const bool handler = (current->ccs_flags &
2196                  va_start(args, fmt);                                                CCS_TASK_IS_EXECUTE_HANDLER)
2197                  vsnprintf(buffer, len - 1, fmt, args);                                  != 0;
2198                  va_end(args);                          va_start(args, fmt);
2199                  ccs_normalize_line(buffer);                          vsnprintf(buffer, len - 1, fmt, args);
2200                  if (r->ee && !strncmp(buffer, "allow_execute ", 14))                          va_end(args);
2201                          cond = ccs_get_execute_condition(r->ee);                          if (handler || realpath || argv0 || symlink) {
2202                  else if (r->obj && r->obj->symlink_target)                                  ccs_addprintf(buffer, len, " if");
2203                          cond = ccs_get_symlink_condition(r);                                  if (handler)
2204                  else if ((current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)) {                                          ccs_addprintf(buffer, len, " task.type"
2205                          char str[] = "if task.type=execute_handler";                                                        "=execute_handler");
2206                          cond = ccs_get_condition(str);                                  if (realpath)
2207                  } else                                          ccs_addprintf(buffer, len,
2208                          cond = NULL;                                                        " exec.realpath=\"%s\"",
2209                  ccs_write_domain2(buffer, domain, cond, false);                                                        realpath);
2210                  ccs_put_condition(cond);                                  if (argv0)
2211                  kfree(buffer);                                          ccs_addprintf(buffer, len,
2212                  /* fall through */                                                        " exec.argv[0]=\"%s\"",
2213          case CCS_CONFIG_PERMISSIVE:                                                        argv0);
2214                                    if (symlink)
2215                                            ccs_addprintf(buffer, len,
2216                                                          " symlink.target=\"%s\"",
2217                                                          symlink);
2218                            }
2219                            ccs_normalize_line(buffer);
2220                            ccs_write_domain2(buffer, domain, false);
2221                            kfree(buffer);
2222                    }
2223                    kfree(realpath);
2224                  return 0;                  return 0;
2225          }          }
2226            if (r->mode != CCS_CONFIG_ENFORCING)
2227                    return 0;
2228          if (!atomic_read(&ccs_query_observers)) {          if (!atomic_read(&ccs_query_observers)) {
2229                  int i;                  int i;
2230                  if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)                  if (current->ccs_flags & CCS_DONT_SLEEP_ON_ENFORCE_ERROR)
# Line 2289  int ccs_supervisor(struct ccs_request_in Line 2236  int ccs_supervisor(struct ccs_request_in
2236                  }                  }
2237                  return -EPERM;                  return -EPERM;
2238          }          }
2239          va_start(args, fmt);          header = ccs_init_log(&len, r);
         len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32;  
         va_end(args);  
         header = ccs_init_audit_log(&len, r);  
2240          if (!header)          if (!header)
2241                  goto out;                  goto out;
2242          ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), CCS_GFP_FLAGS);          ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), CCS_GFP_FLAGS);
# Line 2314  int ccs_supervisor(struct ccs_request_in Line 2258  int ccs_supervisor(struct ccs_request_in
2258          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
2259          if (quota_exceeded)          if (quota_exceeded)
2260                  goto out;                  goto out;
2261          pos = snprintf(ccs_query_entry->query, len - 1, "Q%u-%hu\n%s",          snprintf(ccs_query_entry->query, len - 1, "Q%u-%hu\n%s",
2262                         ccs_query_entry->serial, r->retry, header);                   ccs_query_entry->serial, r->retry, header);
2263          kfree(header);          kfree(header);
2264          header = NULL;          header = NULL;
2265          va_start(args, fmt);          ccs_addprintf(ccs_query_entry->query, len, fmt, args);
         vsnprintf(ccs_query_entry->query + pos, len - 1 - pos, fmt, args);  
2266          ccs_query_entry->query_len = strlen(ccs_query_entry->query) + 1;          ccs_query_entry->query_len = strlen(ccs_query_entry->query) + 1;
         va_end(args);  
2267          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2268          list_add_tail(&ccs_query_entry->list, &ccs_query_list);          list_add_tail(&ccs_query_entry->list, &ccs_query_list);
2269          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
# Line 2556  int ccs_open_control(const u8 type, stru Line 2498  int ccs_open_control(const u8 type, stru
2498  #ifdef CONFIG_CCSECURITY_AUDIT  #ifdef CONFIG_CCSECURITY_AUDIT
2499          case CCS_GRANTLOG: /* /proc/ccs/grant_log */          case CCS_GRANTLOG: /* /proc/ccs/grant_log */
2500          case CCS_REJECTLOG: /* /proc/ccs/reject_log */          case CCS_REJECTLOG: /* /proc/ccs/reject_log */
2501                  head->poll = ccs_poll_audit_log;                  head->poll = ccs_poll_log;
2502                  head->read = ccs_read_audit_log;                  head->read = ccs_read_log;
2503                  break;                  break;
2504  #endif  #endif
2505          case CCS_SELFDOMAIN: /* /proc/ccs/self_domain */          case CCS_SELFDOMAIN: /* /proc/ccs/self_domain */

Legend:
Removed from v.3693  
changed lines
  Added in v.3752

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