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

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 3772 by kumaneko, Mon Jun 21 06:05:52 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 *name, const char *value,
363                             const bool use_default, struct ccs_profile *profile)
364    {
365            struct ccs_preference **pref;
366            bool *verbose;
367            if (!strcmp(name, "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, value,
375                  if (cp2)                               "max_grant_log");
376                          sscanf(cp2 + 14, "%u",                  ccs_set_uint(&profile->preference.audit_max_reject_log, value,
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, value,
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, value,
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(name, "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, value,
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(name, "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(name, "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, value,
412                          profile->preference.learning_verbose = value;                               "max_entry");
413                  cp2 = strstr(cp, "max_entry=");                  ccs_set_bool(&profile->preference.learning_exec_realpath,
414                  if (cp2)                               value, "exec.realpath");
415                          sscanf(cp2 + 10, "%u",                  ccs_set_bool(&profile->preference.learning_exec_argv0, value,
416                                 &profile->preference.learning_max_entry);                               "exec.argv0");
417                  if (strstr(cp, "exec.realpath=yes"))                  ccs_set_bool(&profile->preference.learning_symlink_target,
418                          profile->preference.learning_exec_realpath = true;                               value, "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, value, "verbose");
428                          profile->preference.learning_symlink_target = false;  }
429                  return 0;  
430          }  static int ccs_set_mode(char *name, const char *value, const bool use_default,
431          if (profile == &ccs_default_profile)                          struct ccs_profile *profile)
432                  return -EINVAL;  {
433          if (!strcmp(data, "COMMENT")) {          u8 i;
434                  const struct ccs_path_info *old_comment = profile->comment;          u8 config;
435                  profile->comment = ccs_get_name(cp);          if (!strcmp(name, "CONFIG")) {
                 ccs_put_name(old_comment);  
                 return 0;  
         }  
         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;
438                  config = profile->default_config;                  config = profile->default_config;
439          } else if (ccs_str_starts(&data, "CONFIG::")) {          } else if (ccs_str_starts(&name, "CONFIG::")) {
440                  config = 0;                  config = 0;
441                  for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX                  for (i = 0; i < CCS_MAX_MAC_INDEX + CCS_MAX_CAPABILITY_INDEX
442                               + CCS_MAX_MAC_CATEGORY_INDEX; i++) {                               + CCS_MAX_MAC_CATEGORY_INDEX; i++) {
443                          if (strcmp(data, ccs_mac_keywords[i]))                          if (strcmp(name, ccs_mac_keywords[i]))
444                                  continue;                                  continue;
445                          config = profile->config[i];                          config = profile->config[i];
446                          break;                          break;
# 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(value, 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(value, "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(value, "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(data, cp, use_default, profile);
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(data, cp, use_default, profile);
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);
717          if (!e.manager)          if (!e.manager)
718                  return error;                  return error;
719          error = ccs_update_policy(&e.head, sizeof(e), is_delete,          error = ccs_update_policy(&e.head, sizeof(e), is_delete,
720                                    CCS_ID_MANAGER, ccs_same_manager_entry);                                    &ccs_policy_list[CCS_ID_MANAGER],
721                                      ccs_same_manager_entry);
722          ccs_put_name(e.manager);          ccs_put_name(e.manager);
723          return error;          return error;
724  }  }
# Line 753  static bool ccs_manager(void) Line 787  static bool ccs_manager(void)
787                  return true;                  return true;
788          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))
789                  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;  
                 }  
         }  
790          exe = ccs_get_exe();          exe = ccs_get_exe();
         if (!exe)  
                 return false;  
791          list_for_each_entry_rcu(ptr, &ccs_policy_list[CCS_ID_MANAGER],          list_for_each_entry_rcu(ptr, &ccs_policy_list[CCS_ID_MANAGER],
792                                  head.list) {                                  head.list) {
793                  if (!ptr->head.is_deleted && !ptr->is_domain                  if (ptr->head.is_deleted)
794                      && !strcmp(exe, ptr->manager->name)) {                          continue;
795                          found = true;                  if (ptr->is_domain) {
796                          /* Set manager flag. */                          if (ccs_pathcmp(domainname, ptr->manager))
797                          task->ccs_flags |= CCS_TASK_IS_MANAGER;                                  continue;
798                          break;                  } else {
799                            if (!exe || strcmp(exe, ptr->manager->name))
800                                    continue;
801                  }                  }
802                    /* Set manager flag. */
803                    task->ccs_flags |= CCS_TASK_IS_MANAGER;
804                    found = true;
805                    break;
806          }          }
807          if (!found) { /* Reduce error messages. */          if (!found) { /* Reduce error messages. */
808                  static pid_t ccs_last_pid;                  static pid_t ccs_last_pid;
# Line 799  static bool ccs_manager(void) Line 828  static bool ccs_manager(void)
828  static char *ccs_find_condition_part(char *data)  static char *ccs_find_condition_part(char *data)
829  {  {
830          char *cp = strstr(data, " if ");          char *cp = strstr(data, " if ");
831          if (cp) {          if (!cp)
                 while (1) {  
                         char *cp2 = strstr(cp + 3, " if ");  
                         if (!cp2)  
                                 break;  
                         cp = cp2;  
                 }  
                 *cp++ = '\0';  
         } else {  
832                  cp = strstr(data, " ; set ");                  cp = strstr(data, " ; set ");
833                  if (cp)          if (cp)
834                          *cp++ = '\0';                  *cp++ = '\0';
         }  
835          return cp;          return cp;
836  }  }
837    
# Line 860  static bool ccs_select_one(struct ccs_io Line 880  static bool ccs_select_one(struct ccs_io
880          if (!head->read_buf)          if (!head->read_buf)
881                  return true; /* Do nothing if open(O_WRONLY). */                  return true; /* Do nothing if open(O_WRONLY). */
882          head->read_avail = 0;          head->read_avail = 0;
883            head->read_cond = false;
884          ccs_io_printf(head, "# select %s\n", data);          ccs_io_printf(head, "# select %s\n", data);
885          head->read_single_domain = true;          head->read_single_domain = true;
886          head->read_eof = !domain;          head->read_eof = !domain;
887          if (domain) {          head->read_var1 = domain;
888                  struct ccs_domain_info *d;          head->read_var2 = NULL;
889                  head->read_var1 = NULL;          head->read_bit = 0;
890                  list_for_each_entry_rcu(d, &ccs_domain_list, list) {          head->read_step = 0;
891                          if (d == domain)          if (domain && domain->is_deleted)
892                                  break;                  ccs_io_printf(head, "# This is a deleted domain.\n");
                         head->read_var1 = &d->list;  
                 }  
                 head->read_var2 = NULL;  
                 head->read_bit = 0;  
                 head->read_step = 0;  
                 if (domain->is_deleted)  
                         ccs_io_printf(head, "# This is a deleted domain.\n");  
         }  
893          return true;          return true;
894  }  }
895    
896  static int ccs_write_domain2(char *data, struct ccs_domain_info *domain,  static int ccs_write_domain2(char *data, struct ccs_domain_info *domain,
897                               struct ccs_condition *cond, const bool is_delete)                               const bool is_delete)
898  {  {
         u8 i;  
899          static const struct {          static const struct {
900                  const char *keyword;                  const char *keyword;
901                  int (*write) (char *, struct ccs_domain_info *,                  int (*write) (char *, struct ccs_domain_info *,
# Line 897  static int ccs_write_domain2(char *data, Line 909  static int ccs_write_domain2(char *data,
909          };          };
910          int (*write) (char *, struct ccs_domain_info *, struct ccs_condition *,          int (*write) (char *, struct ccs_domain_info *, struct ccs_condition *,
911                        const bool) = ccs_write_file;                        const bool) = ccs_write_file;
912            int error;
913            u8 i;
914            struct ccs_condition *cond = NULL;
915            char *cp = ccs_find_condition_part(data);
916            if (cp) {
917                    cond = ccs_get_condition(cp);
918                    if (!cond)
919                            return -EINVAL;
920            }
921          for (i = 0; i < 5; i++) {          for (i = 0; i < 5; i++) {
922                  if (!ccs_str_starts(&data, ccs_callback[i].keyword))                  if (!ccs_str_starts(&data, ccs_callback[i].keyword))
923                          continue;                          continue;
924                  write = ccs_callback[i].write;                  write = ccs_callback[i].write;
925                  break;                  break;
926          }          }
927          return write(data, domain, cond, is_delete);          error = write(data, domain, cond, is_delete);
928            if (cond)
929                    ccs_put_condition(cond);
930            return error;
931  }  }
932    
933    static const char *ccs_dif[CCS_MAX_DOMAIN_INFO_FLAGS] = {
934            [CCS_DIF_QUOTA_WARNED] = CCS_KEYWORD_QUOTA_EXCEEDED "\n",
935            [CCS_DIF_IGNORE_GLOBAL] = CCS_KEYWORD_IGNORE_GLOBAL "\n",
936            [CCS_DIF_IGNORE_GLOBAL_ALLOW_READ]
937            = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n",
938            [CCS_DIF_IGNORE_GLOBAL_ALLOW_ENV]
939            = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_ENV "\n",
940            [CCS_DIF_TRANSITION_FAILED] = CCS_KEYWORD_TRANSITION_FAILED "\n"
941    };
942            
943  /**  /**
944   * ccs_write_domain - Write domain policy.   * ccs_write_domain - Write domain policy.
945   *   *
# Line 920  static int ccs_write_domain(struct ccs_i Line 954  static int ccs_write_domain(struct ccs_i
954          bool is_delete = false;          bool is_delete = false;
955          bool is_select = false;          bool is_select = false;
956          unsigned int profile;          unsigned int profile;
         struct ccs_condition *cond = NULL;  
         char *cp;  
         int error;  
957          if (ccs_str_starts(&data, CCS_KEYWORD_DELETE))          if (ccs_str_starts(&data, CCS_KEYWORD_DELETE))
958                  is_delete = true;                  is_delete = true;
959          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 970  static int ccs_write_domain(struct ccs_i
970                  else if (is_select)                  else if (is_select)
971                          domain = ccs_find_domain(data);                          domain = ccs_find_domain(data);
972                  else                  else
973                          domain = ccs_find_or_assign_new_domain(data, 0);                          domain = ccs_assign_domain(data, 0);
974                  head->write_var1 = domain;                  head->write_var1 = domain;
975                  return 0;                  return 0;
976          }          }
# Line 952  static int ccs_write_domain(struct ccs_i Line 983  static int ccs_write_domain(struct ccs_i
983                          domain->profile = (u8) profile;                          domain->profile = (u8) profile;
984                  return 0;                  return 0;
985          }          }
986          if (!strcmp(data, CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {          for (profile = 0; profile < CCS_MAX_DOMAIN_INFO_FLAGS; profile++) {
987                  domain->ignore_global_allow_read = !is_delete;                  const char *cp = ccs_dif[profile];
988                  return 0;                  if (strncmp(data, cp, strlen(cp) - 1))
989          }                          continue;
990          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;  
991                  return 0;                  return 0;
992          }          }
993          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;  
994  }  }
995    
996  /**  /**
# Line 1082  static bool ccs_print_number_union_commo Line 1095  static bool ccs_print_number_union_commo
1095   *   *
1096   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1097   */   */
1098  bool ccs_print_number_union(struct ccs_io_buffer *head,  static bool ccs_print_number_union(struct ccs_io_buffer *head,
1099                              const struct ccs_number_union *ptr)                                     const struct ccs_number_union *ptr)
1100  {  {
1101          return ccs_print_number_union_common(head, ptr, true);          return ccs_print_number_union_common(head, ptr, true);
1102  }  }
# Line 1106  static bool ccs_print_number_union_nospa Line 1119  static bool ccs_print_number_union_nospa
1119   * ccs_print_condition - Print condition part.   * ccs_print_condition - Print condition part.
1120   *   *
1121   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1122   * @cond: Pointer to "struct ccs_condition". May be NULL.   * @cond: Pointer to "struct ccs_condition". Maybe NULL.
1123   *   *
1124   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1125   */   */
# Line 1206  static bool ccs_print_condition(struct c Line 1219  static bool ccs_print_condition(struct c
1219                                     cond->post_state[j]))                                     cond->post_state[j]))
1220                          goto out;                          goto out;
1221          }          }
1222            if (i & (1 << 4)) {
1223                    if (!ccs_io_printf(head, " audit=%s",
1224                                       ccs_yesno(cond->post_state[4])))
1225                            goto out;
1226            }
1227   no_condition:   no_condition:
1228          if (ccs_io_printf(head, "\n"))          if (ccs_io_printf(head, "\n"))
1229                  return true;                  return true;
# Line 1214  static bool ccs_print_condition(struct c Line 1232  static bool ccs_print_condition(struct c
1232  }  }
1233    
1234  /**  /**
1235   * ccs_print_path_acl - Print a path ACL entry.   * ccs_print_entry - Print an ACL entry.
1236   *   *
1237   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1238   * @ptr:  Pointer to "struct ccs_path_acl".   * @ptr:  Pointer to an ACL entry.
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
1239   *   *
1240   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1241   */   */
1242  static bool ccs_print_path_acl(struct ccs_io_buffer *head,  static bool ccs_print_entry(struct ccs_io_buffer *head,
1243                                 struct ccs_path_acl *ptr,                              const struct ccs_acl_info *acl)
                                const struct ccs_condition *cond)  
1244  {  {
1245          int pos;          int pos;
1246          u8 bit;          const u8 acl_type = acl->type;
1247          const u16 perm = ptr->perm;          u8 bit = head->read_bit;
1248          for (bit = head->read_bit; bit < CCS_MAX_PATH_OPERATION; bit++) {          if (head->read_cond)
1249                  if (!(perm & (1 << bit)))                  goto print_cond;
1250                          continue;          if (acl->is_deleted)
1251                  if (head->read_execute_only && bit != CCS_TYPE_EXECUTE                  return true;
1252                      && bit != CCS_TYPE_TRANSIT)   next:
1253                          continue;          pos = head->read_avail;
1254                  /* Print "read/write" instead of "read" and "write". */          if (acl_type == CCS_TYPE_PATH_ACL) {
1255                  if ((bit == CCS_TYPE_READ || bit == CCS_TYPE_WRITE)                  struct ccs_path_acl *ptr
1256                      && (perm & (1 << CCS_TYPE_READ_WRITE)))                          = container_of(acl, typeof(*ptr), head);
1257                          continue;                  const u16 perm = ptr->perm;
1258                  pos = head->read_avail;                  for ( ; bit < CCS_MAX_PATH_OPERATION; bit++) {
1259                  if (!ccs_io_printf(head, "allow_%s", ccs_path2keyword(bit)) ||                          if (!(perm & (1 << bit)))
1260                      !ccs_print_name_union(head, &ptr->name) ||                                  continue;
1261                      !ccs_print_condition(head, cond)) {                          if (head->read_execute_only && bit != CCS_TYPE_EXECUTE
1262                          head->read_bit = bit;                              && bit != CCS_TYPE_TRANSIT)
1263                          head->read_avail = pos;                                  continue;
1264                          return false;                          /* Print "read/write" instead of "read" and "write". */
1265                            if ((bit == CCS_TYPE_READ || bit == CCS_TYPE_WRITE)
1266                                && (perm & (1 << CCS_TYPE_READ_WRITE)))
1267                                    continue;
1268                            break;
1269                  }                  }
1270          }                  if (bit == CCS_MAX_PATH_OPERATION)
1271          head->read_bit = 0;                          goto done;
1272          return true;                  if (!ccs_io_printf(head, "allow_%s", ccs_path_keyword[bit]) ||
1273  }                      !ccs_print_name_union(head, &ptr->name))
1274                            goto fail;
1275  /**          } else if (acl_type == CCS_TYPE_EXECUTE_HANDLER ||
1276   * ccs_print_path_number3_acl - Print a path_number3 ACL entry.                     acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {
1277   *                  struct ccs_execute_handler *ptr
1278   * @head: Pointer to "struct ccs_io_buffer".                          = container_of(acl, typeof(*ptr), head);
1279   * @ptr:  Pointer to "struct ccs_path_number3_acl".                  if (!ccs_io_printf(head, "%s %s",
1280   * @cond: Pointer to "struct ccs_condition". May be NULL.                                     acl_type == CCS_TYPE_EXECUTE_HANDLER ?
1281   *                                     CCS_KEYWORD_EXECUTE_HANDLER :
1282   * Returns true on success, false otherwise.                                     CCS_KEYWORD_DENIED_EXECUTE_HANDLER,
1283   */                                     ptr->handler->name))
1284  static bool ccs_print_path_number3_acl(struct ccs_io_buffer *head,                          goto fail;
1285                                         struct ccs_path_number3_acl *ptr,          } if (head->read_execute_only) {
1286                                         const struct ccs_condition *cond)                  return true;
1287  {          } else if (acl_type == CCS_TYPE_MKDEV_ACL) {
1288          int pos;                  struct ccs_mkdev_acl *ptr
1289          u8 bit;                          = container_of(acl, typeof(*ptr), head);
1290          const u16 perm = ptr->perm;                  const u8 perm = ptr->perm;
1291          for (bit = head->read_bit; bit < CCS_MAX_PATH_NUMBER3_OPERATION;                  for ( ; bit < CCS_MAX_MKDEV_OPERATION; bit++) {
1292               bit++) {                          if (!(perm & (1 << bit)))
1293                  if (!(perm & (1 << bit)))                                  continue;
1294                          continue;                          break;
1295                  pos = head->read_avail;                  }
1296                  if (!ccs_io_printf(head, "allow_%s",                  if (bit == CCS_MAX_MKDEV_OPERATION)
1297                                     ccs_path_number32keyword(bit)) ||                          goto done;
1298                    if (!ccs_io_printf(head, "allow_%s", ccs_mkdev_keyword[bit]) ||
1299                      !ccs_print_name_union(head, &ptr->name) ||                      !ccs_print_name_union(head, &ptr->name) ||
1300                      !ccs_print_number_union(head, &ptr->mode) ||                      !ccs_print_number_union(head, &ptr->mode) ||
1301                      !ccs_print_number_union(head, &ptr->major) ||                      !ccs_print_number_union(head, &ptr->major) ||
1302                      !ccs_print_number_union(head, &ptr->minor) ||                      !ccs_print_number_union(head, &ptr->minor))
1303                      !ccs_print_condition(head, cond)) {                          goto fail;
1304                          head->read_bit = bit;          } else if (acl_type == CCS_TYPE_PATH2_ACL) {
1305                          head->read_avail = pos;                  struct ccs_path2_acl *ptr
1306                          return false;                          = container_of(acl, typeof(*ptr), head);
1307                    const u8 perm = ptr->perm;
1308                    for ( ; bit < CCS_MAX_PATH2_OPERATION; bit++) {
1309                            if (!(perm & (1 << bit)))
1310                                    continue;
1311                            break;
1312                  }                  }
1313          }                  if (bit == CCS_MAX_PATH2_OPERATION)
1314          head->read_bit = 0;                          goto done;
1315          return true;                  if (!ccs_io_printf(head, "allow_%s", ccs_path2_keyword[bit]) ||
 }  
   
 /**  
  * ccs_print_path2_acl - Print a path2 ACL entry.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  * @ptr:  Pointer to "struct ccs_path2_acl".  
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
  *  
  * Returns true on success, false otherwise.  
  */  
 static bool ccs_print_path2_acl(struct ccs_io_buffer *head,  
                                 struct ccs_path2_acl *ptr,  
                                 const struct ccs_condition *cond)  
 {  
         int pos;  
         u8 bit;  
         const u8 perm = ptr->perm;  
         for (bit = head->read_bit; bit < CCS_MAX_PATH2_OPERATION; bit++) {  
                 if (!(perm & (1 << bit)))  
                         continue;  
                 pos = head->read_avail;  
                 if (!ccs_io_printf(head, "allow_%s",  
                                    ccs_path22keyword(bit)) ||  
1316                      !ccs_print_name_union(head, &ptr->name1) ||                      !ccs_print_name_union(head, &ptr->name1) ||
1317                      !ccs_print_name_union(head, &ptr->name2) ||                      !ccs_print_name_union(head, &ptr->name2))
1318                      !ccs_print_condition(head, cond)) {                          goto fail;
1319                          head->read_bit = bit;          } else if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {
1320                          head->read_avail = pos;                  struct ccs_path_number_acl *ptr
1321                          return false;                          = container_of(acl, typeof(*ptr), head);
1322                    const u8 perm = ptr->perm;
1323                    for ( ; bit < CCS_MAX_PATH_NUMBER_OPERATION; bit++) {
1324                            if (!(perm & (1 << bit)))
1325                                    continue;
1326                            break;
1327                  }                  }
1328          }                  if (bit == CCS_MAX_PATH_NUMBER_OPERATION)
1329          head->read_bit = 0;                          goto done;
         return true;  
 }  
   
 /**  
  * ccs_print_path_number_acl - Print a path_number ACL entry.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  * @ptr:  Pointer to "struct ccs_path_number_acl".  
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
  *  
  * Returns true on success, false otherwise.  
  */  
 static bool ccs_print_path_number_acl(struct ccs_io_buffer *head,  
                                       struct ccs_path_number_acl *ptr,  
                                       const struct ccs_condition *cond)  
 {  
         int pos;  
         u8 bit;  
         const u8 perm = ptr->perm;  
         for (bit = head->read_bit; bit < CCS_MAX_PATH_NUMBER_OPERATION;  
              bit++) {  
                 if (!(perm & (1 << bit)))  
                         continue;  
                 pos = head->read_avail;  
1330                  if (!ccs_io_printf(head, "allow_%s",                  if (!ccs_io_printf(head, "allow_%s",
1331                                     ccs_path_number2keyword(bit)) ||                                     ccs_path_number_keyword[bit]) ||
1332                      !ccs_print_name_union(head, &ptr->name) ||                      !ccs_print_name_union(head, &ptr->name) ||
1333                      !ccs_print_number_union(head, &ptr->number) ||                      !ccs_print_number_union(head, &ptr->number))
1334                      !ccs_print_condition(head, cond)) {                          goto fail;
1335                          head->read_bit = bit;          } else if (acl_type == CCS_TYPE_ENV_ACL) {
1336                          head->read_avail = pos;                  struct ccs_env_acl *ptr
1337                          return false;                          = container_of(acl, typeof(*ptr), head);
1338                    if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_ENV "%s",
1339                                       ptr->env->name))
1340                            goto fail;
1341            } else if (acl_type == CCS_TYPE_CAPABILITY_ACL) {
1342                    struct ccs_capability_acl *ptr
1343                            = container_of(acl, typeof(*ptr), head);
1344                    if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CAPABILITY "%s",
1345                                       ccs_cap2keyword(ptr->operation)))
1346                            goto fail;
1347            } else if (acl_type == CCS_TYPE_IP_NETWORK_ACL) {
1348                    struct ccs_ip_network_acl *ptr
1349                            = container_of(acl, typeof(*ptr), head);
1350                    char buf[128];
1351                    const char *w[2] = { buf, "" };
1352                    const u8 perm = ptr->perm;
1353                    for ( ; bit < CCS_MAX_NETWORK_OPERATION; bit++) {
1354                            if (!(perm & (1 << bit)))
1355                                    continue;
1356                            break;
1357                  }                  }
1358          }                  if (bit == CCS_MAX_NETWORK_OPERATION)
1359          head->read_bit = 0;                          goto done;
         return true;  
 }  
   
 /**  
  * ccs_print_env_acl - Print an evironment variable name's ACL entry.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  * @ptr:  Pointer to "struct ccs_env_acl".  
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
  *  
  * Returns true on success, false otherwise.  
  */  
 static bool ccs_print_env_acl(struct ccs_io_buffer *head,  
                               struct ccs_env_acl *ptr,  
                               const struct ccs_condition *cond)  
 {  
         const int pos = head->read_avail;  
         if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_ENV "%s", ptr->env->name) ||  
             !ccs_print_condition(head, cond)) {  
                 head->read_avail = pos;  
                 return false;  
         }  
         return true;  
 }  
   
 /**  
  * ccs_print_capability_acl - Print a capability ACL entry.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  * @ptr:  Pointer to "struct ccs_capability_acl".  
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
  *  
  * Returns true on success, false otherwise.  
  */  
 static bool ccs_print_capability_acl(struct ccs_io_buffer *head,  
                                      struct ccs_capability_acl *ptr,  
                                      const struct ccs_condition *cond)  
 {  
         const int pos = head->read_avail;  
         if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_CAPABILITY "%s",  
                            ccs_cap2keyword(ptr->operation)) ||  
             !ccs_print_condition(head, cond)) {  
                 head->read_avail = pos;  
                 return false;  
         }  
         return true;  
 }  
   
 /**  
  * ccs_print_network_acl - Print a network ACL entry.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  * @ptr:  Pointer to "struct ccs_ip_network_acl".  
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
  *  
  * Returns true on success, false otherwise.  
  */  
 static bool ccs_print_network_acl(struct ccs_io_buffer *head,  
                                   struct ccs_ip_network_acl *ptr,  
                                   const struct ccs_condition *cond)  
 {  
         int pos;  
         u8 bit;  
         const u16 perm = ptr->perm;  
         char buf[128];  
         for (bit = head->read_bit; bit < CCS_MAX_NETWORK_OPERATION; bit++) {  
                 const char *w[2] = { "", "" };  
                 if (!(perm & (1 << bit)))  
                         continue;  
                 pos = head->read_avail;  
1360                  switch (ptr->address_type) {                  switch (ptr->address_type) {
1361                  case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP:                  case CCS_IP_ADDRESS_TYPE_ADDRESS_GROUP:
1362                          w[0] = "@";                          w[0] = "@";
# Line 1433  static bool ccs_print_network_acl(struct Line 1365  static bool ccs_print_network_acl(struct
1365                  case CCS_IP_ADDRESS_TYPE_IPv4:                  case CCS_IP_ADDRESS_TYPE_IPv4:
1366                          ccs_print_ipv4(buf, sizeof(buf), ptr->address.ipv4.min,                          ccs_print_ipv4(buf, sizeof(buf), ptr->address.ipv4.min,
1367                                         ptr->address.ipv4.max);                                         ptr->address.ipv4.max);
                         w[0] = buf;  
1368                          break;                          break;
1369                  case CCS_IP_ADDRESS_TYPE_IPv6:                  case CCS_IP_ADDRESS_TYPE_IPv6:
1370                          ccs_print_ipv6(buf, sizeof(buf), ptr->address.ipv6.min,                          ccs_print_ipv6(buf, sizeof(buf), ptr->address.ipv6.min,
1371                                         ptr->address.ipv6.max);                                         ptr->address.ipv6.max);
                         w[0] = buf;  
1372                          break;                          break;
1373                  }                  }
1374                  if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s %s%s",                  if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_NETWORK "%s %s%s",
1375                                     ccs_net2keyword(bit), w[0], w[1]) ||                                     ccs_net_keyword[bit], w[0], w[1]) ||
1376                      !ccs_print_number_union(head, &ptr->port) ||                      !ccs_print_number_union(head, &ptr->port))
1377                      !ccs_print_condition(head, cond))                          goto fail;
1378                          goto out;          } else if (acl_type == CCS_TYPE_SIGNAL_ACL) {
1379                    struct ccs_signal_acl *ptr
1380                            = container_of(acl, typeof(*ptr), head);
1381                    if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_SIGNAL "%u %s",
1382                                       ptr->sig, ptr->domainname->name))
1383                            goto fail;
1384            } else if (acl_type == CCS_TYPE_MOUNT_ACL) {
1385                    struct ccs_mount_acl *ptr
1386                            = container_of(acl, typeof(*ptr), head);
1387                    if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_MOUNT) ||
1388                        !ccs_print_name_union(head, &ptr->dev_name) ||
1389                        !ccs_print_name_union(head, &ptr->dir_name) ||
1390                        !ccs_print_name_union(head, &ptr->fs_type) ||
1391                        !ccs_print_number_union(head, &ptr->flags))
1392                            goto fail;
1393          }          }
         head->read_bit = 0;  
         return true;  
  out:  
1394          head->read_bit = bit;          head->read_bit = bit;
1395          head->read_avail = pos;          head->read_cond = true;
1396          return false;   print_cond:
1397  }          pos = head->read_avail;
1398            if (!ccs_print_condition(head, acl->cond)) {
 /**  
  * ccs_print_signal_acl - Print a signal ACL entry.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  * @ptr:  Pointer to "struct signale_acl".  
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
  *  
  * Returns true on success, false otherwise.  
  */  
 static bool ccs_print_signal_acl(struct ccs_io_buffer *head,  
                                  struct ccs_signal_acl *ptr,  
                                  const struct ccs_condition *cond)  
 {  
         const int pos = head->read_avail;  
         if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_SIGNAL "%u %s",  
                            ptr->sig, ptr->domainname->name) ||  
             !ccs_print_condition(head, cond)) {  
1399                  head->read_avail = pos;                  head->read_avail = pos;
1400                  return false;                  return false;
1401          }          }
1402            head->read_cond = false;
1403            switch (acl_type) {
1404            case CCS_TYPE_PATH_ACL:
1405            case CCS_TYPE_MKDEV_ACL:
1406            case CCS_TYPE_PATH2_ACL:
1407            case CCS_TYPE_PATH_NUMBER_ACL:
1408            case CCS_TYPE_IP_NETWORK_ACL:
1409                    bit++;
1410                    goto next;
1411            }
1412     done:
1413            head->read_bit = 0;
1414          return true;          return true;
1415     fail:
1416            head->read_bit = bit;
1417            head->read_avail = pos;
1418            return false;
1419  }  }
1420    
1421  /**  /**
1422   * ccs_print_execute_handler_record - Print an execute handler ACL entry.   * ccs_read_domain2 - Read domain policy.
1423   *   *
1424   * @head:    Pointer to "struct ccs_io_buffer".   * @head:   Pointer to "struct ccs_io_buffer".
1425   * @keyword: Name of the keyword.   * @domain: Pointer to "struct ccs_domain_info".
  * @ptr:     Pointer to "struct ccs_execute_handler_record".  
1426   *   *
1427   * Returns true on success, false otherwise.   * Caller holds ccs_read_lock().
  */  
 static bool ccs_print_execute_handler_record(struct ccs_io_buffer *head,  
                                              const char *keyword,  
                                              struct ccs_execute_handler_record  
                                              *ptr)  
 {  
         return ccs_io_printf(head, "%s %s\n", keyword, ptr->handler->name);  
 }  
   
 /**  
  * ccs_print_mount_acl - Print a mount ACL entry.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  * @ptr:  Pointer to "struct ccs_mount_acl".  
  * @cond: Pointer to "struct ccs_condition". May be NULL.  
1428   *   *
1429   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1430   */   */
1431  static bool ccs_print_mount_acl(struct ccs_io_buffer *head,  static bool ccs_read_domain2(struct ccs_io_buffer *head,
1432                                  struct ccs_mount_acl *ptr,                               struct ccs_domain_info *domain)
                                 const struct ccs_condition *cond)  
1433  {  {
1434          const int pos = head->read_avail;          struct list_head *pos;
1435          if (!ccs_io_printf(head, CCS_KEYWORD_ALLOW_MOUNT) ||          /* Print ACL entries in the domain. */
1436              !ccs_print_name_union(head, &ptr->dev_name) ||          list_for_each_cookie(pos, head->read_var2, &domain->acl_info_list) {
1437              !ccs_print_name_union(head, &ptr->dir_name) ||                  struct ccs_acl_info *ptr
1438              !ccs_print_name_union(head, &ptr->fs_type) ||                          = list_entry(pos, struct ccs_acl_info, list);
1439              !ccs_print_number_union(head, &ptr->flags) ||                  if (!ccs_print_entry(head, ptr))
1440              !ccs_print_condition(head, cond)) {                          return false;
                 head->read_avail = pos;  
                 return false;  
1441          }          }
1442          return true;          return true;
1443  }  }
1444    
1445  /**  /**
  * ccs_print_entry - Print an ACL entry.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  * @ptr:  Pointer to an ACL entry.  
  *  
  * Returns true on success, false otherwise.  
  */  
 static bool ccs_print_entry(struct ccs_io_buffer *head,  
                             struct ccs_acl_info *ptr)  
 {  
         const struct ccs_condition *cond = ptr->cond;  
         const u8 acl_type = ptr->type;  
         if (ptr->is_deleted)  
                 return true;  
         if (acl_type == CCS_TYPE_PATH_ACL) {  
                 struct ccs_path_acl *acl  
                         = container_of(ptr, struct ccs_path_acl, head);  
                 return ccs_print_path_acl(head, acl, cond);  
         }  
         if (acl_type == CCS_TYPE_EXECUTE_HANDLER) {  
                 struct ccs_execute_handler_record *acl  
                         = container_of(ptr, struct ccs_execute_handler_record,  
                                        head);  
                 const char *keyword = CCS_KEYWORD_EXECUTE_HANDLER;  
                 return ccs_print_execute_handler_record(head, keyword, acl);  
         }  
         if (acl_type == CCS_TYPE_DENIED_EXECUTE_HANDLER) {  
                 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);  
         }  
         if (head->read_execute_only)  
                 return true;  
         if (acl_type == CCS_TYPE_PATH_NUMBER3_ACL) {  
                 struct ccs_path_number3_acl *acl  
                         = container_of(ptr, struct ccs_path_number3_acl, head);  
                 return ccs_print_path_number3_acl(head, acl, cond);  
         }  
         if (acl_type == CCS_TYPE_PATH2_ACL) {  
                 struct ccs_path2_acl *acl  
                         = container_of(ptr, struct ccs_path2_acl, head);  
                 return ccs_print_path2_acl(head, acl, cond);  
         }  
         if (acl_type == CCS_TYPE_PATH_NUMBER_ACL) {  
                 struct ccs_path_number_acl *acl  
                         = container_of(ptr, struct ccs_path_number_acl, head);  
                 return ccs_print_path_number_acl(head, acl, cond);  
         }  
         if (acl_type == CCS_TYPE_ENV_ACL) {  
                 struct ccs_env_acl *acl  
                         = container_of(ptr, struct ccs_env_acl, head);  
                 return ccs_print_env_acl(head, acl, cond);  
         }  
         if (acl_type == CCS_TYPE_CAPABILITY_ACL) {  
                 struct ccs_capability_acl *acl  
                         = container_of(ptr, struct ccs_capability_acl, head);  
                 return ccs_print_capability_acl(head, acl, cond);  
         }  
         if (acl_type == CCS_TYPE_IP_NETWORK_ACL) {  
                 struct ccs_ip_network_acl *acl  
                         = container_of(ptr, struct ccs_ip_network_acl, head);  
                 return ccs_print_network_acl(head, acl, cond);  
         }  
         if (acl_type == CCS_TYPE_SIGNAL_ACL) {  
                 struct ccs_signal_acl *acl  
                         = container_of(ptr, struct ccs_signal_acl, head);  
                 return ccs_print_signal_acl(head, acl, cond);  
         }  
         if (acl_type == CCS_TYPE_MOUNT_ACL) {  
                 struct ccs_mount_acl *acl  
                         = container_of(ptr, struct ccs_mount_acl, head);  
                 return ccs_print_mount_acl(head, acl, cond);  
         }  
         BUG(); /* This must not happen. */  
         return false;  
 }  
   
 /**  
1446   * ccs_read_domain - Read domain policy.   * ccs_read_domain - Read domain policy.
1447   *   *
1448   * @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 1451  static bool ccs_print_entry(struct ccs_i
1451   */   */
1452  static void ccs_read_domain(struct ccs_io_buffer *head)  static void ccs_read_domain(struct ccs_io_buffer *head)
1453  {  {
1454          struct list_head *dpos;          struct list_head *pos;
         struct list_head *apos;  
1455          if (head->read_eof)          if (head->read_eof)
1456                  return;                  return;
1457          if (head->read_step == 0)          list_for_each_cookie(pos, head->read_var1, &ccs_domain_list) {
1458                  head->read_step = 1;                  struct ccs_domain_info *domain =
1459          list_for_each_cookie(dpos, head->read_var1, &ccs_domain_list) {                          list_entry(pos, struct ccs_domain_info, list);
1460                  struct ccs_domain_info *domain;                  switch (head->read_step) {
1461                  const char *quota_exceeded = "";                          u8 i;
1462                  const char *transition_failed = "";                          const char *w[CCS_MAX_DOMAIN_INFO_FLAGS];
1463                  const char *ignore_global_allow_read = "";                  case 0:
1464                  const char *ignore_global_allow_env = "";                          if (domain->is_deleted && !head->read_single_domain)
1465                  domain = list_entry(dpos, struct ccs_domain_info, list);                                  continue;
1466                  if (head->read_step != 1)                          /* Print domainname and flags. */
1467                          goto acl_loop;                          for (i = 0; i < CCS_MAX_DOMAIN_INFO_FLAGS; i++)
1468                  if (domain->is_deleted && !head->read_single_domain)                                  w[i] = domain->flags[i] ? ccs_dif[i] : "";
1469                          continue;                          if (!ccs_io_printf(head, "%s\n" CCS_KEYWORD_USE_PROFILE
1470                  /* Print domainname and flags. */                                             "%u\n%s%s%s%s%s\n",
1471                  if (domain->quota_warned)                                             domain->domainname->name,
1472                          quota_exceeded = CCS_KEYWORD_QUOTA_EXCEEDED "\n";                                             domain->profile,
1473                  if (domain->domain_transition_failed)                                             w[CCS_DIF_QUOTA_WARNED],
1474                          transition_failed = CCS_KEYWORD_TRANSITION_FAILED "\n";                                             w[CCS_DIF_IGNORE_GLOBAL],
1475                  if (domain->ignore_global_allow_read)                                             w[CCS_DIF_IGNORE_GLOBAL_ALLOW_READ],
1476                          ignore_global_allow_read                                             w[CCS_DIF_IGNORE_GLOBAL_ALLOW_ENV],
1477                                  = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";                                             w[CCS_DIF_TRANSITION_FAILED]))
1478                  if (domain->ignore_global_allow_env)                                  return;
1479                          ignore_global_allow_env                          head->read_step++;
1480                                  = CCS_KEYWORD_IGNORE_GLOBAL_ALLOW_ENV "\n";                          /* fall through */
1481                  if (!ccs_io_printf(head, "%s\n" CCS_KEYWORD_USE_PROFILE "%u\n"                  case 1:
1482                                     "%s%s%s%s\n", domain->domainname->name,                          if (!ccs_read_domain2(head, domain))
                                    domain->profile, quota_exceeded,  
                                    transition_failed,  
                                    ignore_global_allow_read,  
                                    ignore_global_allow_env))  
                         return;  
                 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))  
1483                                  return;                                  return;
1484                            head->read_step++;
1485                            /* fall through */
1486                    case 2:
1487                            if (!ccs_io_printf(head, "\n"))
1488                                    return;
1489                            head->read_step = 0;
1490                            if (head->read_single_domain)
1491                                    goto out;
1492                  }                  }
                 head->read_step = 3;  
  tail_mark:  
                 if (!ccs_io_printf(head, "\n"))  
                         return;  
                 head->read_step = 1;  
                 if (head->read_single_domain)  
                         break;  
1493          }          }
1494     out:
1495          head->read_eof = true;          head->read_eof = true;
1496  }  }
1497    
# Line 1808  static void ccs_read_pid(struct ccs_io_b Line 1635  static void ccs_read_pid(struct ccs_io_b
1635                                (u8) (ccs_flags >> 8));                                (u8) (ccs_flags >> 8));
1636  }  }
1637    
1638    static const char *ccs_transition_type[CCS_MAX_TRANSITION_TYPE] = {
1639            [CCS_TRANSITION_CONTROL_NO_INITIALIZE]
1640            = CCS_KEYWORD_NO_INITIALIZE_DOMAIN,
1641            [CCS_TRANSITION_CONTROL_INITIALIZE] = CCS_KEYWORD_INITIALIZE_DOMAIN,
1642            [CCS_TRANSITION_CONTROL_NO_KEEP] = CCS_KEYWORD_NO_KEEP_DOMAIN,
1643            [CCS_TRANSITION_CONTROL_KEEP] = CCS_KEYWORD_KEEP_DOMAIN
1644    };
1645    
1646    static const char *ccs_group_name[CCS_MAX_GROUP] = {
1647            [CCS_PATH_GROUP] = CCS_KEYWORD_PATH_GROUP,
1648            [CCS_NUMBER_GROUP] = CCS_KEYWORD_NUMBER_GROUP,
1649            [CCS_ADDRESS_GROUP] = CCS_KEYWORD_ADDRESS_GROUP
1650    };
1651    
1652  /**  /**
1653   * ccs_write_exception - Write exception policy.   * ccs_write_exception - Write exception policy.
1654   *   *
# Line 1822  static int ccs_write_exception(struct cc Line 1663  static int ccs_write_exception(struct cc
1663          u8 i;          u8 i;
1664          static const struct {          static const struct {
1665                  const char *keyword;                  const char *keyword;
1666                  int (*write) (char *, const bool, const u8);                  int (*write) (char *, const bool);
1667          } 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 },  
1668                  { 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 },  
1669                  { CCS_KEYWORD_FILE_PATTERN, ccs_write_pattern },                  { CCS_KEYWORD_FILE_PATTERN, ccs_write_pattern },
1670                  { CCS_KEYWORD_DENY_REWRITE, ccs_write_no_rewrite },                  { CCS_KEYWORD_DENY_REWRITE, ccs_write_no_rewrite },
1671                  { CCS_KEYWORD_DENY_AUTOBIND, ccs_write_reserved_port }                  { CCS_KEYWORD_DENY_AUTOBIND, ccs_write_reserved_port }
1672          };          };
1673          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++) {  
1674                  if (ccs_str_starts(&data, ccs_callback[i].keyword))                  if (ccs_str_starts(&data, ccs_callback[i].keyword))
1675                          return ccs_callback[i].write(data, is_delete, i < 2);                          return ccs_callback[i].write(data, is_delete);
1676            }
1677            for (i = 0; i < CCS_MAX_TRANSITION_TYPE; i++) {
1678                    if (ccs_str_starts(&data, ccs_transition_type[i]))
1679                            return ccs_write_transition_control(data, is_delete,
1680                                                                i);
1681          }          }
1682          for (i = 0; i < CCS_MAX_GROUP; i++) {          for (i = 0; i < CCS_MAX_GROUP; i++) {
1683                  if (ccs_str_starts(&data, ccs_name[i]))                  if (ccs_str_starts(&data, ccs_group_name[i]))
1684                          return ccs_write_group(data, is_delete, i);                          return ccs_write_group(data, is_delete, i);
1685          }          }
1686          return -EINVAL;          return ccs_write_domain2(data, &ccs_global_domain, is_delete);
1687  }  }
1688    
1689  /**  /**
# Line 1868  static bool ccs_read_group(struct ccs_io Line 1701  static bool ccs_read_group(struct ccs_io
1701          struct list_head *gpos;          struct list_head *gpos;
1702          struct list_head *mpos;          struct list_head *mpos;
1703          const char *w[3] = { "", "", "" };          const char *w[3] = { "", "", "" };
1704          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;  
1705          list_for_each_cookie(gpos, head->read_var1, &ccs_group_list[idx]) {          list_for_each_cookie(gpos, head->read_var1, &ccs_group_list[idx]) {
1706                  struct ccs_group *group =                  struct ccs_group *group =
1707                          list_entry(gpos, struct ccs_group, head.list);                          list_entry(gpos, struct ccs_group, head.list);
# Line 1885  static bool ccs_read_group(struct ccs_io Line 1713  static bool ccs_read_group(struct ccs_io
1713                                  list_entry(mpos, struct ccs_acl_head, list);                                  list_entry(mpos, struct ccs_acl_head, list);
1714                          if (ptr->is_deleted)                          if (ptr->is_deleted)
1715                                  continue;                                  continue;
1716                            w[2] = buffer;
1717                          if (idx == CCS_PATH_GROUP) {                          if (idx == CCS_PATH_GROUP) {
1718                                  w[2] = container_of(ptr, struct ccs_path_group,                                  w[2] = container_of(ptr, struct ccs_path_group,
1719                                                      head)->member_name->name;                                                      head)->member_name->name;
1720                          } else if (idx == CCS_NUMBER_GROUP) {                          } else if (idx == CCS_NUMBER_GROUP) {
                                 w[2] = buffer;  
1721                                  ccs_print_number(buffer, sizeof(buffer),                                  ccs_print_number(buffer, sizeof(buffer),
1722                                                   &container_of                                                   &container_of
1723                                                   (ptr, struct ccs_number_group,                                                   (ptr, struct ccs_number_group,
# Line 1898  static bool ccs_read_group(struct ccs_io Line 1726  static bool ccs_read_group(struct ccs_io
1726                                  struct ccs_address_group *member =                                  struct ccs_address_group *member =
1727                                          container_of(ptr, typeof(*member),                                          container_of(ptr, typeof(*member),
1728                                                       head);                                                       head);
                                 w[2] = buffer;  
1729                                  if (member->is_ipv6)                                  if (member->is_ipv6)
1730                                          ccs_print_ipv6(buffer, sizeof(buffer),                                          ccs_print_ipv6(buffer, sizeof(buffer),
1731                                                         member->min.ipv6,                                                         member->min.ipv6,
# Line 1937  static bool ccs_read_policy(struct ccs_i Line 1764  static bool ccs_read_policy(struct ccs_i
1764                  if (acl->is_deleted)                  if (acl->is_deleted)
1765                          continue;                          continue;
1766                  switch (idx) {                  switch (idx) {
1767                  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:  
1768                          {                          {
1769                                  struct ccs_domain_initializer *ptr =                                  struct ccs_transition_control *ptr =
1770                                          container_of(acl, typeof(*ptr), head);                                          container_of(acl, typeof(*ptr), head);
1771                                  w[0] = ptr->is_not ?                                  w[0] = ccs_transition_type[ptr->type];
1772                                          CCS_KEYWORD_NO_INITIALIZE_DOMAIN :                                  w[1] = ptr->program ? ptr->program->name
1773                                          CCS_KEYWORD_INITIALIZE_DOMAIN;                                          : "any";
1774                                  w[1] = ptr->program->name;                                  w[2] = " from ";
1775                                  if (ptr->domainname) {                                  w[3] = ptr->domainname ? ptr->domainname->name
1776                                          w[2] = " from ";                                          : "any";
                                         w[3] = ptr->domainname->name;  
                                 }  
1777                          }                          }
1778                          break;                          break;
1779                  case CCS_ID_AGGREGATOR:                  case CCS_ID_AGGREGATOR:
# Line 1975  static bool ccs_read_policy(struct ccs_i Line 1786  static bool ccs_read_policy(struct ccs_i
1786                                  w[3] = ptr->aggregated_name->name;                                  w[3] = ptr->aggregated_name->name;
1787                          }                          }
1788                          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;  
1789                  case CCS_ID_PATTERN:                  case CCS_ID_PATTERN:
1790                          {                          {
1791                                  struct ccs_pattern *ptr =                                  struct ccs_pattern *ptr =
# Line 1999  static bool ccs_read_policy(struct ccs_i Line 1802  static bool ccs_read_policy(struct ccs_i
1802                                  w[1] = ptr->pattern->name;                                  w[1] = ptr->pattern->name;
1803                          }                          }
1804                          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;  
1805                  case CCS_ID_RESERVEDPORT:                  case CCS_ID_RESERVEDPORT:
1806                          {                          {
1807                                  struct ccs_reserved *ptr =                                  struct ccs_reserved *ptr =
# Line 2021  static bool ccs_read_policy(struct ccs_i Line 1816  static bool ccs_read_policy(struct ccs_i
1816                                  w[1] = buffer;                                  w[1] = buffer;
1817                          }                          }
1818                          break;                          break;
1819                    default:
1820                            continue;
1821                  }                  }
1822                  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]))
1823                          return false;                          return false;
# Line 2028  static bool ccs_read_policy(struct ccs_i Line 1825  static bool ccs_read_policy(struct ccs_i
1825          return true;          return true;
1826  }  }
1827    
1828    static void ccs_read_global_domain(struct ccs_io_buffer *head)
1829    {
1830            if (!head->read_eof)
1831                    head->read_eof = ccs_read_domain2(head, &ccs_global_domain);
1832    }
1833    
1834  /**  /**
1835   * ccs_read_exception - Read exception policy.   * ccs_read_exception - Read exception policy.
1836   *   *
# Line 2047  static void ccs_read_exception(struct cc Line 1850  static void ccs_read_exception(struct cc
1850          while (head->read_step < CCS_MAX_POLICY + CCS_MAX_GROUP &&          while (head->read_step < CCS_MAX_POLICY + CCS_MAX_GROUP &&
1851                 ccs_read_group(head, head->read_step - CCS_MAX_POLICY))                 ccs_read_group(head, head->read_step - CCS_MAX_POLICY))
1852                  head->read_step++;                  head->read_step++;
1853          head->read_eof = head->read_step == CCS_MAX_POLICY + CCS_MAX_GROUP;          if (head->read_step < CCS_MAX_POLICY + CCS_MAX_GROUP)
1854  }                  return;
1855            head->read = ccs_read_global_domain;
 /**  
  * ccs_get_argv0 - Get argv[0].  
  *  
  * @ee: Pointer to "struct ccs_execve".  
  *  
  * Returns true on success, false otherwise.  
  */  
 static bool ccs_get_argv0(struct ccs_execve *ee)  
 {  
         struct linux_binprm *bprm = ee->bprm;  
         char *arg_ptr = ee->tmp;  
         int arg_len = 0;  
         unsigned long pos = bprm->p;  
         int offset = pos % PAGE_SIZE;  
         bool done = false;  
         if (!bprm->argc)  
                 goto out;  
         while (1) {  
                 if (!ccs_dump_page(bprm, pos, &ee->dump))  
                         goto out;  
                 pos += PAGE_SIZE - offset;  
                 /* Read. */  
                 while (offset < PAGE_SIZE) {  
                         const char *kaddr = ee->dump.data;  
                         const unsigned char c = kaddr[offset++];  
                         if (c && arg_len < CCS_EXEC_TMPSIZE - 10) {  
                                 if (c == '\\') {  
                                         arg_ptr[arg_len++] = '\\';  
                                         arg_ptr[arg_len++] = '\\';  
                                 } else if (c > ' ' && c < 127) {  
                                         arg_ptr[arg_len++] = c;  
                                 } else {  
                                         arg_ptr[arg_len++] = '\\';  
                                         arg_ptr[arg_len++] = (c >> 6) + '0';  
                                         arg_ptr[arg_len++]  
                                                 = ((c >> 3) & 7) + '0';  
                                         arg_ptr[arg_len++] = (c & 7) + '0';  
                                 }  
                         } else {  
                                 arg_ptr[arg_len] = '\0';  
                                 done = true;  
                                 break;  
                         }  
                 }  
                 offset = 0;  
                 if (done)  
                         break;  
         }  
         return true;  
  out:  
         return false;  
 }  
   
 /**  
  * 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;  
1856  }  }
1857    
1858  /* Wait queue for ccs_query_list. */  /* Wait queue for ccs_query_list. */
# Line 2224  static LIST_HEAD(ccs_query_list); Line 1877  static LIST_HEAD(ccs_query_list);
1877  /* Number of "struct file" referring /proc/ccs/query interface. */  /* Number of "struct file" referring /proc/ccs/query interface. */
1878  static atomic_t ccs_query_observers = ATOMIC_INIT(0);  static atomic_t ccs_query_observers = ATOMIC_INIT(0);
1879    
1880    static void ccs_addprintf(char *buffer, int len, const char *fmt, ...)
1881    {
1882            va_list args;
1883            const int pos = strlen(buffer);
1884            va_start(args, fmt);
1885            vsnprintf(buffer + pos, len - pos - 1, fmt, args);
1886            va_end(args);
1887    }
1888    
1889    static void ccs_truncate(char *str)
1890    {
1891            while (* (unsigned char *) str > (unsigned char) ' ')
1892                    str++;
1893            *str = '\0';
1894    }
1895    
1896  /**  /**
1897   * ccs_supervisor - Ask for the supervisor's decision.   * ccs_supervisor - Ask for the supervisor's decision.
1898   *   *
1899   * @r:       Pointer to "struct ccs_request_info".   * @r:   Pointer to "struct ccs_request_info".
1900   * @fmt:     The printf()'s format string, followed by parameters.   * @fmt: The printf()'s format string, followed by parameters.
1901   *   *
1902   * Returns 0 if the supervisor decided to permit the access request which   * Returns 0 if the supervisor decided to permit the access request which
1903   * 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 1915  int ccs_supervisor(struct ccs_request_in
1915          bool quota_exceeded = false;          bool quota_exceeded = false;
1916          char *header;          char *header;
1917          struct ccs_domain_info * const domain = ccs_current_domain();          struct ccs_domain_info * const domain = ccs_current_domain();
1918          switch (r->mode) {          va_start(args, fmt);
1919            len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 80;
1920            va_end(args);
1921            if (r->mode == CCS_CONFIG_LEARNING) {
1922                  char *buffer;                  char *buffer;
1923                  struct ccs_condition *cond;                  char *realpath = NULL;
1924          case CCS_CONFIG_LEARNING:                  char *argv0 = NULL;
1925                    char *symlink = NULL;
1926                    char *handler = NULL;
1927                    const struct ccs_preference *pref;
1928                  if (!ccs_domain_quota_ok(r))                  if (!ccs_domain_quota_ok(r))
1929                          return 0;                          return 0;
1930                  va_start(args, fmt);                  header = ccs_init_log(&len, r);
1931                  len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 4;                  if (!header)
                 va_end(args);  
                 buffer = kmalloc(len, CCS_GFP_FLAGS);  
                 if (!buffer)  
1932                          return 0;                          return 0;
1933                  va_start(args, fmt);                  pref = ccs_profile(r->profile)->learning;
1934                  vsnprintf(buffer, len - 1, fmt, args);                  /* strstr() will return NULL if ordering is wrong. */
1935                  va_end(args);                  if (r->param_type == CCS_TYPE_PATH_ACL &&
1936                  ccs_normalize_line(buffer);                      r->param.path.operation == CCS_TYPE_EXECUTE) {
1937                  if (r->ee && !strncmp(buffer, "allow_execute ", 14))                          if (pref->learning_exec_argv0) {
1938                          cond = ccs_get_execute_condition(r->ee);                                  argv0 = strstr(header, " argv[]={ \"");
1939                  else if (r->obj && r->obj->symlink_target)                                  if (argv0) {
1940                          cond = ccs_get_symlink_condition(r);                                          argv0 += 10;
1941                  else if ((current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)) {                                          ccs_truncate(argv0);
1942                          char str[] = "if task.type=execute_handler";                                  }
1943                          cond = ccs_get_condition(str);                          }
1944                  } else                          if (pref->learning_exec_realpath) {
1945                          cond = NULL;                                  realpath = strstr(header,
1946                  ccs_write_domain2(buffer, domain, cond, false);                                                    " exec={ realpath=\"");
1947                  ccs_put_condition(cond);                                  if (realpath) {
1948                  kfree(buffer);                                          realpath += 8;
1949                  /* fall through */                                          ccs_truncate(realpath);
1950          case CCS_CONFIG_PERMISSIVE:                                  }
1951                            }
1952                    } else if (r->param_type == CCS_TYPE_PATH_ACL &&
1953                               r->param.path.operation == CCS_TYPE_SYMLINK &&
1954                               pref->learning_symlink_target) {
1955                            symlink = strstr(header, " symlink.target=\"");
1956                            if (symlink)
1957                                    ccs_truncate(symlink + 1);
1958                    }
1959                    handler = strstr(header, "type=execute_handler");
1960                    if (handler)
1961                            ccs_truncate(handler);
1962                    buffer = kmalloc(len, CCS_GFP_FLAGS);
1963                    if (buffer) {
1964                            va_start(args, fmt);
1965                            vsnprintf(buffer, len - 1, fmt, args);
1966                            va_end(args);
1967                            if (handler || realpath || argv0 || symlink) {
1968                                    ccs_addprintf(buffer, len, " if");
1969                                    if (handler)
1970                                            ccs_addprintf(buffer, len, " task.%s",
1971                                                          handler);
1972                                    if (realpath)
1973                                            ccs_addprintf(buffer, len, " exec.%s",
1974                                                          realpath);
1975                                    if (argv0)
1976                                            ccs_addprintf(buffer, len,
1977                                                          " exec.argv[0]=%s",
1978                                                          argv0);
1979                                    if (symlink)
1980                                            ccs_addprintf(buffer, len, "%s",
1981                                                          symlink);
1982                            }
1983                            ccs_normalize_line(buffer);
1984                            ccs_write_domain2(buffer, domain, false);
1985                            kfree(buffer);
1986                    }
1987                    kfree(header);
1988                  return 0;                  return 0;
1989          }          }
1990            if (r->mode != CCS_CONFIG_ENFORCING)
1991                    return 0;
1992          if (!atomic_read(&ccs_query_observers)) {          if (!atomic_read(&ccs_query_observers)) {
1993                  int i;                  int i;
1994                  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 2000  int ccs_supervisor(struct ccs_request_in
2000                  }                  }
2001                  return -EPERM;                  return -EPERM;
2002          }          }
2003          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);  
2004          if (!header)          if (!header)
2005                  goto out;                  goto out;
2006          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 2022  int ccs_supervisor(struct ccs_request_in
2022          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
2023          if (quota_exceeded)          if (quota_exceeded)
2024                  goto out;                  goto out;
2025          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",
2026                         ccs_query_entry->serial, r->retry, header);                   ccs_query_entry->serial, r->retry, header);
2027          kfree(header);          kfree(header);
2028          header = NULL;          header = NULL;
2029          va_start(args, fmt);          ccs_addprintf(ccs_query_entry->query, len, fmt, args);
         vsnprintf(ccs_query_entry->query + pos, len - 1 - pos, fmt, args);  
2030          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);  
2031          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2032          list_add_tail(&ccs_query_entry->list, &ccs_query_list);          list_add_tail(&ccs_query_entry->list, &ccs_query_list);
2033          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
# Line 2556  int ccs_open_control(const u8 type, stru Line 2262  int ccs_open_control(const u8 type, stru
2262  #ifdef CONFIG_CCSECURITY_AUDIT  #ifdef CONFIG_CCSECURITY_AUDIT
2263          case CCS_GRANTLOG: /* /proc/ccs/grant_log */          case CCS_GRANTLOG: /* /proc/ccs/grant_log */
2264          case CCS_REJECTLOG: /* /proc/ccs/reject_log */          case CCS_REJECTLOG: /* /proc/ccs/reject_log */
2265                  head->poll = ccs_poll_audit_log;                  head->poll = ccs_poll_log;
2266                  head->read = ccs_read_audit_log;                  head->read = ccs_read_log;
2267                  break;                  break;
2268  #endif  #endif
2269          case CCS_SELFDOMAIN: /* /proc/ccs/self_domain */          case CCS_SELFDOMAIN: /* /proc/ccs/self_domain */

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

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