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

Subversion リポジトリの参照

Diff of /trunk/1.7.x/ccs-patch/security/ccsecurity/util.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

trunk/1.6.x/ccs-patch/fs/ccs_common.c revision 2303 by kumaneko, Mon Mar 23 08:34:53 2009 UTC branches/ccs-patch/fs/ccsecurity/util.c revision 2854 by kumaneko, Wed Aug 5 11:57:20 2009 UTC
# Line 1  Line 1 
1  /*  /*
2   * fs/ccs_common.c   * fs/ccsecurity/util.c
  *  
  * Common functions for SAKURA and TOMOYO.  
3   *   *
4   * Copyright (C) 2005-2009  NTT DATA CORPORATION   * Copyright (C) 2005-2009  NTT DATA CORPORATION
5   *   *
6   * Version: 1.6.7-rc   2009/03/18   * Version: 1.7.0-pre   2009/07/03
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 31  static const int ccs_lookup_flags = LOOK Line 29  static const int ccs_lookup_flags = LOOK
29  #else  #else
30  static const int ccs_lookup_flags = LOOKUP_FOLLOW | LOOKUP_POSITIVE;  static const int ccs_lookup_flags = LOOKUP_FOLLOW | LOOKUP_POSITIVE;
31  #endif  #endif
 #include <linux/realpath.h>  
 #include <linux/ccs_common.h>  
 #include <linux/ccs_proc.h>  
 #include <linux/tomoyo.h>  
32  #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)  #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0)
33  #include <linux/unistd.h>  #include <linux/unistd.h>
34  #endif  #endif
35    #include "internal.h"
36    #include <linux/ccsecurity.h>
37    
38  /* To support PID namespace. */  /* To support PID namespace. */
39  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)  #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
# Line 45  static const int ccs_lookup_flags = LOOK Line 41  static const int ccs_lookup_flags = LOOK
41  #endif  #endif
42    
43  /* Set default specified by the kernel config. */  /* Set default specified by the kernel config. */
44  #ifdef CONFIG_TOMOYO  #define MAX_ACCEPT_ENTRY (CONFIG_CCSECURITY_MAX_ACCEPT_ENTRY)
45  #define MAX_ACCEPT_ENTRY (CONFIG_TOMOYO_MAX_ACCEPT_ENTRY)  #define MAX_GRANT_LOG    (CONFIG_CCSECURITY_MAX_GRANT_LOG)
46  #define MAX_GRANT_LOG    (CONFIG_TOMOYO_MAX_GRANT_LOG)  #define MAX_REJECT_LOG   (CONFIG_CCSECURITY_MAX_REJECT_LOG)
47  #define MAX_REJECT_LOG   (CONFIG_TOMOYO_MAX_REJECT_LOG)  
48  #else  DEFINE_MUTEX(ccs_policy_lock);
 #define MAX_ACCEPT_ENTRY 0  
 #define MAX_GRANT_LOG    0  
 #define MAX_REJECT_LOG   0  
 #endif  
49    
50  /* Has /sbin/init started? */  /* Has /sbin/init started? */
51  bool ccs_policy_loaded;  bool ccs_policy_loaded;
52    
 /* Log level for SAKURA's printk(). */  
 const char *ccs_log_level = KERN_DEBUG;  
   
53  /* String table for functionality that takes 4 modes. */  /* String table for functionality that takes 4 modes. */
54  static const char *ccs_mode_4[4] = {  static const char *ccs_mode_4[4] = {
55          "disabled", "learning", "permissive", "enforcing"          "disabled", "learning", "permissive", "enforcing"
# Line 82  static struct { Line 71  static struct {
71          [CCS_MAC_FOR_ENV]         = { "MAC_FOR_ENV",         0, 3 },          [CCS_MAC_FOR_ENV]         = { "MAC_FOR_ENV",         0, 3 },
72          [CCS_MAC_FOR_NETWORK]     = { "MAC_FOR_NETWORK",     0, 3 },          [CCS_MAC_FOR_NETWORK]     = { "MAC_FOR_NETWORK",     0, 3 },
73          [CCS_MAC_FOR_SIGNAL]      = { "MAC_FOR_SIGNAL",      0, 3 },          [CCS_MAC_FOR_SIGNAL]      = { "MAC_FOR_SIGNAL",      0, 3 },
74          [CCS_DENY_CONCEAL_MOUNT]  = { "DENY_CONCEAL_MOUNT",  0, 3 },          [CCS_MAC_FOR_NAMESPACE]   = { "MAC_FOR_NAMESPACE",   0, 3 },
         [CCS_RESTRICT_CHROOT]     = { "RESTRICT_CHROOT",     0, 3 },  
         [CCS_RESTRICT_MOUNT]      = { "RESTRICT_MOUNT",      0, 3 },  
         [CCS_RESTRICT_UNMOUNT]    = { "RESTRICT_UNMOUNT",    0, 3 },  
         [CCS_RESTRICT_PIVOT_ROOT] = { "RESTRICT_PIVOT_ROOT", 0, 3 },  
75          [CCS_RESTRICT_AUTOBIND]   = { "RESTRICT_AUTOBIND",   0, 1 },          [CCS_RESTRICT_AUTOBIND]   = { "RESTRICT_AUTOBIND",   0, 1 },
76          [CCS_MAX_ACCEPT_ENTRY]          [CCS_MAX_ACCEPT_ENTRY]
77          = { "MAX_ACCEPT_ENTRY",    MAX_ACCEPT_ENTRY, INT_MAX },          = { "MAX_ACCEPT_ENTRY",    MAX_ACCEPT_ENTRY, INT_MAX },
78  #ifdef CONFIG_TOMOYO_AUDIT  #ifdef CONFIG_CCSECURITY_AUDIT
79          [CCS_MAX_GRANT_LOG]          [CCS_MAX_GRANT_LOG]
80          = { "MAX_GRANT_LOG",       MAX_GRANT_LOG, INT_MAX },          = { "MAX_GRANT_LOG",       MAX_GRANT_LOG, INT_MAX },
81          [CCS_MAX_REJECT_LOG]          [CCS_MAX_REJECT_LOG]
# Line 101  static struct { Line 86  static struct {
86          = { "SLEEP_PERIOD",        0, 3000 }, /* in 0.1 second */          = { "SLEEP_PERIOD",        0, 3000 }, /* in 0.1 second */
87  };  };
88    
 #ifdef CONFIG_TOMOYO  
89  /* Capability name used by domain policy. */  /* Capability name used by domain policy. */
90  static const char *ccs_capability_control_keyword[CCS_MAX_CAPABILITY_INDEX]  static const char *ccs_capability_control_keyword[CCS_MAX_CAPABILITY_INDEX]
91  = {  = {
# Line 136  static const char *ccs_capability_contro Line 120  static const char *ccs_capability_contro
120          [CCS_SYS_KEXEC_LOAD]             = "SYS_KEXEC_LOAD",          [CCS_SYS_KEXEC_LOAD]             = "SYS_KEXEC_LOAD",
121          [CCS_SYS_PIVOT_ROOT]             = "SYS_PIVOT_ROOT",          [CCS_SYS_PIVOT_ROOT]             = "SYS_PIVOT_ROOT",
122          [CCS_SYS_PTRACE]                 = "SYS_PTRACE",          [CCS_SYS_PTRACE]                 = "SYS_PTRACE",
123            [CCS_CONCEAL_MOUNT]              = "conceal_mount",
124  };  };
 #endif  
125    
 #ifdef CONFIG_TOMOYO  
126  static bool ccs_profile_entry_used[CCS_MAX_CONTROL_INDEX +  static bool ccs_profile_entry_used[CCS_MAX_CONTROL_INDEX +
127                                     CCS_MAX_CAPABILITY_INDEX + 1];                                     CCS_MAX_CAPABILITY_INDEX + 1];
 #else  
 static bool ccs_profile_entry_used[CCS_MAX_CONTROL_INDEX + 1];  
 #endif  
128    
129  /* Profile table. Memory is allocated as needed. */  /* Profile table. Memory is allocated as needed. */
130  static struct ccs_profile {  static struct ccs_profile {
131          unsigned int value[CCS_MAX_CONTROL_INDEX];          unsigned int value[CCS_MAX_CONTROL_INDEX];
132          const struct ccs_path_info *comment;          const struct ccs_path_info *comment;
 #ifdef CONFIG_TOMOYO  
133          unsigned char capability_value[CCS_MAX_CAPABILITY_INDEX];          unsigned char capability_value[CCS_MAX_CAPABILITY_INDEX];
 #endif  
134  } *ccs_profile_ptr[MAX_PROFILES];  } *ccs_profile_ptr[MAX_PROFILES];
135    
136    /* Lock for protecting ccs_profile->comment  */
137    static DEFINE_SPINLOCK(ccs_profile_comment_lock);
138    
139  /* Permit policy management by non-root user? */  /* Permit policy management by non-root user? */
140  static bool ccs_manage_by_non_root;  static bool ccs_manage_by_non_root;
141    
142  /* Utility functions. */  /* Utility functions. */
143    
 #ifdef CONFIG_TOMOYO  
144  /**  /**
145   * ccs_quiet_setup - Set CCS_VERBOSE=0 by default.   * ccs_quiet_setup - Set CCS_VERBOSE=0 by default.
146   *   *
# Line 175  static int __init ccs_quiet_setup(char * Line 155  static int __init ccs_quiet_setup(char *
155  }  }
156    
157  __setup("CCS_QUIET", ccs_quiet_setup);  __setup("CCS_QUIET", ccs_quiet_setup);
 #endif  
158    
159  /**  /**
160   * ccs_is_byte_range - Check whether the string isa \ooo style octal value.   * ccs_is_byte_range - Check whether the string isa \ooo style octal value.
# Line 275  static bool ccs_str_starts(char **src, c Line 254  static bool ccs_str_starts(char **src, c
254   *   *
255   * Returns nothing.   * Returns nothing.
256   */   */
257  static void ccs_normalize_line(unsigned char *buffer)  void ccs_normalize_line(unsigned char *buffer)
258  {  {
259          unsigned char *sp = buffer;          unsigned char *sp = buffer;
260          unsigned char *dp = buffer;          unsigned char *dp = buffer;
# Line 295  static void ccs_normalize_line(unsigned Line 274  static void ccs_normalize_line(unsigned
274  }  }
275    
276  /**  /**
277     * ccs_tokenize - Tokenize string.
278     *
279     * @buffer: The line to tokenize.
280     * @w:      Pointer to "char *".
281     * @size:   Sizeof @w .
282     *
283     * Returns true on success, false otherwise.
284     */
285    bool ccs_tokenize(char *buffer, char *w[], size_t size)
286    {
287            int count = size / sizeof(char *);
288            int i;
289            for (i = 0; i < count; i++)
290                    w[i] = "";
291            for (i = 0; i < count; i++) {
292                    char *cp = strchr(buffer, ' ');
293                    if (cp)
294                            *cp = '\0';
295                    w[i] = buffer;
296                    if (!cp)
297                            break;
298                    buffer = cp + 1;
299            }
300            return i < count || !*buffer;
301    }
302    
303    /**
304   * ccs_is_correct_path - Validate a pathname.   * ccs_is_correct_path - Validate a pathname.
305   * @filename:     The pathname to check.   * @filename:     The pathname to check.
306   * @start_type:   Should the pathname start with '/'?   * @start_type:   Should the pathname start with '/'?
# Line 303  static void ccs_normalize_line(unsigned Line 309  static void ccs_normalize_line(unsigned
309   *                1 = must / -1 = must not / 0 = don't care   *                1 = must / -1 = must not / 0 = don't care
310   * @end_type:     Should the pathname end with '/'?   * @end_type:     Should the pathname end with '/'?
311   *                1 = must / -1 = must not / 0 = don't care   *                1 = must / -1 = must not / 0 = don't care
  * @function:     The name of function calling me.  
312   *   *
313   * Check whether the given filename follows the naming rules.   * Check whether the given filename follows the naming rules.
314   * Returns true if @filename follows the naming rules, false otherwise.   * Returns true if @filename follows the naming rules, false otherwise.
315   */   */
316  bool ccs_is_correct_path(const char *filename, const s8 start_type,  bool ccs_is_correct_path(const char *filename, const s8 start_type,
317                           const s8 pattern_type, const s8 end_type,                           const s8 pattern_type, const s8 end_type)
                          const char *function)  
318  {  {
319          bool contains_pattern = false;          bool contains_pattern = false;
320          unsigned char c;          unsigned char c;
# Line 384  bool ccs_is_correct_path(const char *fil Line 388  bool ccs_is_correct_path(const char *fil
388          }          }
389          return true;          return true;
390   out:   out:
391          printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function,          printk(KERN_DEBUG "Invalid pathname '%s'\n", original_filename);
                original_filename);  
392          return false;          return false;
393  }  }
394    
395  /**  /**
396   * ccs_is_correct_domain - Check whether the given domainname follows the naming rules.   * ccs_is_correct_domain - Check whether the given domainname follows the naming rules.
397   * @domainname:   The domainname to check.   * @domainname:   The domainname to check.
  * @function:     The name of function calling me.  
398   *   *
399   * Returns true if @domainname follows the naming rules, false otherwise.   * Returns true if @domainname follows the naming rules, false otherwise.
400   */   */
401  bool ccs_is_correct_domain(const unsigned char *domainname,  bool ccs_is_correct_domain(const unsigned char *domainname)
                            const char *function)  
402  {  {
403          unsigned char c;          unsigned char c;
404          unsigned char d;          unsigned char d;
# Line 446  bool ccs_is_correct_domain(const unsigne Line 447  bool ccs_is_correct_domain(const unsigne
447          } while (*domainname);          } while (*domainname);
448          return true;          return true;
449   out:   out:
450          printk(KERN_DEBUG "%s: Invalid domainname '%s'\n", function,          printk(KERN_DEBUG "Invalid domainname '%s'\n", org_domainname);
                org_domainname);  
451          return false;          return false;
452  }  }
453    
# Line 469  bool ccs_is_domain_def(const unsigned ch Line 469  bool ccs_is_domain_def(const unsigned ch
469   * @domainname: The domainname to find.   * @domainname: The domainname to find.
470   *   *
471   * Returns pointer to "struct ccs_domain_info" if found, NULL otherwise.   * Returns pointer to "struct ccs_domain_info" if found, NULL otherwise.
472     *
473     * Caller holds ccs_read_lock().
474   */   */
475  struct ccs_domain_info *ccs_find_domain(const char *domainname)  struct ccs_domain_info *ccs_find_domain(const char *domainname)
476  {  {
477          struct ccs_domain_info *domain;          struct ccs_domain_info *domain;
478          struct ccs_path_info name;          struct ccs_path_info name;
479            ccs_check_read_lock();
480          name.name = domainname;          name.name = domainname;
481          ccs_fill_path_info(&name);          ccs_fill_path_info(&name);
482          list1_for_each_entry(domain, &ccs_domain_list, list) {          list_for_each_entry_rcu(domain, &ccs_domain_list, list) {
483                  if (!domain->is_deleted &&                  if (!domain->is_deleted &&
484                      !ccs_pathcmp(&name, domain->domainname))                      !ccs_pathcmp(&name, domain->domainname))
485                          return domain;                          return domain;
# Line 828  bool ccs_io_printf(struct ccs_io_buffer Line 831  bool ccs_io_printf(struct ccs_io_buffer
831   *   *
832   * Returns the ccs_realpath() of current process on success, NULL otherwise.   * Returns the ccs_realpath() of current process on success, NULL otherwise.
833   *   *
834   * This function uses ccs_alloc(), so the caller must ccs_free()   * This function uses kzalloc(), so the caller must kfree()
835   * if this function didn't return NULL.   * if this function didn't return NULL.
836   */   */
837  const char *ccs_get_exe(void)  const char *ccs_get_exe(void)
# Line 914  unsigned int ccs_check_flags(const struc Line 917  unsigned int ccs_check_flags(const struc
917                  ccs_profile_ptr[profile]->value[index] : 0;                  ccs_profile_ptr[profile]->value[index] : 0;
918  }  }
919    
 #ifdef CONFIG_TOMOYO  
920  /**  /**
921   * ccs_check_capability_flags - Check mode for specified capability.   * ccs_check_capability_flags - Check mode for specified capability.
922   *   *
# Line 949  const char *ccs_cap2keyword(const u8 ope Line 951  const char *ccs_cap2keyword(const u8 ope
951                  ? ccs_capability_control_keyword[operation] : NULL;                  ? ccs_capability_control_keyword[operation] : NULL;
952  }  }
953    
 #endif  
   
954  /**  /**
955   * ccs_init_request_info - Initialize "struct ccs_request_info" members.   * ccs_init_request_info - Initialize "struct ccs_request_info" members.
956   *   *
# Line 968  void ccs_init_request_info(struct ccs_re Line 968  void ccs_init_request_info(struct ccs_re
968          r->profile = domain->profile;          r->profile = domain->profile;
969          if (index < CCS_MAX_CONTROL_INDEX)          if (index < CCS_MAX_CONTROL_INDEX)
970                  r->mode = ccs_check_flags(domain, index);                  r->mode = ccs_check_flags(domain, index);
 #ifdef CONFIG_TOMOYO  
971          else          else
972                  r->mode = ccs_check_capability_flags(domain, index                  r->mode = ccs_check_capability_flags(domain, index
973                                                       - CCS_MAX_CONTROL_INDEX);                                                       - CCS_MAX_CONTROL_INDEX);
 #endif  
974  }  }
975    
976  /**  /**
# Line 991  bool ccs_verbose_mode(const struct ccs_d Line 989  bool ccs_verbose_mode(const struct ccs_d
989  /**  /**
990   * ccs_domain_quota_ok - Check for domain's quota.   * ccs_domain_quota_ok - Check for domain's quota.
991   *   *
992   * @domain: Pointer to "struct ccs_domain_info".   * @r: Pointer to "struct ccs_request_info".
993   *   *
994   * Returns true if the domain is not exceeded quota, false otherwise.   * Returns true if the domain is not exceeded quota, false otherwise.
995     *
996     * Caller holds ccs_read_lock().
997   */   */
998  bool ccs_domain_quota_ok(struct ccs_domain_info * const domain)  bool ccs_domain_quota_ok(struct ccs_request_info *r)
999  {  {
1000          unsigned int count = 0;          unsigned int count = 0;
1001            struct ccs_domain_info *domain = r->domain;
1002          struct ccs_acl_info *ptr;          struct ccs_acl_info *ptr;
1003            ccs_check_read_lock();
1004            if (r->mode != 1)
1005                    return false;
1006          if (!domain)          if (!domain)
1007                  return true;                  return true;
1008          list1_for_each_entry(ptr, &domain->acl_info_list, list) {          list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) {
1009                  if (ptr->type & ACL_DELETED)                  if (ptr->type & ACL_DELETED)
1010                          continue;                          continue;
1011                  switch (ccs_acl_type2(ptr)) {                  switch (ccs_acl_type2(ptr)) {
# Line 1079  bool ccs_domain_quota_ok(struct ccs_doma Line 1083  bool ccs_domain_quota_ok(struct ccs_doma
1083  static struct ccs_profile *ccs_find_or_assign_new_profile(const unsigned int  static struct ccs_profile *ccs_find_or_assign_new_profile(const unsigned int
1084                                                            profile)                                                            profile)
1085  {  {
1086          static DEFINE_MUTEX(lock);          struct ccs_profile *ptr;
1087          struct ccs_profile *ptr = NULL;          struct ccs_profile *entry;
1088          mutex_lock(&lock);          int i;
1089          if (profile < MAX_PROFILES) {          if (profile >= MAX_PROFILES)
1090                  ptr = ccs_profile_ptr[profile];                  return NULL;
1091                  if (ptr)          ptr = ccs_profile_ptr[profile];
1092                          goto ok;          if (ptr)
1093                  ptr = ccs_alloc_element(sizeof(*ptr));                  return ptr;
1094                  if (ptr) {          entry = kzalloc(sizeof(*entry), GFP_KERNEL);
1095                          int i;          mutex_lock(&ccs_policy_lock);
1096                          for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++)          ptr = ccs_profile_ptr[profile];
1097                                  ptr->value[i]          if (!ptr && ccs_memory_ok(entry, sizeof(*entry))) {
1098                                          = ccs_control_array[i].current_value;                  ptr = entry;
1099                          /*                  for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++)
1100                           * Needn't to initialize "ptr->capability_value"                          ptr->value[i] = ccs_control_array[i].current_value;
1101                           * because they are always 0.                  /*
1102                           */                   * Needn't to initialize "ptr->capability_value"
1103                          mb(); /* Avoid out-of-order execution. */                   * because they are always 0.
1104                          ccs_profile_ptr[profile] = ptr;                   */
1105                  }                  mb(); /* Avoid out-of-order execution. */
1106                    ccs_profile_ptr[profile] = ptr;
1107                    entry = NULL;
1108          }          }
1109   ok:          mutex_unlock(&ccs_policy_lock);
1110          mutex_unlock(&lock);          kfree(entry);
1111          return ptr;          return ptr;
1112  }  }
1113    
# Line 1132  static int ccs_write_profile(struct ccs_ Line 1138  static int ccs_write_profile(struct ccs_
1138          if (!cp)          if (!cp)
1139                  return -EINVAL;                  return -EINVAL;
1140          *cp = '\0';          *cp = '\0';
         ccs_update_counter(CCS_UPDATES_COUNTER_PROFILE);  
1141          if (!strcmp(data, "COMMENT")) {          if (!strcmp(data, "COMMENT")) {
1142                  ccs_profile->comment = ccs_save_name(cp + 1);                  const struct ccs_path_info *new_comment
1143                            = ccs_get_name(cp + 1);
1144                    const struct ccs_path_info *old_comment;
1145                    /* Protect reader from ccs_put_name(). */
1146                    /***** CRITICAL SECTION START *****/
1147                    spin_lock(&ccs_profile_comment_lock);
1148                    old_comment = ccs_profile->comment;
1149                    ccs_profile->comment = new_comment;
1150                    spin_unlock(&ccs_profile_comment_lock);
1151                    /***** CRITICAL SECTION END *****/
1152                    ccs_put_name(old_comment);
1153                  ccs_profile_entry_used[0] = true;                  ccs_profile_entry_used[0] = true;
1154                  return 0;                  return 0;
1155          }          }
 #ifdef CONFIG_TOMOYO  
1156          if (ccs_str_starts(&data, KEYWORD_MAC_FOR_CAPABILITY)) {          if (ccs_str_starts(&data, KEYWORD_MAC_FOR_CAPABILITY)) {
1157                  if (sscanf(cp + 1, "%u", &value) != 1) {                  if (sscanf(cp + 1, "%u", &value) != 1) {
1158                          for (i = 0; i < 4; i++) {                          for (i = 0; i < 4; i++) {
# Line 1162  static int ccs_write_profile(struct ccs_ Line 1176  static int ccs_write_profile(struct ccs_
1176                  }                  }
1177                  return -EINVAL;                  return -EINVAL;
1178          }          }
 #endif  
1179          for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++) {          for (i = 0; i < CCS_MAX_CONTROL_INDEX; i++) {
1180                  if (strcmp(data, ccs_control_array[i].keyword))                  if (strcmp(data, ccs_control_array[i].keyword))
1181                          continue;                          continue;
# Line 1189  static int ccs_write_profile(struct ccs_ Line 1202  static int ccs_write_profile(struct ccs_
1202                  } else if (value > ccs_control_array[i].max_value) {                  } else if (value > ccs_control_array[i].max_value) {
1203                          value = ccs_control_array[i].max_value;                          value = ccs_control_array[i].max_value;
1204                  }                  }
                 switch (i) {  
                 case CCS_DENY_CONCEAL_MOUNT:  
                 case CCS_RESTRICT_UNMOUNT:  
                         if (value == 1)  
                                 value = 2; /* learning mode is not supported. */  
                 }  
1205                  ccs_profile->value[i] = value;                  ccs_profile->value[i] = value;
1206                  ccs_profile_entry_used[i + 1] = true;                  ccs_profile_entry_used[i + 1] = true;
1207                  return 0;                  return 0;
# Line 1223  static int ccs_read_profile(struct ccs_i Line 1230  static int ccs_read_profile(struct ccs_i
1230                  head->read_step = step;                  head->read_step = step;
1231                  if (!ccs_profile)                  if (!ccs_profile)
1232                          continue;                          continue;
 #if !defined(CONFIG_SAKURA) || !defined(CONFIG_TOMOYO)  
                 switch (type - 1) {  
 #ifndef CONFIG_SAKURA  
                 case CCS_DENY_CONCEAL_MOUNT:  
                 case CCS_RESTRICT_CHROOT:  
                 case CCS_RESTRICT_MOUNT:  
                 case CCS_RESTRICT_UNMOUNT:  
                 case CCS_RESTRICT_PIVOT_ROOT:  
                 case CCS_RESTRICT_AUTOBIND:  
 #endif  
 #ifndef CONFIG_TOMOYO  
                 case CCS_MAC_FOR_FILE:  
                 case CCS_MAC_FOR_IOCTL:  
                 case CCS_MAC_FOR_ARGV0:  
                 case CCS_MAC_FOR_ENV:  
                 case CCS_MAC_FOR_NETWORK:  
                 case CCS_MAC_FOR_SIGNAL:  
                 case CCS_MAX_ACCEPT_ENTRY:  
                 case CCS_VERBOSE:  
 #endif  
                         continue;  
                 }  
 #endif  
1233                  if (!ccs_profile_entry_used[type])                  if (!ccs_profile_entry_used[type])
1234                          continue;                          continue;
1235                  if (!type) { /* Print profile' comment tag. */                  if (!type) { /* Print profile' comment tag. */
1236                          if (!ccs_io_printf(head, "%u-COMMENT=%s\n",                          bool done;
1237                                             index, ccs_profile->comment ?                          /***** CRITICAL SECTION START *****/
1238                                             ccs_profile->comment->name : ""))                          spin_lock(&ccs_profile_comment_lock);
1239                            done = ccs_io_printf(head, "%u-COMMENT=%s\n",
1240                                                 index, ccs_profile->comment ?
1241                                                 ccs_profile->comment->name : "");
1242                            spin_unlock(&ccs_profile_comment_lock);
1243                            /***** CRITICAL SECTION END *****/
1244                            if (!done)
1245                                  break;                                  break;
1246                          continue;                          continue;
1247                  }                  }
1248                  type--;                  type--;
1249                  if (type >= CCS_MAX_CONTROL_INDEX) {                  if (type >= CCS_MAX_CONTROL_INDEX) {
 #ifdef CONFIG_TOMOYO  
1250                          const int i = type - CCS_MAX_CONTROL_INDEX;                          const int i = type - CCS_MAX_CONTROL_INDEX;
1251                          const u8 value = ccs_profile->capability_value[i];                          const u8 value = ccs_profile->capability_value[i];
1252                          if (!ccs_io_printf(head,                          if (!ccs_io_printf(head,
# Line 1266  static int ccs_read_profile(struct ccs_i Line 1255  static int ccs_read_profile(struct ccs_i
1255                                             ccs_capability_control_keyword[i],                                             ccs_capability_control_keyword[i],
1256                                             ccs_mode_4[value]))                                             ccs_mode_4[value]))
1257                                  break;                                  break;
 #endif  
1258                  } else {                  } else {
1259                          const unsigned int value = ccs_profile->value[type];                          const unsigned int value = ccs_profile->value[type];
1260                          const char **modes = NULL;                          const char **modes = NULL;
# Line 1295  static int ccs_read_profile(struct ccs_i Line 1283  static int ccs_read_profile(struct ccs_i
1283          return 0;          return 0;
1284  }  }
1285    
 /* Structure for policy manager. */  
 struct ccs_policy_manager_entry {  
         struct list1_head list;  
         /* A path to program or a domainname. */  
         const struct ccs_path_info *manager;  
         bool is_domain;  /* True if manager is a domainname. */  
         bool is_deleted; /* True if this entry is deleted. */  
 };  
   
1286  /* The list for "struct ccs_policy_manager_entry". */  /* The list for "struct ccs_policy_manager_entry". */
1287  static LIST1_HEAD(ccs_policy_manager_list);  LIST_HEAD(ccs_policy_manager_list);
1288    
1289  /**  /**
1290   * ccs_update_manager_entry - Add a manager entry.   * ccs_update_manager_entry - Add a manager entry.
# Line 1317  static LIST1_HEAD(ccs_policy_manager_lis Line 1296  static LIST1_HEAD(ccs_policy_manager_lis
1296   */   */
1297  static int ccs_update_manager_entry(const char *manager, const bool is_delete)  static int ccs_update_manager_entry(const char *manager, const bool is_delete)
1298  {  {
1299          struct ccs_policy_manager_entry *new_entry;          struct ccs_policy_manager_entry *entry = NULL;
1300          struct ccs_policy_manager_entry *ptr;          struct ccs_policy_manager_entry *ptr;
         static DEFINE_MUTEX(lock);  
1301          const struct ccs_path_info *saved_manager;          const struct ccs_path_info *saved_manager;
1302          int error = -ENOMEM;          int error = is_delete ? -ENOENT : -ENOMEM;
1303          bool is_domain = false;          bool is_domain = false;
1304          if (ccs_is_domain_def(manager)) {          if (ccs_is_domain_def(manager)) {
1305                  if (!ccs_is_correct_domain(manager, __func__))                  if (!ccs_is_correct_domain(manager))
1306                          return -EINVAL;                          return -EINVAL;
1307                  is_domain = true;                  is_domain = true;
1308          } else {          } else {
1309                  if (!ccs_is_correct_path(manager, 1, -1, -1, __func__))                  if (!ccs_is_correct_path(manager, 1, -1, -1))
1310                          return -EINVAL;                          return -EINVAL;
1311          }          }
1312          saved_manager = ccs_save_name(manager);          saved_manager = ccs_get_name(manager);
1313          if (!saved_manager)          if (!saved_manager)
1314                  return -ENOMEM;                  return -ENOMEM;
1315          mutex_lock(&lock);          if (!is_delete)
1316          list1_for_each_entry(ptr, &ccs_policy_manager_list, list) {                  entry = kzalloc(sizeof(*entry), GFP_KERNEL);
1317            mutex_lock(&ccs_policy_lock);
1318            list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
1319                  if (ptr->manager != saved_manager)                  if (ptr->manager != saved_manager)
1320                          continue;                          continue;
1321                  ptr->is_deleted = is_delete;                  ptr->is_deleted = is_delete;
1322                  error = 0;                  error = 0;
1323                  goto out;                  break;
1324          }          }
1325          if (is_delete) {          if (!is_delete && error && ccs_memory_ok(entry, sizeof(*entry))) {
1326                  error = -ENOENT;                  entry->manager = saved_manager;
1327                  goto out;                  saved_manager = NULL;
1328                    entry->is_domain = is_domain;
1329                    list_add_tail_rcu(&entry->list, &ccs_policy_manager_list);
1330                    entry = NULL;
1331                    error = 0;
1332          }          }
1333          new_entry = ccs_alloc_element(sizeof(*new_entry));          mutex_unlock(&ccs_policy_lock);
1334          if (!new_entry)          ccs_put_name(saved_manager);
1335                  goto out;          kfree(entry);
         new_entry->manager = saved_manager;  
         new_entry->is_domain = is_domain;  
         list1_add_tail_mb(&new_entry->list, &ccs_policy_manager_list);  
         error = 0;  
  out:  
         mutex_unlock(&lock);  
         if (!error)  
                 ccs_update_counter(CCS_UPDATES_COUNTER_MANAGER);  
1336          return error;          return error;
1337  }  }
1338    
# Line 1384  static int ccs_write_manager_policy(stru Line 1360  static int ccs_write_manager_policy(stru
1360   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1361   *   *
1362   * Returns 0.   * Returns 0.
1363     *
1364     * Caller holds ccs_read_lock().
1365   */   */
1366  static int ccs_read_manager_policy(struct ccs_io_buffer *head)  static int ccs_read_manager_policy(struct ccs_io_buffer *head)
1367  {  {
1368          struct list1_head *pos;          struct list_head *pos;
1369            ccs_check_read_lock();
1370          if (head->read_eof)          if (head->read_eof)
1371                  return 0;                  return 0;
1372          list1_for_each_cookie(pos, head->read_var2, &ccs_policy_manager_list) {          list_for_each_cookie(pos, head->read_var2, &ccs_policy_manager_list) {
1373                  struct ccs_policy_manager_entry *ptr;                  struct ccs_policy_manager_entry *ptr;
1374                  ptr = list1_entry(pos, struct ccs_policy_manager_entry, list);                  ptr = list_entry(pos, struct ccs_policy_manager_entry, list);
1375                  if (ptr->is_deleted)                  if (ptr->is_deleted)
1376                          continue;                          continue;
1377                  if (!ccs_io_printf(head, "%s\n", ptr->manager->name))                  if (!ccs_io_printf(head, "%s\n", ptr->manager->name))
# Line 1407  static int ccs_read_manager_policy(struc Line 1386  static int ccs_read_manager_policy(struc
1386   *   *
1387   * Returns true if the current process is permitted to modify policy   * Returns true if the current process is permitted to modify policy
1388   * via /proc/ccs/ interface.   * via /proc/ccs/ interface.
1389     *
1390     * Caller holds ccs_read_lock().
1391   */   */
1392  static bool ccs_is_policy_manager(void)  static bool ccs_is_policy_manager(void)
1393  {  {
# Line 1416  static bool ccs_is_policy_manager(void) Line 1397  static bool ccs_is_policy_manager(void)
1397          const struct ccs_path_info *domainname          const struct ccs_path_info *domainname
1398                  = ccs_current_domain()->domainname;                  = ccs_current_domain()->domainname;
1399          bool found = false;          bool found = false;
1400            ccs_check_read_lock();
1401          if (!ccs_policy_loaded)          if (!ccs_policy_loaded)
1402                  return true;                  return true;
1403          if (task->ccs_flags & CCS_TASK_IS_POLICY_MANAGER)          if (task->ccs_flags & CCS_TASK_IS_POLICY_MANAGER)
1404                  return true;                  return true;
1405          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))          if (!ccs_manage_by_non_root && (current_uid() || current_euid()))
1406                  return false;                  return false;
1407          list1_for_each_entry(ptr, &ccs_policy_manager_list, list) {          list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
1408                  if (!ptr->is_deleted && ptr->is_domain                  if (!ptr->is_deleted && ptr->is_domain
1409                      && !ccs_pathcmp(domainname, ptr->manager)) {                      && !ccs_pathcmp(domainname, ptr->manager)) {
1410                          /* Set manager flag. */                          /* Set manager flag. */
# Line 1433  static bool ccs_is_policy_manager(void) Line 1415  static bool ccs_is_policy_manager(void)
1415          exe = ccs_get_exe();          exe = ccs_get_exe();
1416          if (!exe)          if (!exe)
1417                  return false;                  return false;
1418          list1_for_each_entry(ptr, &ccs_policy_manager_list, list) {          list_for_each_entry_rcu(ptr, &ccs_policy_manager_list, list) {
1419                  if (!ptr->is_deleted && !ptr->is_domain                  if (!ptr->is_deleted && !ptr->is_domain
1420                      && !strcmp(exe, ptr->manager->name)) {                      && !strcmp(exe, ptr->manager->name)) {
1421                          found = true;                          found = true;
# Line 1451  static bool ccs_is_policy_manager(void) Line 1433  static bool ccs_is_policy_manager(void)
1433                          ccs_last_pid = pid;                          ccs_last_pid = pid;
1434                  }                  }
1435          }          }
1436          ccs_free(exe);          kfree(exe);
1437          return found;          return found;
1438  }  }
1439    
 #ifdef CONFIG_TOMOYO  
   
1440  /**  /**
1441   * ccs_find_condition_part - Find condition part from the statement.   * ccs_find_condition_part - Find condition part from the statement.
1442   *   *
# Line 1491  static char *ccs_find_condition_part(cha Line 1471  static char *ccs_find_condition_part(cha
1471   * @data: String to parse.   * @data: String to parse.
1472   *   *
1473   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1474     *
1475     * Caller holds ccs_read_lock().
1476   */   */
1477  static bool ccs_is_select_one(struct ccs_io_buffer *head, const char *data)  static bool ccs_is_select_one(struct ccs_io_buffer *head, const char *data)
1478  {  {
1479          unsigned int pid;          unsigned int pid;
1480          struct ccs_domain_info *domain = NULL;          struct ccs_domain_info *domain = NULL;
1481            ccs_check_read_lock();
1482          if (!strcmp(data, "allow_execute")) {          if (!strcmp(data, "allow_execute")) {
1483                  head->read_execute_only = true;                  head->read_execute_only = true;
1484                  return true;                  return true;
# Line 1525  static bool ccs_is_select_one(struct ccs Line 1508  static bool ccs_is_select_one(struct ccs
1508          if (domain) {          if (domain) {
1509                  struct ccs_domain_info *d;                  struct ccs_domain_info *d;
1510                  head->read_var1 = NULL;                  head->read_var1 = NULL;
1511                  list1_for_each_entry(d, &ccs_domain_list, list) {                  list_for_each_entry_rcu(d, &ccs_domain_list, list) {
1512                          if (d == domain)                          if (d == domain)
1513                                  break;                                  break;
1514                          head->read_var1 = &d->list;                          head->read_var1 = &d->list;
# Line 1552  static int ccs_write_domain_policy(struc Line 1535  static int ccs_write_domain_policy(struc
1535          struct ccs_domain_info *domain = head->write_var1;          struct ccs_domain_info *domain = head->write_var1;
1536          bool is_delete = false;          bool is_delete = false;
1537          bool is_select = false;          bool is_select = false;
         bool is_undelete = false;  
1538          unsigned int profile;          unsigned int profile;
1539          const struct ccs_condition_list *cond = NULL;          struct ccs_condition *cond = NULL;
1540          char *cp;          char *cp;
1541            int error;
1542          if (ccs_str_starts(&data, KEYWORD_DELETE))          if (ccs_str_starts(&data, KEYWORD_DELETE))
1543                  is_delete = true;                  is_delete = true;
1544          else if (ccs_str_starts(&data, KEYWORD_SELECT))          else if (ccs_str_starts(&data, KEYWORD_SELECT))
1545                  is_select = true;                  is_select = true;
         else if (ccs_str_starts(&data, KEYWORD_UNDELETE))  
                 is_undelete = true;  
1546          if (is_select && ccs_is_select_one(head, data))          if (is_select && ccs_is_select_one(head, data))
1547                  return 0;                  return 0;
1548          /* Don't allow updating policies by non manager programs. */          /* Don't allow updating policies by non manager programs. */
# Line 1573  static int ccs_write_domain_policy(struc Line 1554  static int ccs_write_domain_policy(struc
1554                          ccs_delete_domain(data);                          ccs_delete_domain(data);
1555                  else if (is_select)                  else if (is_select)
1556                          domain = ccs_find_domain(data);                          domain = ccs_find_domain(data);
                 else if (is_undelete)  
                         domain = ccs_undelete_domain(data);  
1557                  else                  else
1558                          domain = ccs_find_or_assign_new_domain(data, 0);                          domain = ccs_find_or_assign_new_domain(data, 0);
1559                  head->write_var1 = domain;                  head->write_var1 = domain;
                 ccs_update_counter(CCS_UPDATES_COUNTER_DOMAIN_POLICY);  
1560                  return 0;                  return 0;
1561          }          }
1562          if (!domain)          if (!domain)
# Line 1591  static int ccs_write_domain_policy(struc Line 1569  static int ccs_write_domain_policy(struc
1569                  return 0;                  return 0;
1570          }          }
1571          if (!strcmp(data, KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {          if (!strcmp(data, KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) {
1572                  ccs_set_domain_flag(domain, is_delete,                  domain->ignore_global_allow_read = !is_delete;
                                     DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ);  
1573                  return 0;                  return 0;
1574          }          }
1575          if (!strcmp(data, KEYWORD_IGNORE_GLOBAL_ALLOW_ENV)) {          if (!strcmp(data, KEYWORD_IGNORE_GLOBAL_ALLOW_ENV)) {
1576                  ccs_set_domain_flag(domain, is_delete,                  domain->ignore_global_allow_env = !is_delete;
                                     DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_ENV);  
1577                  return 0;                  return 0;
1578          }          }
1579          cp = ccs_find_condition_part(data);          cp = ccs_find_condition_part(data);
1580          if (cp) {          if (cp) {
1581                  cond = ccs_find_or_assign_new_condition(cp);                  cond = ccs_get_condition(cp);
1582                  if (!cond)                  if (!cond)
1583                          return -EINVAL;                          return -EINVAL;
1584          }          }
1585          if (ccs_str_starts(&data, KEYWORD_ALLOW_CAPABILITY))          if (ccs_str_starts(&data, KEYWORD_ALLOW_CAPABILITY))
1586                  return ccs_write_capability_policy(data, domain, cond,                  error = ccs_write_capability_policy(data, domain, cond,
1587                                                     is_delete);                                                      is_delete);
1588          else if (ccs_str_starts(&data, KEYWORD_ALLOW_NETWORK))          else if (ccs_str_starts(&data, KEYWORD_ALLOW_NETWORK))
1589                  return ccs_write_network_policy(data, domain, cond, is_delete);                  error = ccs_write_network_policy(data, domain, cond, is_delete);
1590          else if (ccs_str_starts(&data, KEYWORD_ALLOW_SIGNAL))          else if (ccs_str_starts(&data, KEYWORD_ALLOW_SIGNAL))
1591                  return ccs_write_signal_policy(data, domain, cond, is_delete);                  error = ccs_write_signal_policy(data, domain, cond, is_delete);
1592          else if (ccs_str_starts(&data, KEYWORD_ALLOW_ARGV0))          else if (ccs_str_starts(&data, KEYWORD_ALLOW_ARGV0))
1593                  return ccs_write_argv0_policy(data, domain, cond, is_delete);                  error = ccs_write_argv0_policy(data, domain, cond, is_delete);
1594          else if (ccs_str_starts(&data, KEYWORD_ALLOW_ENV))          else if (ccs_str_starts(&data, KEYWORD_ALLOW_ENV))
1595                  return ccs_write_env_policy(data, domain, cond, is_delete);                  error = ccs_write_env_policy(data, domain, cond, is_delete);
1596          else if (ccs_str_starts(&data, KEYWORD_ALLOW_IOCTL))          else if (ccs_str_starts(&data, KEYWORD_ALLOW_IOCTL))
1597                  return ccs_write_ioctl_policy(data, domain, cond, is_delete);                  error = ccs_write_ioctl_policy(data, domain, cond, is_delete);
1598            else if (ccs_str_starts(&data, KEYWORD_ALLOW_MOUNT))
1599                    error = ccs_write_mount_policy(data, domain, cond, is_delete);
1600            else if (ccs_str_starts(&data, KEYWORD_ALLOW_UNMOUNT))
1601                    error = ccs_write_umount_policy(data, domain, cond, is_delete);
1602            else if (ccs_str_starts(&data, KEYWORD_ALLOW_CHROOT))
1603                    error = ccs_write_chroot_policy(data, domain, cond, is_delete);
1604            else if (ccs_str_starts(&data, KEYWORD_ALLOW_PIVOT_ROOT))
1605                    error = ccs_write_pivot_root_policy(data, domain, cond,
1606                                                        is_delete);
1607          else          else
1608                  return ccs_write_file_policy(data, domain, cond, is_delete);                  error = ccs_write_file_policy(data, domain, cond, is_delete);
1609            if (cond)
1610                    ccs_put_condition(cond);
1611            return error;
1612  }  }
1613    
1614  /**  /**
# Line 1628  static int ccs_write_domain_policy(struc Line 1616  static int ccs_write_domain_policy(struc
1616   *   *
1617   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1618   * @ptr:  Pointer to "struct ccs_single_path_acl_record".   * @ptr:  Pointer to "struct ccs_single_path_acl_record".
1619   * @cond: Pointer to "struct ccs_condition_list". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1620   *   *
1621   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1622   */   */
1623  static bool ccs_print_single_path_acl(struct ccs_io_buffer *head,  static bool ccs_print_single_path_acl(struct ccs_io_buffer *head,
1624                                        struct ccs_single_path_acl_record *ptr,                                        struct ccs_single_path_acl_record *ptr,
1625                                        const struct ccs_condition_list *cond)                                        const struct ccs_condition *cond)
1626  {  {
1627          int pos;          int pos;
1628          u8 bit;          u8 bit;
# Line 1673  static bool ccs_print_single_path_acl(st Line 1661  static bool ccs_print_single_path_acl(st
1661  }  }
1662    
1663  /**  /**
1664     * ccs_print_mkdev_acl - Print a mkdev ACL entry.
1665     *
1666     * @head: Pointer to "struct ccs_io_buffer".
1667     * @ptr:  Pointer to "struct ccs_mkdev_acl_record".
1668     * @cond: Pointer to "struct ccs_condition". May be NULL.
1669     *
1670     * Returns true on success, false otherwise.
1671     */
1672    static bool ccs_print_mkdev_acl(struct ccs_io_buffer *head,
1673                                    struct ccs_mkdev_acl_record *ptr,
1674                                    const struct ccs_condition *cond)
1675    {
1676            int pos;
1677            u8 bit;
1678            const char *atmark = "";
1679            const char *filename;
1680            const u16 perm = ptr->perm;
1681            if (ptr->u_is_group) {
1682                    atmark = "@";
1683                    filename = ptr->u.group->group_name->name;
1684            } else {
1685                    filename = ptr->u.filename->name;
1686            }
1687            for (bit = head->read_bit; bit < MAX_MKDEV_OPERATION; bit++) {
1688                    const char *msg;
1689                    const unsigned int min_major = ptr->min_major;
1690                    const unsigned int max_major = ptr->max_major;
1691                    const unsigned int min_minor = ptr->min_minor;
1692                    const unsigned int max_minor = ptr->max_minor;
1693                    if (!(perm & (1 << bit)))
1694                            continue;
1695                    msg = ccs_mkdev2keyword(bit);
1696                    pos = head->read_avail;
1697                    if (!ccs_io_printf(head, "allow_%s %s%s %u", msg, atmark,
1698                                       filename, min_major) ||
1699                        (min_major != max_major &&
1700                         !ccs_io_printf(head, "-%u", max_major)) ||
1701                        !ccs_io_printf(head, " %u", min_minor) ||
1702                        (min_minor != max_minor &&
1703                         !ccs_io_printf(head, "-%u", max_minor)) ||
1704                        !ccs_print_condition(head, cond))
1705                            goto out;
1706            }
1707            head->read_bit = 0;
1708            return true;
1709     out:
1710            head->read_bit = bit;
1711            head->read_avail = pos;
1712            return false;
1713    }
1714    
1715    /**
1716   * ccs_print_double_path_acl - Print a double path ACL entry.   * ccs_print_double_path_acl - Print a double path ACL entry.
1717   *   *
1718   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1719   * @ptr:  Pointer to "struct ccs_double_path_acl_record".   * @ptr:  Pointer to "struct ccs_double_path_acl_record".
1720   * @cond: Pointer to "struct ccs_condition_list". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1721   *   *
1722   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1723   */   */
1724  static bool ccs_print_double_path_acl(struct ccs_io_buffer *head,  static bool ccs_print_double_path_acl(struct ccs_io_buffer *head,
1725                                        struct ccs_double_path_acl_record *ptr,                                        struct ccs_double_path_acl_record *ptr,
1726                                        const struct ccs_condition_list *cond)                                        const struct ccs_condition *cond)
1727  {  {
1728          int pos;          int pos;
1729          const char *atmark1 = "";          const char *atmark1 = "";
# Line 1728  static bool ccs_print_double_path_acl(st Line 1768  static bool ccs_print_double_path_acl(st
1768   *   *
1769   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1770   * @ptr:  Pointer to "struct ccs_ioctl_acl_record".   * @ptr:  Pointer to "struct ccs_ioctl_acl_record".
1771   * @cond: Pointer to "struct ccs_condition_list". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1772   *   *
1773   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1774   */   */
1775  static bool ccs_print_ioctl_acl(struct ccs_io_buffer *head,  static bool ccs_print_ioctl_acl(struct ccs_io_buffer *head,
1776                                  struct ccs_ioctl_acl_record *ptr,                                  struct ccs_ioctl_acl_record *ptr,
1777                                  const struct ccs_condition_list *cond)                                  const struct ccs_condition *cond)
1778  {  {
1779          int pos = head->read_avail;          int pos = head->read_avail;
1780          const char *atmark = "";          const char *atmark = "";
# Line 1766  static bool ccs_print_ioctl_acl(struct c Line 1806  static bool ccs_print_ioctl_acl(struct c
1806   *   *
1807   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1808   * @ptr:  Pointer to "struct ccs_argv0_acl_record".   * @ptr:  Pointer to "struct ccs_argv0_acl_record".
1809   * @cond: Pointer to "struct ccs_condition_list". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1810   *   *
1811   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1812   */   */
1813  static bool ccs_print_argv0_acl(struct ccs_io_buffer *head,  static bool ccs_print_argv0_acl(struct ccs_io_buffer *head,
1814                                  struct ccs_argv0_acl_record *ptr,                                  struct ccs_argv0_acl_record *ptr,
1815                                  const struct ccs_condition_list *cond)                                  const struct ccs_condition *cond)
1816  {  {
1817          int pos = head->read_avail;          int pos = head->read_avail;
1818          if (!ccs_io_printf(head, KEYWORD_ALLOW_ARGV0 "%s %s",          if (!ccs_io_printf(head, KEYWORD_ALLOW_ARGV0 "%s %s",
# Line 1791  static bool ccs_print_argv0_acl(struct c Line 1831  static bool ccs_print_argv0_acl(struct c
1831   *   *
1832   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1833   * @ptr:  Pointer to "struct ccs_env_acl_record".   * @ptr:  Pointer to "struct ccs_env_acl_record".
1834   * @cond: Pointer to "struct ccs_condition_list". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1835   *   *
1836   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1837   */   */
1838  static bool ccs_print_env_acl(struct ccs_io_buffer *head,  static bool ccs_print_env_acl(struct ccs_io_buffer *head,
1839                                struct ccs_env_acl_record *ptr,                                struct ccs_env_acl_record *ptr,
1840                                const struct ccs_condition_list *cond)                                const struct ccs_condition *cond)
1841  {  {
1842          int pos = head->read_avail;          int pos = head->read_avail;
1843          if (!ccs_io_printf(head, KEYWORD_ALLOW_ENV "%s", ptr->env->name))          if (!ccs_io_printf(head, KEYWORD_ALLOW_ENV "%s", ptr->env->name))
# Line 1815  static bool ccs_print_env_acl(struct ccs Line 1855  static bool ccs_print_env_acl(struct ccs
1855   *   *
1856   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1857   * @ptr:  Pointer to "struct ccs_capability_acl_record".   * @ptr:  Pointer to "struct ccs_capability_acl_record".
1858   * @cond: Pointer to "struct ccs_condition_list". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1859   *   *
1860   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1861   */   */
1862  static bool ccs_print_capability_acl(struct ccs_io_buffer *head,  static bool ccs_print_capability_acl(struct ccs_io_buffer *head,
1863                                       struct ccs_capability_acl_record *ptr,                                       struct ccs_capability_acl_record *ptr,
1864                                       const struct ccs_condition_list *cond)                                       const struct ccs_condition *cond)
1865  {  {
1866          int pos = head->read_avail;          int pos = head->read_avail;
1867          if (!ccs_io_printf(head, KEYWORD_ALLOW_CAPABILITY "%s",          if (!ccs_io_printf(head, KEYWORD_ALLOW_CAPABILITY "%s",
# Line 1906  static bool ccs_print_port_entry(struct Line 1946  static bool ccs_print_port_entry(struct
1946   *   *
1947   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1948   * @ptr:  Pointer to "struct ccs_ip_network_acl_record".   * @ptr:  Pointer to "struct ccs_ip_network_acl_record".
1949   * @cond: Pointer to "struct ccs_condition_list". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1950   *   *
1951   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1952   */   */
1953  static bool ccs_print_network_acl(struct ccs_io_buffer *head,  static bool ccs_print_network_acl(struct ccs_io_buffer *head,
1954                                    struct ccs_ip_network_acl_record *ptr,                                    struct ccs_ip_network_acl_record *ptr,
1955                                    const struct ccs_condition_list *cond)                                    const struct ccs_condition *cond)
1956  {  {
1957          int pos = head->read_avail;          int pos = head->read_avail;
1958          if (!ccs_io_printf(head, KEYWORD_ALLOW_NETWORK "%s ",          if (!ccs_io_printf(head, KEYWORD_ALLOW_NETWORK "%s ",
# Line 1947  static bool ccs_print_network_acl(struct Line 1987  static bool ccs_print_network_acl(struct
1987   *   *
1988   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
1989   * @ptr:  Pointer to "struct signale_acl_record".   * @ptr:  Pointer to "struct signale_acl_record".
1990   * @cond: Pointer to "struct ccs_condition_list". May be NULL.   * @cond: Pointer to "struct ccs_condition". May be NULL.
1991   *   *
1992   * Returns true on success, false otherwise.   * Returns true on success, false otherwise.
1993   */   */
1994  static bool ccs_print_signal_acl(struct ccs_io_buffer *head,  static bool ccs_print_signal_acl(struct ccs_io_buffer *head,
1995                                   struct ccs_signal_acl_record *ptr,                                   struct ccs_signal_acl_record *ptr,
1996                                   const struct ccs_condition_list *cond)                                   const struct ccs_condition *cond)
1997  {  {
1998          int pos = head->read_avail;          int pos = head->read_avail;
1999          if (!ccs_io_printf(head, KEYWORD_ALLOW_SIGNAL "%u %s",          if (!ccs_io_printf(head, KEYWORD_ALLOW_SIGNAL "%u %s",
# Line 1985  static bool ccs_print_execute_handler_re Line 2025  static bool ccs_print_execute_handler_re
2025  }  }
2026    
2027  /**  /**
2028     * ccs_print_mount_acl - Print a mount ACL entry.
2029     *
2030     * @head: Pointer to "struct ccs_io_buffer".
2031     * @ptr:  Pointer to "struct ccs_mount_acl_record".
2032     * @cond: Pointer to "struct ccs_condition". May be NULL.
2033     *
2034     * Returns true on success, false otherwise.
2035     */
2036    static bool ccs_print_mount_acl(struct ccs_io_buffer *head,
2037                                    struct ccs_mount_acl_record *ptr,
2038                                    const struct ccs_condition *cond)
2039    {
2040            int pos = head->read_avail;
2041            if (!ccs_io_printf(head, KEYWORD_ALLOW_MOUNT "%s %s %s 0x%lX\n",
2042                               ptr->dev_name->name, ptr->dir_name->name,
2043                               ptr->fs_type->name, ptr->flags))
2044                    goto out;
2045            if (!ccs_print_condition(head, cond))
2046                    goto out;
2047            return true;
2048     out:
2049            head->read_avail = pos;
2050            return false;
2051    }
2052    
2053    /**
2054     * ccs_print_umount_acl - Print a mount ACL entry.
2055     *
2056     * @head: Pointer to "struct ccs_io_buffer".
2057     * @ptr:  Pointer to "struct ccs_umount_acl_record".
2058     * @cond: Pointer to "struct ccs_condition". May be NULL.
2059     *
2060     * Returns true on success, false otherwise.
2061     */
2062    static bool ccs_print_umount_acl(struct ccs_io_buffer *head,
2063                                     struct ccs_umount_acl_record *ptr,
2064                                     const struct ccs_condition *cond)
2065    {
2066            int pos = head->read_avail;
2067            if (!ccs_io_printf(head, KEYWORD_ALLOW_UNMOUNT "%s\n",
2068                               ptr->dir->name))
2069                    goto out;
2070            if (!ccs_print_condition(head, cond))
2071                    goto out;
2072            return true;
2073     out:
2074            head->read_avail = pos;
2075            return false;
2076    }
2077    
2078    /**
2079     * ccs_print_chroot_acl - Print a chroot ACL entry.
2080     *
2081     * @head: Pointer to "struct ccs_io_buffer".
2082     * @ptr:  Pointer to "struct ccs_chroot_acl_record".
2083     * @cond: Pointer to "struct ccs_condition". May be NULL.
2084     *
2085     * Returns true on success, false otherwise.
2086     */
2087    static bool ccs_print_chroot_acl(struct ccs_io_buffer *head,
2088                                     struct ccs_chroot_acl_record *ptr,
2089                                     const struct ccs_condition *cond)
2090    {
2091            int pos = head->read_avail;
2092            if (!ccs_io_printf(head, KEYWORD_ALLOW_CHROOT "%s\n",
2093                               ptr->dir->name))
2094                    goto out;
2095            if (!ccs_print_condition(head, cond))
2096                    goto out;
2097            return true;
2098     out:
2099            head->read_avail = pos;
2100            return false;
2101    }
2102    
2103    /**
2104     * ccs_print_pivot_root_acl - Print a pivot_root ACL entry.
2105     *
2106     * @head: Pointer to "struct ccs_io_buffer".
2107     * @ptr:  Pointer to "struct ccs_pivot_root_acl_record".
2108     * @cond: Pointer to "struct ccs_condition". May be NULL.
2109     *
2110     * Returns true on success, false otherwise.
2111     */
2112    static bool ccs_print_pivot_root_acl(struct ccs_io_buffer *head,
2113                                         struct ccs_pivot_root_acl_record *ptr,
2114                                         const struct ccs_condition *cond)
2115    {
2116            int pos = head->read_avail;
2117            if (!ccs_io_printf(head, KEYWORD_ALLOW_PIVOT_ROOT "%s %s\n",
2118                               ptr->new_root->name, ptr->old_root->name))
2119                    goto out;
2120            if (!ccs_print_condition(head, cond))
2121                    goto out;
2122            return true;
2123     out:
2124            head->read_avail = pos;
2125            return false;
2126    }
2127    
2128    /**
2129   * ccs_print_entry - Print an ACL entry.   * ccs_print_entry - Print an ACL entry.
2130   *   *
2131   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
# Line 1995  static bool ccs_print_execute_handler_re Line 2136  static bool ccs_print_execute_handler_re
2136  static bool ccs_print_entry(struct ccs_io_buffer *head,  static bool ccs_print_entry(struct ccs_io_buffer *head,
2137                              struct ccs_acl_info *ptr)                              struct ccs_acl_info *ptr)
2138  {  {
2139          const struct ccs_condition_list *cond = ccs_get_condition_part(ptr);          const struct ccs_condition *cond = ptr->cond;
2140          const u8 acl_type = ccs_acl_type2(ptr);          const u8 acl_type = ccs_acl_type2(ptr);
2141          if (acl_type & ACL_DELETED)          if (acl_type & ACL_DELETED)
2142                  return true;                  return true;
# Line 2021  static bool ccs_print_entry(struct ccs_i Line 2162  static bool ccs_print_entry(struct ccs_i
2162          }          }
2163          if (head->read_execute_only)          if (head->read_execute_only)
2164                  return true;                  return true;
2165            if (acl_type == TYPE_MKDEV_ACL) {
2166                    struct ccs_mkdev_acl_record *acl
2167                            = container_of(ptr, struct ccs_mkdev_acl_record, head);
2168                    return ccs_print_mkdev_acl(head, acl, cond);
2169            }
2170          if (acl_type == TYPE_DOUBLE_PATH_ACL) {          if (acl_type == TYPE_DOUBLE_PATH_ACL) {
2171                  struct ccs_double_path_acl_record *acl                  struct ccs_double_path_acl_record *acl
2172                          = container_of(ptr, struct ccs_double_path_acl_record,                          = container_of(ptr, struct ccs_double_path_acl_record,
# Line 2059  static bool ccs_print_entry(struct ccs_i Line 2205  static bool ccs_print_entry(struct ccs_i
2205                          = container_of(ptr, struct ccs_signal_acl_record, head);                          = container_of(ptr, struct ccs_signal_acl_record, head);
2206                  return ccs_print_signal_acl(head, acl, cond);                  return ccs_print_signal_acl(head, acl, cond);
2207          }          }
2208            if (acl_type == TYPE_MOUNT_ACL) {
2209                    struct ccs_mount_acl_record *acl
2210                            = container_of(ptr, struct ccs_mount_acl_record, head);
2211                    return ccs_print_mount_acl(head, acl, cond);
2212            }
2213            if (acl_type == TYPE_UMOUNT_ACL) {
2214                    struct ccs_umount_acl_record *acl
2215                            = container_of(ptr, struct ccs_umount_acl_record, head);
2216                    return ccs_print_umount_acl(head, acl, cond);
2217            }
2218            if (acl_type == TYPE_CHROOT_ACL) {
2219                    struct ccs_chroot_acl_record *acl
2220                            = container_of(ptr, struct ccs_chroot_acl_record, head);
2221                    return ccs_print_chroot_acl(head, acl, cond);
2222            }
2223            if (acl_type == TYPE_PIVOT_ROOT_ACL) {
2224                    struct ccs_pivot_root_acl_record *acl
2225                            = container_of(ptr, struct ccs_pivot_root_acl_record,
2226                                           head);
2227                    return ccs_print_pivot_root_acl(head, acl, cond);
2228            }
2229          /* Workaround for gcc 3.2.2's inline bug. */          /* Workaround for gcc 3.2.2's inline bug. */
2230          if (acl_type & ACL_DELETED)          if (acl_type & ACL_DELETED)
2231                  return true;                  return true;
# Line 2072  static bool ccs_print_entry(struct ccs_i Line 2239  static bool ccs_print_entry(struct ccs_i
2239   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
2240   *   *
2241   * Returns 0.   * Returns 0.
2242     *
2243     * Caller holds ccs_read_lock().
2244   */   */
2245  static int ccs_read_domain_policy(struct ccs_io_buffer *head)  static int ccs_read_domain_policy(struct ccs_io_buffer *head)
2246  {  {
2247          struct list1_head *dpos;          struct list_head *dpos;
2248          struct list1_head *apos;          struct list_head *apos;
2249            ccs_check_read_lock();
2250          if (head->read_eof)          if (head->read_eof)
2251                  return 0;                  return 0;
2252          if (head->read_step == 0)          if (head->read_step == 0)
2253                  head->read_step = 1;                  head->read_step = 1;
2254          list1_for_each_cookie(dpos, head->read_var1, &ccs_domain_list) {          list_for_each_cookie(dpos, head->read_var1, &ccs_domain_list) {
2255                  struct ccs_domain_info *domain;                  struct ccs_domain_info *domain;
2256                  const char *quota_exceeded = "";                  const char *quota_exceeded = "";
2257                  const char *transition_failed = "";                  const char *transition_failed = "";
2258                  const char *ignore_global_allow_read = "";                  const char *ignore_global_allow_read = "";
2259                  const char *ignore_global_allow_env = "";                  const char *ignore_global_allow_env = "";
2260                  domain = list1_entry(dpos, struct ccs_domain_info, list);                  domain = list_entry(dpos, struct ccs_domain_info, list);
2261                  if (head->read_step != 1)                  if (head->read_step != 1)
2262                          goto acl_loop;                          goto acl_loop;
2263                  if (domain->is_deleted && !head->read_single_domain)                  if (domain->is_deleted && !head->read_single_domain)
# Line 2095  static int ccs_read_domain_policy(struct Line 2265  static int ccs_read_domain_policy(struct
2265                  /* Print domainname and flags. */                  /* Print domainname and flags. */
2266                  if (domain->quota_warned)                  if (domain->quota_warned)
2267                          quota_exceeded = "quota_exceeded\n";                          quota_exceeded = "quota_exceeded\n";
2268                  if (domain->flags & DOMAIN_FLAGS_TRANSITION_FAILED)                  if (domain->domain_transition_failed)
2269                          transition_failed = "transition_failed\n";                          transition_failed = "transition_failed\n";
2270                  if (domain->flags & DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ)                  if (domain->ignore_global_allow_read)
2271                          ignore_global_allow_read                          ignore_global_allow_read
2272                                  = KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";                                  = KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n";
2273                  if (domain->flags & DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_ENV)                  if (domain->ignore_global_allow_env)
2274                          ignore_global_allow_env                          ignore_global_allow_env
2275                                  = KEYWORD_IGNORE_GLOBAL_ALLOW_ENV "\n";                                  = KEYWORD_IGNORE_GLOBAL_ALLOW_ENV "\n";
2276                  if (!ccs_io_printf(head, "%s\n" KEYWORD_USE_PROFILE "%u\n"                  if (!ccs_io_printf(head, "%s\n" KEYWORD_USE_PROFILE "%u\n"
# Line 2115  static int ccs_read_domain_policy(struct Line 2285  static int ccs_read_domain_policy(struct
2285                  if (head->read_step == 3)                  if (head->read_step == 3)
2286                          goto tail_mark;                          goto tail_mark;
2287                  /* Print ACL entries in the domain. */                  /* Print ACL entries in the domain. */
2288                  list1_for_each_cookie(apos, head->read_var2,                  list_for_each_cookie(apos, head->read_var2,
2289                                        &domain->acl_info_list) {                                       &domain->acl_info_list) {
2290                          struct ccs_acl_info *ptr                          struct ccs_acl_info *ptr
2291                                  = list1_entry(apos, struct ccs_acl_info, list);                                  = list_entry(apos, struct ccs_acl_info, list);
2292                          if (!ccs_print_entry(head, ptr))                          if (!ccs_print_entry(head, ptr))
2293                                  return 0;                                  return 0;
2294                  }                  }
# Line 2134  static int ccs_read_domain_policy(struct Line 2304  static int ccs_read_domain_policy(struct
2304          return 0;          return 0;
2305  }  }
2306    
 #endif  
   
2307  /**  /**
2308   * ccs_write_domain_profile - Assign profile for specified domain.   * ccs_write_domain_profile - Assign profile for specified domain.
2309   *   *
# Line 2147  static int ccs_read_domain_policy(struct Line 2315  static int ccs_read_domain_policy(struct
2315   *   *
2316   *     ( echo "select " $domainname; echo "use_profile " $profile ) |   *     ( echo "select " $domainname; echo "use_profile " $profile ) |
2317   *     /usr/lib/ccs/loadpolicy -d   *     /usr/lib/ccs/loadpolicy -d
2318     *
2319     * Caller holds ccs_read_lock().
2320   */   */
2321  static int ccs_write_domain_profile(struct ccs_io_buffer *head)  static int ccs_write_domain_profile(struct ccs_io_buffer *head)
2322  {  {
# Line 2154  static int ccs_write_domain_profile(stru Line 2324  static int ccs_write_domain_profile(stru
2324          char *cp = strchr(data, ' ');          char *cp = strchr(data, ' ');
2325          struct ccs_domain_info *domain;          struct ccs_domain_info *domain;
2326          unsigned int profile;          unsigned int profile;
2327            ccs_check_read_lock();
2328          if (!cp)          if (!cp)
2329                  return -EINVAL;                  return -EINVAL;
2330          *cp = '\0';          *cp = '\0';
         domain = ccs_find_domain(cp + 1);  
2331          profile = simple_strtoul(data, NULL, 10);          profile = simple_strtoul(data, NULL, 10);
2332          if (domain && profile < MAX_PROFILES          if (profile >= MAX_PROFILES)
2333              && (ccs_profile_ptr[profile] || !ccs_policy_loaded))                  return -EINVAL;
2334            domain = ccs_find_domain(cp + 1);
2335            if (domain && (ccs_profile_ptr[profile] || !ccs_policy_loaded))
2336                  domain->profile = (u8) profile;                  domain->profile = (u8) profile;
         ccs_update_counter(CCS_UPDATES_COUNTER_DOMAIN_POLICY);  
2337          return 0;          return 0;
2338  }  }
2339    
# Line 2179  static int ccs_write_domain_profile(stru Line 2350  static int ccs_write_domain_profile(stru
2350   *     awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )   *     awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" )
2351   *     domainname = $0; } else if ( $1 == "use_profile" ) {   *     domainname = $0; } else if ( $1 == "use_profile" ) {
2352   *     print $2 " " domainname; domainname = ""; } } ; '   *     print $2 " " domainname; domainname = ""; } } ; '
2353     *
2354     * Caller holds ccs_read_lock().
2355   */   */
2356  static int ccs_read_domain_profile(struct ccs_io_buffer *head)  static int ccs_read_domain_profile(struct ccs_io_buffer *head)
2357  {  {
2358          struct list1_head *pos;          struct list_head *pos;
2359            ccs_check_read_lock();
2360          if (head->read_eof)          if (head->read_eof)
2361                  return 0;                  return 0;
2362          list1_for_each_cookie(pos, head->read_var1, &ccs_domain_list) {          list_for_each_cookie(pos, head->read_var1, &ccs_domain_list) {
2363                  struct ccs_domain_info *domain;                  struct ccs_domain_info *domain;
2364                  domain = list1_entry(pos, struct ccs_domain_info, list);                  domain = list_entry(pos, struct ccs_domain_info, list);
2365                  if (domain->is_deleted)                  if (domain->is_deleted)
2366                          continue;                          continue;
2367                  if (!ccs_io_printf(head, "%u %s\n", domain->profile,                  if (!ccs_io_printf(head, "%u %s\n", domain->profile,
# Line 2219  static int ccs_write_pid(struct ccs_io_b Line 2393  static int ccs_write_pid(struct ccs_io_b
2393   * Returns the domainname which the specified PID is in or   * Returns the domainname which the specified PID is in or
2394   * process information of the specified PID on success,   * process information of the specified PID on success,
2395   * empty string otherwise.   * empty string otherwise.
2396     *
2397     * Caller holds ccs_read_lock().
2398   */   */
2399  static int ccs_read_pid(struct ccs_io_buffer *head)  static int ccs_read_pid(struct ccs_io_buffer *head)
2400  {  {
# Line 2228  static int ccs_read_pid(struct ccs_io_bu Line 2404  static int ccs_read_pid(struct ccs_io_bu
2404          struct task_struct *p;          struct task_struct *p;
2405          struct ccs_domain_info *domain = NULL;          struct ccs_domain_info *domain = NULL;
2406          u32 ccs_flags = 0;          u32 ccs_flags = 0;
2407            ccs_check_read_lock();
2408          /* Accessing write_buf is safe because head->io_sem is held. */          /* Accessing write_buf is safe because head->io_sem is held. */
2409          if (!buf)          if (!buf)
2410                  goto done; /* Do nothing if open(O_RDONLY). */                  goto done; /* Do nothing if open(O_RDONLY). */
# Line 2265  static int ccs_read_pid(struct ccs_io_bu Line 2442  static int ccs_read_pid(struct ccs_io_bu
2442          return 0;          return 0;
2443  }  }
2444    
 #ifdef CONFIG_TOMOYO  
   
2445  /**  /**
2446   * ccs_write_exception_policy - Write exception policy.   * ccs_write_exception_policy - Write exception policy.
2447   *   *
# Line 2288  static int ccs_write_exception_policy(st Line 2463  static int ccs_write_exception_policy(st
2463          if (ccs_str_starts(&data, KEYWORD_NO_INITIALIZE_DOMAIN))          if (ccs_str_starts(&data, KEYWORD_NO_INITIALIZE_DOMAIN))
2464                  return ccs_write_domain_initializer_policy(data, true,                  return ccs_write_domain_initializer_policy(data, true,
2465                                                             is_delete);                                                             is_delete);
         if (ccs_str_starts(&data, KEYWORD_ALIAS))  
                 return ccs_write_alias_policy(data, is_delete);  
2466          if (ccs_str_starts(&data, KEYWORD_AGGREGATOR))          if (ccs_str_starts(&data, KEYWORD_AGGREGATOR))
2467                  return ccs_write_aggregator_policy(data, is_delete);                  return ccs_write_aggregator_policy(data, is_delete);
2468          if (ccs_str_starts(&data, KEYWORD_ALLOW_READ))          if (ccs_str_starts(&data, KEYWORD_ALLOW_READ))
# Line 2300  static int ccs_write_exception_policy(st Line 2473  static int ccs_write_exception_policy(st
2473                  return ccs_write_pattern_policy(data, is_delete);                  return ccs_write_pattern_policy(data, is_delete);
2474          if (ccs_str_starts(&data, KEYWORD_PATH_GROUP))          if (ccs_str_starts(&data, KEYWORD_PATH_GROUP))
2475                  return ccs_write_path_group_policy(data, is_delete);                  return ccs_write_path_group_policy(data, is_delete);
2476            if (ccs_str_starts(&data, KEYWORD_NUMBER_GROUP))
2477                    return ccs_write_number_group_policy(data, is_delete);
2478          if (ccs_str_starts(&data, KEYWORD_DENY_REWRITE))          if (ccs_str_starts(&data, KEYWORD_DENY_REWRITE))
2479                  return ccs_write_no_rewrite_policy(data, is_delete);                  return ccs_write_no_rewrite_policy(data, is_delete);
2480          if (ccs_str_starts(&data, KEYWORD_ADDRESS_GROUP))          if (ccs_str_starts(&data, KEYWORD_ADDRESS_GROUP))
2481                  return ccs_write_address_group_policy(data, is_delete);                  return ccs_write_address_group_policy(data, is_delete);
2482            if (ccs_str_starts(&data, KEYWORD_DENY_AUTOBIND))
2483                    return ccs_write_reserved_port_policy(data, is_delete);
2484          return -EINVAL;          return -EINVAL;
2485  }  }
2486    
# Line 2313  static int ccs_write_exception_policy(st Line 2490  static int ccs_write_exception_policy(st
2490   * @head: Pointer to "struct ccs_io_buffer".   * @head: Pointer to "struct ccs_io_buffer".
2491   *   *
2492   * Returns 0 on success, -EINVAL otherwise.   * Returns 0 on success, -EINVAL otherwise.
2493     *
2494     * Caller holds ccs_read_lock().
2495   */   */
2496  static int ccs_read_exception_policy(struct ccs_io_buffer *head)  static int ccs_read_exception_policy(struct ccs_io_buffer *head)
2497  {  {
2498            ccs_check_read_lock();
2499          if (!head->read_eof) {          if (!head->read_eof) {
2500                  switch (head->read_step) {                  switch (head->read_step) {
2501                  case 0:                  case 0:
# Line 2340  static int ccs_read_exception_policy(str Line 2520  static int ccs_read_exception_policy(str
2520                          if (!ccs_read_domain_initializer_policy(head))                          if (!ccs_read_domain_initializer_policy(head))
2521                                  break;                                  break;
2522                          head->read_var2 = NULL;                          head->read_var2 = NULL;
                         head->read_step = 5;  
                 case 5:  
                         if (!ccs_read_alias_policy(head))  
                                 break;  
                         head->read_var2 = NULL;  
2523                          head->read_step = 6;                          head->read_step = 6;
2524                  case 6:                  case 6:
2525                          if (!ccs_read_aggregator_policy(head))                          if (!ccs_read_aggregator_policy(head))
# Line 2368  static int ccs_read_exception_policy(str Line 2543  static int ccs_read_exception_policy(str
2543                          head->read_var2 = NULL;                          head->read_var2 = NULL;
2544                          head->read_step = 10;                          head->read_step = 10;
2545                  case 10:                  case 10:
2546                          if (!ccs_read_address_group_policy(head))                          if (!ccs_read_number_group_policy(head))
                                 break;  
                         head->read_eof = true;  
                         break;  
                 default:  
                         return -EINVAL;  
                 }  
         }  
         return 0;  
 }  
   
 #endif  
   
 #ifdef CONFIG_SAKURA  
   
 /**  
  * ccs_write_system_policy - Write system policy.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  *  
  * Returns 0 on success, negative value otherwise.  
  */  
 static int ccs_write_system_policy(struct ccs_io_buffer *head)  
 {  
         char *data = head->write_buf;  
         bool is_delete = false;  
         if (ccs_str_starts(&data, KEYWORD_DELETE))  
                 is_delete = true;  
         if (ccs_str_starts(&data, KEYWORD_ALLOW_MOUNT))  
                 return ccs_write_mount_policy(data, is_delete);  
         if (ccs_str_starts(&data, KEYWORD_DENY_UNMOUNT))  
                 return ccs_write_no_umount_policy(data, is_delete);  
         if (ccs_str_starts(&data, KEYWORD_ALLOW_CHROOT))  
                 return ccs_write_chroot_policy(data, is_delete);  
         if (ccs_str_starts(&data, KEYWORD_ALLOW_PIVOT_ROOT))  
                 return ccs_write_pivot_root_policy(data, is_delete);  
         if (ccs_str_starts(&data, KEYWORD_DENY_AUTOBIND))  
                 return ccs_write_reserved_port_policy(data, is_delete);  
         return -EINVAL;  
 }  
   
 /**  
  * ccs_read_system_policy - Read system policy.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  *  
  * Returns 0 on success, -EINVAL otherwise.  
  */  
 static int ccs_read_system_policy(struct ccs_io_buffer *head)  
 {  
         if (!head->read_eof) {  
                 switch (head->read_step) {  
                 case 0:  
                         head->read_var2 = NULL;  
                         head->read_step = 1;  
                 case 1:  
                         if (!ccs_read_mount_policy(head))  
                                 break;  
                         head->read_var2 = NULL;  
                         head->read_step = 2;  
                 case 2:  
                         if (!ccs_read_no_umount_policy(head))  
                                 break;  
                         head->read_var2 = NULL;  
                         head->read_step = 3;  
                 case 3:  
                         if (!ccs_read_chroot_policy(head))  
2547                                  break;                                  break;
2548                            head->read_var1 = NULL;
2549                          head->read_var2 = NULL;                          head->read_var2 = NULL;
2550                          head->read_step = 4;                          head->read_step = 11;
2551                  case 4:                  case 11:
2552                          if (!ccs_read_pivot_root_policy(head))                          if (!ccs_read_address_group_policy(head))
2553                                  break;                                  break;
2554                          head->read_var2 = NULL;                          head->read_var2 = NULL;
2555                          head->read_step = 5;                          head->read_step = 12;
2556                  case 5:                  case 12:
2557                          if (!ccs_read_reserved_port_policy(head))                          if (!ccs_read_reserved_port_policy(head))
2558                                  break;                                  break;
2559                          head->read_eof = true;                          head->read_eof = true;
# Line 2455  static int ccs_read_system_policy(struct Line 2565  static int ccs_read_system_policy(struct
2565          return 0;          return 0;
2566  }  }
2567    
 #endif  
   
2568  /* Path to the policy loader. The default is /sbin/ccs-init. */  /* Path to the policy loader. The default is /sbin/ccs-init. */
2569  static const char *ccs_loader;  static const char *ccs_loader;
2570    
# Line 2608  void ccs_load_policy(const char *filenam Line 2716  void ccs_load_policy(const char *filenam
2716                  spin_unlock_irq(&task->sigmask_lock);                  spin_unlock_irq(&task->sigmask_lock);
2717          }          }
2718  #endif  #endif
2719  #ifdef CONFIG_SAKURA          printk(KERN_INFO "SAKURA: 1.7.0-pre   2009/07/03\n");
2720          printk(KERN_INFO "SAKURA: 1.6.7-rc   2009/03/18\n");          printk(KERN_INFO "TOMOYO: 1.7.0-pre   2009/07/03\n");
 #endif  
 #ifdef CONFIG_TOMOYO  
         printk(KERN_INFO "TOMOYO: 1.6.7-rc   2009/03/18\n");  
 #endif  
2721          printk(KERN_INFO "Mandatory Access Control activated.\n");          printk(KERN_INFO "Mandatory Access Control activated.\n");
2722          ccs_policy_loaded = true;          ccs_policy_loaded = true;
         ccs_log_level = KERN_WARNING;  
2723          { /* Check all profiles currently assigned to domains are defined. */          { /* Check all profiles currently assigned to domains are defined. */
2724                  struct ccs_domain_info *domain;                  struct ccs_domain_info *domain;
2725                  list1_for_each_entry(domain, &ccs_domain_list, list) {                  list_for_each_entry_rcu(domain, &ccs_domain_list, list) {
2726                          const u8 profile = domain->profile;                          const u8 profile = domain->profile;
2727                          if (ccs_profile_ptr[profile])                          if (ccs_profile_ptr[profile])
2728                                  continue;                                  continue;
# Line 2670  int ccs_check_supervisor(struct ccs_requ Line 2773  int ccs_check_supervisor(struct ccs_requ
2773          int len;          int len;
2774          static unsigned int ccs_serial;          static unsigned int ccs_serial;
2775          struct ccs_query_entry *ccs_query_entry = NULL;          struct ccs_query_entry *ccs_query_entry = NULL;
2776            bool quota_exceeded = false;
2777          char *header;          char *header;
2778          if (!r->domain)          if (!r->domain)
2779                  r->domain = ccs_current_domain();                  r->domain = ccs_current_domain();
# Line 2687  int ccs_check_supervisor(struct ccs_requ Line 2791  int ccs_check_supervisor(struct ccs_requ
2791          va_start(args, fmt);          va_start(args, fmt);
2792          len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32;          len = vsnprintf((char *) &pos, sizeof(pos) - 1, fmt, args) + 32;
2793          va_end(args);          va_end(args);
 #ifdef CONFIG_TOMOYO  
2794          header = ccs_init_audit_log(&len, r);          header = ccs_init_audit_log(&len, r);
 #else  
         header = ccs_alloc(1, true);  
 #endif  
2795          if (!header)          if (!header)
2796                  goto out;                  goto out;
2797          ccs_query_entry = ccs_alloc(sizeof(*ccs_query_entry), true);          ccs_query_entry = kzalloc(sizeof(*ccs_query_entry), GFP_KERNEL);
2798          if (!ccs_query_entry)          if (!ccs_query_entry)
2799                  goto out;                  goto out;
2800          ccs_query_entry->query = ccs_alloc(len, true);          ccs_query_entry->query = kzalloc(len, GFP_KERNEL);
2801          if (!ccs_query_entry->query)          if (!ccs_query_entry->query)
2802                  goto out;                  goto out;
2803          INIT_LIST_HEAD(&ccs_query_entry->list);          INIT_LIST_HEAD(&ccs_query_entry->list);
2804          /***** CRITICAL SECTION START *****/          /***** CRITICAL SECTION START *****/
2805          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2806          ccs_query_entry->serial = ccs_serial++;          if (ccs_quota_for_query && ccs_query_memory_size + len +
2807                sizeof(*ccs_query_entry) >= ccs_quota_for_query) {
2808                    quota_exceeded = true;
2809            } else {
2810                    ccs_query_memory_size += len + sizeof(*ccs_query_entry);
2811                    ccs_query_entry->serial = ccs_serial++;
2812            }
2813          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
2814          /***** CRITICAL SECTION END *****/          /***** CRITICAL SECTION END *****/
2815            if (quota_exceeded)
2816                    goto out;
2817          pos = snprintf(ccs_query_entry->query, len - 1, "Q%u-%hu\n%s",          pos = snprintf(ccs_query_entry->query, len - 1, "Q%u-%hu\n%s",
2818                         ccs_query_entry->serial, r->retry, header);                         ccs_query_entry->serial, r->retry, header);
2819          ccs_free(header);          kfree(header);
2820          header = NULL;          header = NULL;
2821          va_start(args, fmt);          va_start(args, fmt);
2822          vsnprintf(ccs_query_entry->query + pos, len - 1 - pos, fmt, args);          vsnprintf(ccs_query_entry->query + pos, len - 1 - pos, fmt, args);
# Line 2719  int ccs_check_supervisor(struct ccs_requ Line 2827  int ccs_check_supervisor(struct ccs_requ
2827          list_add_tail(&ccs_query_entry->list, &ccs_query_list);          list_add_tail(&ccs_query_entry->list, &ccs_query_list);
2828          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
2829          /***** CRITICAL SECTION END *****/          /***** CRITICAL SECTION END *****/
         ccs_update_counter(CCS_UPDATES_COUNTER_QUERY);  
2830          /* Give 10 seconds for supervisor's opinion. */          /* Give 10 seconds for supervisor's opinion. */
2831          for (ccs_query_entry->timer = 0;          for (ccs_query_entry->timer = 0;
2832               atomic_read(&ccs_query_observers) && ccs_query_entry->timer < 100;               atomic_read(&ccs_query_observers) && ccs_query_entry->timer < 100;
# Line 2730  int ccs_check_supervisor(struct ccs_requ Line 2837  int ccs_check_supervisor(struct ccs_requ
2837                  if (ccs_query_entry->answer)                  if (ccs_query_entry->answer)
2838                          break;                          break;
2839          }          }
         ccs_update_counter(CCS_UPDATES_COUNTER_QUERY);  
2840          /***** CRITICAL SECTION START *****/          /***** CRITICAL SECTION START *****/
2841          spin_lock(&ccs_query_list_lock);          spin_lock(&ccs_query_list_lock);
2842          list_del(&ccs_query_entry->list);          list_del(&ccs_query_entry->list);
2843            ccs_query_memory_size -= len + sizeof(*ccs_query_entry);
2844          spin_unlock(&ccs_query_list_lock);          spin_unlock(&ccs_query_list_lock);
2845          /***** CRITICAL SECTION END *****/          /***** CRITICAL SECTION END *****/
2846          switch (ccs_query_entry->answer) {          switch (ccs_query_entry->answer) {
# Line 2754  int ccs_check_supervisor(struct ccs_requ Line 2861  int ccs_check_supervisor(struct ccs_requ
2861          }          }
2862   out:   out:
2863          if (ccs_query_entry)          if (ccs_query_entry)
2864                  ccs_free(ccs_query_entry->query);                  kfree(ccs_query_entry->query);
2865          ccs_free(ccs_query_entry);          kfree(ccs_query_entry);
2866          ccs_free(header);          kfree(header);
2867          return error;          return error;
2868  }  }
2869    
# Line 2813  static int ccs_read_query(struct ccs_io_ Line 2920  static int ccs_read_query(struct ccs_io_
2920          if (head->read_avail)          if (head->read_avail)
2921                  return 0;                  return 0;
2922          if (head->read_buf) {          if (head->read_buf) {
2923                  ccs_free(head->read_buf);                  kfree(head->read_buf);
2924                  head->read_buf = NULL;                  head->read_buf = NULL;
2925                  head->readbuf_size = 0;                  head->readbuf_size = 0;
2926          }          }
# Line 2835  static int ccs_read_query(struct ccs_io_ Line 2942  static int ccs_read_query(struct ccs_io_
2942                  head->read_step = 0;                  head->read_step = 0;
2943                  return 0;                  return 0;
2944          }          }
2945          buf = ccs_alloc(len, false);          buf = kzalloc(len, GFP_KERNEL);
2946          if (!buf)          if (!buf)
2947                  return 0;                  return 0;
2948          pos = 0;          pos = 0;
# Line 2864  static int ccs_read_query(struct ccs_io_ Line 2971  static int ccs_read_query(struct ccs_io_
2971                  head->read_buf = buf;                  head->read_buf = buf;
2972                  head->read_step++;                  head->read_step++;
2973          } else {          } else {
2974                  ccs_free(buf);                  kfree(buf);
2975          }          }
2976          return 0;          return 0;
2977  }  }
# Line 2909  static int ccs_write_answer(struct ccs_i Line 3016  static int ccs_write_answer(struct ccs_i
3016          return 0;          return 0;
3017  }  }
3018    
 #if !defined(atomic_xchg) || LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 3)  
   
 /* Policy updates counter. */  
 static unsigned int ccs_updates_counter[MAX_CCS_UPDATES_COUNTER];  
   
 /* Policy updates counter lock. */  
 static DEFINE_SPINLOCK(ccs_updates_counter_lock);  
   
 /**  
  * ccs_update_counter - Increment policy change counter.  
  *  
  * @index: Type of policy.  
  *  
  * Returns nothing.  
  */  
 void ccs_update_counter(const unsigned char index)  
 {  
         /***** CRITICAL SECTION START *****/  
         spin_lock(&ccs_updates_counter_lock);  
         if (index < MAX_CCS_UPDATES_COUNTER)  
                 ccs_updates_counter[index]++;  
         spin_unlock(&ccs_updates_counter_lock);  
         /***** CRITICAL SECTION END *****/  
 }  
   
 /**  
  * ccs_read_updates_counter - Check for policy change counter.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  *  
  * Returns how many times policy has changed since the previous check.  
  */  
 static int ccs_read_updates_counter(struct ccs_io_buffer *head)  
 {  
         unsigned int counter[MAX_CCS_UPDATES_COUNTER];  
         if (head->read_eof)  
                 return 0;  
         /***** CRITICAL SECTION START *****/  
         spin_lock(&ccs_updates_counter_lock);  
         memmove(counter, ccs_updates_counter, sizeof(ccs_updates_counter));  
         memset(ccs_updates_counter, 0, sizeof(ccs_updates_counter));  
         spin_unlock(&ccs_updates_counter_lock);  
         /***** CRITICAL SECTION END *****/  
         ccs_io_printf(head,  
                       "/proc/ccs/system_policy:    %10u\n"  
                       "/proc/ccs/domain_policy:    %10u\n"  
                       "/proc/ccs/exception_policy: %10u\n"  
                       "/proc/ccs/profile:          %10u\n"  
                       "/proc/ccs/query:            %10u\n"  
                       "/proc/ccs/manager:          %10u\n"  
 #ifdef CONFIG_TOMOYO_AUDIT  
                       "/proc/ccs/grant_log:        %10u\n"  
                       "/proc/ccs/reject_log:       %10u\n"  
 #endif  
                       , counter[CCS_UPDATES_COUNTER_SYSTEM_POLICY]  
                       , counter[CCS_UPDATES_COUNTER_DOMAIN_POLICY]  
                       , counter[CCS_UPDATES_COUNTER_EXCEPTION_POLICY]  
                       , counter[CCS_UPDATES_COUNTER_PROFILE]  
                       , counter[CCS_UPDATES_COUNTER_QUERY]  
                       , counter[CCS_UPDATES_COUNTER_MANAGER]  
 #ifdef CONFIG_TOMOYO_AUDIT  
                       , counter[CCS_UPDATES_COUNTER_GRANT_LOG]  
                       , counter[CCS_UPDATES_COUNTER_REJECT_LOG]  
 #endif  
                       );  
         head->read_eof = true;  
         return 0;  
 }  
   
 #else  
   
 /* Policy updates counter. */  
 static atomic_t ccs_updates_counter[MAX_CCS_UPDATES_COUNTER];  
   
 /**  
  * ccs_update_counter - Increment policy change counter.  
  *  
  * @index: Type of policy.  
  *  
  * Returns nothing.  
  */  
 void ccs_update_counter(const unsigned char index)  
 {  
         if (index < MAX_CCS_UPDATES_COUNTER)  
                 atomic_inc(&ccs_updates_counter[index]);  
 }  
   
 /**  
  * ccs_read_updates_counter - Check for policy change counter.  
  *  
  * @head: Pointer to "struct ccs_io_buffer".  
  *  
  * Returns how many times policy has changed since the previous check.  
  */  
 static int ccs_read_updates_counter(struct ccs_io_buffer *head)  
 {  
         if (head->read_eof)  
                 return 0;  
         ccs_io_printf(head,  
                       "/proc/ccs/system_policy:    %10u\n"  
                       "/proc/ccs/domain_policy:    %10u\n"  
                       "/proc/ccs/exception_policy: %10u\n"  
                       "/proc/ccs/profile:          %10u\n"  
                       "/proc/ccs/query:            %10u\n"  
                       "/proc/ccs/manager:          %10u\n"  
 #ifdef CONFIG_TOMOYO_AUDIT  
                       "/proc/ccs/grant_log:        %10u\n"  
                       "/proc/ccs/reject_log:       %10u\n"  
 #endif  
                       , atomic_xchg(&ccs_updates_counter  
                                     [CCS_UPDATES_COUNTER_SYSTEM_POLICY], 0)  
                       , atomic_xchg(&ccs_updates_counter  
                                     [CCS_UPDATES_COUNTER_DOMAIN_POLICY], 0)  
                       , atomic_xchg(&ccs_updates_counter  
                                     [CCS_UPDATES_COUNTER_EXCEPTION_POLICY], 0)  
                       , atomic_xchg(&ccs_updates_counter  
                                     [CCS_UPDATES_COUNTER_PROFILE], 0)  
                       , atomic_xchg(&ccs_updates_counter  
                                     [CCS_UPDATES_COUNTER_QUERY], 0)  
                       , atomic_xchg(&ccs_updates_counter  
                                     [CCS_UPDATES_COUNTER_MANAGER], 0)  
 #ifdef CONFIG_TOMOYO_AUDIT  
                       , atomic_xchg(&ccs_updates_counter  
                                     [CCS_UPDATES_COUNTER_GRANT_LOG], 0)  
                       , atomic_xchg(&ccs_updates_counter  
                                     [CCS_UPDATES_COUNTER_REJECT_LOG], 0)  
 #endif  
                       );  
         head->read_eof = true;  
         return 0;  
 }  
   
 #endif  
   
3019  /**  /**
3020   * ccs_read_version: Get version.   * ccs_read_version: Get version.
3021   *   *
# Line 3053  static int ccs_read_updates_counter(stru Line 3026  static int ccs_read_updates_counter(stru
3026  static int ccs_read_version(struct ccs_io_buffer *head)  static int ccs_read_version(struct ccs_io_buffer *head)
3027  {  {
3028          if (!head->read_eof) {          if (!head->read_eof) {
3029                  ccs_io_printf(head, "1.6.7-rc");                  ccs_io_printf(head, "1.7.0-pre");
3030                  head->read_eof = true;                  head->read_eof = true;
3031          }          }
3032          return 0;          return 0;
# Line 3091  static int ccs_read_self_domain(struct c Line 3064  static int ccs_read_self_domain(struct c
3064   */   */
3065  int ccs_open_control(const u8 type, struct file *file)  int ccs_open_control(const u8 type, struct file *file)
3066  {  {
3067          struct ccs_io_buffer *head = ccs_alloc(sizeof(*head), false);          struct ccs_io_buffer *head = kzalloc(sizeof(*head), GFP_KERNEL);
3068          if (!head)          if (!head)
3069                  return -ENOMEM;                  return -ENOMEM;
3070          mutex_init(&head->io_sem);          mutex_init(&head->io_sem);
3071            head->type = type;
3072          switch (type) {          switch (type) {
 #ifdef CONFIG_SAKURA  
         case CCS_SYSTEMPOLICY: /* /proc/ccs/system_policy */  
                 head->write = ccs_write_system_policy;  
                 head->read = ccs_read_system_policy;  
                 break;  
 #endif  
 #ifdef CONFIG_TOMOYO  
3073          case CCS_DOMAINPOLICY: /* /proc/ccs/domain_policy */          case CCS_DOMAINPOLICY: /* /proc/ccs/domain_policy */
3074                  head->write = ccs_write_domain_policy;                  head->write = ccs_write_domain_policy;
3075                  head->read = ccs_read_domain_policy;                  head->read = ccs_read_domain_policy;
# Line 3111  int ccs_open_control(const u8 type, stru Line 3078  int ccs_open_control(const u8 type, stru
3078                  head->write = ccs_write_exception_policy;                  head->write = ccs_write_exception_policy;
3079                  head->read = ccs_read_exception_policy;                  head->read = ccs_read_exception_policy;
3080                  break;                  break;
3081  #ifdef CONFIG_TOMOYO_AUDIT  #ifdef CONFIG_CCSECURITY_AUDIT
3082          case CCS_GRANTLOG: /* /proc/ccs/grant_log */          case CCS_GRANTLOG: /* /proc/ccs/grant_log */
3083                  head->poll = ccs_poll_grant_log;                  head->poll = ccs_poll_grant_log;
3084                  head->read = ccs_read_grant_log;                  head->read = ccs_read_grant_log;
# Line 3121  int ccs_open_control(const u8 type, stru Line 3088  int ccs_open_control(const u8 type, stru
3088                  head->read = ccs_read_reject_log;                  head->read = ccs_read_reject_log;
3089                  break;                  break;
3090  #endif  #endif
 #endif  
3091          case CCS_SELFDOMAIN: /* /proc/ccs/self_domain */          case CCS_SELFDOMAIN: /* /proc/ccs/self_domain */
3092                  head->read = ccs_read_self_domain;                  head->read = ccs_read_self_domain;
3093                  break;                  break;
# Line 3132  int ccs_open_control(const u8 type, stru Line 3098  int ccs_open_control(const u8 type, stru
3098          case CCS_EXECUTE_HANDLER: /* /proc/ccs/.execute_handler */          case CCS_EXECUTE_HANDLER: /* /proc/ccs/.execute_handler */
3099                  /* Allow execute_handler to read process's status. */                  /* Allow execute_handler to read process's status. */
3100                  if (!(current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)) {                  if (!(current->ccs_flags & CCS_TASK_IS_EXECUTE_HANDLER)) {
3101                          ccs_free(head);                          kfree(head);
3102                          return -EPERM;                          return -EPERM;
3103                  }                  }
3104                  /* fall through */                  /* fall through */
# Line 3162  int ccs_open_control(const u8 type, stru Line 3128  int ccs_open_control(const u8 type, stru
3128                  head->write = ccs_write_manager_policy;                  head->write = ccs_write_manager_policy;
3129                  head->read = ccs_read_manager_policy;                  head->read = ccs_read_manager_policy;
3130                  break;                  break;
         case CCS_UPDATESCOUNTER: /* /proc/ccs/.ccs_updates_counter */  
                 head->read = ccs_read_updates_counter;  
                 break;  
3131          }          }
3132          if (!(file->f_mode & FMODE_READ)) {          if (!(file->f_mode & FMODE_READ)) {
3133                  /*                  /*
# Line 3173  int ccs_open_control(const u8 type, stru Line 3136  int ccs_open_control(const u8 type, stru
3136                   */                   */
3137                  head->read = NULL;                  head->read = NULL;
3138                  head->poll = NULL;                  head->poll = NULL;
3139          } else if (type != CCS_QUERY          } else if (type != CCS_QUERY &&
3140  #ifdef CONFIG_TOMOYO_AUDIT                     type != CCS_GRANTLOG && type != CCS_REJECTLOG) {
                    && type != CCS_GRANTLOG && type != CCS_REJECTLOG  
 #endif  
                    ) {  
3141                  /*                  /*
3142                   * Don't allocate buffer for reading if the file is one of                   * Don't allocate buffer for reading if the file is one of
3143                   * /proc/ccs/grant_log , /proc/ccs/reject_log , /proc/ccs/query.                   * /proc/ccs/grant_log , /proc/ccs/reject_log , /proc/ccs/query.
3144                   */                   */
3145                  if (!head->readbuf_size)                  if (!head->readbuf_size)
3146                          head->readbuf_size = 4096 * 2;                          head->readbuf_size = 4096 * 2;
3147                  head->read_buf = ccs_alloc(head->readbuf_size, false);                  head->read_buf = kzalloc(head->readbuf_size, GFP_KERNEL);
3148                  if (!head->read_buf) {                  if (!head->read_buf) {
3149                          ccs_free(head);                          kfree(head);
3150                          return -ENOMEM;                          return -ENOMEM;
3151                  }                  }
3152          }          }
# Line 3198  int ccs_open_control(const u8 type, stru Line 3158  int ccs_open_control(const u8 type, stru
3158                  head->write = NULL;                  head->write = NULL;
3159          } else if (head->write) {          } else if (head->write) {
3160                  head->writebuf_size = 4096 * 2;                  head->writebuf_size = 4096 * 2;
3161                  head->write_buf = ccs_alloc(head->writebuf_size, false);                  head->write_buf = kzalloc(head->writebuf_size, GFP_KERNEL);
3162                  if (!head->write_buf) {                  if (!head->write_buf) {
3163                          ccs_free(head->read_buf);                          kfree(head->read_buf);
3164                          ccs_free(head);                          kfree(head);
3165                          return -ENOMEM;                          return -ENOMEM;
3166                  }                  }
3167          }          }
3168            if (type != CCS_QUERY &&
3169                type != CCS_GRANTLOG && type != CCS_REJECTLOG)
3170                    head->reader_idx = ccs_read_lock();
3171          file->private_data = head;          file->private_data = head;
3172          /*          /*
3173           * Call the handler now if the file is /proc/ccs/self_domain           * Call the handler now if the file is /proc/ccs/self_domain
# Line 3218  int ccs_open_control(const u8 type, stru Line 3181  int ccs_open_control(const u8 type, stru
3181           * The obserber counter is used by ccs_check_supervisor() to see if           * The obserber counter is used by ccs_check_supervisor() to see if
3182           * there is some process monitoring /proc/ccs/query.           * there is some process monitoring /proc/ccs/query.
3183           */           */
3184          else if (head->write == ccs_write_answer ||          else if (type == CCS_QUERY)
                  head->read == ccs_read_query)  
3185                  atomic_inc(&ccs_query_observers);                  atomic_inc(&ccs_query_observers);
3186          return 0;          return 0;
3187  }  }
# Line 3309  int ccs_write_control(struct file *file, Line 3271  int ccs_write_control(struct file *file,
3271                  return -EFAULT;                  return -EFAULT;
3272          /* Don't allow updating policies by non manager programs. */          /* Don't allow updating policies by non manager programs. */
3273          if (head->write != ccs_write_pid &&          if (head->write != ccs_write_pid &&
 #ifdef CONFIG_TOMOYO  
3274              head->write != ccs_write_domain_policy &&              head->write != ccs_write_domain_policy &&
 #endif  
3275              !ccs_is_policy_manager())              !ccs_is_policy_manager())
3276                  return -EPERM;                  return -EPERM;
3277          if (mutex_lock_interruptible(&head->io_sem))          if (mutex_lock_interruptible(&head->io_sem))
# Line 3350  int ccs_write_control(struct file *file, Line 3310  int ccs_write_control(struct file *file,
3310  int ccs_close_control(struct file *file)  int ccs_close_control(struct file *file)
3311  {  {
3312          struct ccs_io_buffer *head = file->private_data;          struct ccs_io_buffer *head = file->private_data;
3313            const bool is_write = head->write_buf != NULL;
3314            const u8 type = head->type;
3315          /*          /*
3316           * If the file is /proc/ccs/query , decrement the observer counter.           * If the file is /proc/ccs/query , decrement the observer counter.
3317           */           */
3318          if (head->write == ccs_write_answer || head->read == ccs_read_query)          if (type == CCS_QUERY)
3319                  atomic_dec(&ccs_query_observers);                  atomic_dec(&ccs_query_observers);
3320            if (type != CCS_QUERY &&
3321                type != CCS_GRANTLOG && type != CCS_REJECTLOG)
3322                    ccs_read_unlock(head->reader_idx);
3323          /* Release memory used for policy I/O. */          /* Release memory used for policy I/O. */
3324          ccs_free(head->read_buf);          kfree(head->read_buf);
3325          head->read_buf = NULL;          head->read_buf = NULL;
3326          ccs_free(head->write_buf);          kfree(head->write_buf);
3327          head->write_buf = NULL;          head->write_buf = NULL;
3328          ccs_free(head);          kfree(head);
3329          head = NULL;          head = NULL;
3330          file->private_data = NULL;          file->private_data = NULL;
3331            if (is_write)
3332                    ccs_run_gc();
3333          return 0;          return 0;
3334  }  }
   
 /**  
  * ccs_alloc_acl_element - Allocate permanent memory for ACL entry.  
  *  
  * @acl_type:  Type of ACL entry.  
  * @condition: Pointer to condition part of the ACL entry. May be NULL.  
  *  
  * Returns pointer to the ACL entry on success, NULL otherwise.  
  */  
 void *ccs_alloc_acl_element(const u8 acl_type,  
                             const struct ccs_condition_list *condition)  
 {  
         int len;  
         struct ccs_acl_info *ptr;  
         switch (acl_type) {  
         case TYPE_SINGLE_PATH_ACL:  
                 len = sizeof(struct ccs_single_path_acl_record);  
                 break;  
         case TYPE_DOUBLE_PATH_ACL:  
                 len = sizeof(struct ccs_double_path_acl_record);  
                 break;  
         case TYPE_IOCTL_ACL:  
                 len = sizeof(struct ccs_ioctl_acl_record);  
                 break;  
         case TYPE_ARGV0_ACL:  
                 len = sizeof(struct ccs_argv0_acl_record);  
                 break;  
         case TYPE_ENV_ACL:  
                 len = sizeof(struct ccs_env_acl_record);  
                 break;  
         case TYPE_CAPABILITY_ACL:  
                 len = sizeof(struct ccs_capability_acl_record);  
                 break;  
         case TYPE_IP_NETWORK_ACL:  
                 len = sizeof(struct ccs_ip_network_acl_record);  
                 break;  
         case TYPE_SIGNAL_ACL:  
                 len = sizeof(struct ccs_signal_acl_record);  
                 break;  
         case TYPE_EXECUTE_HANDLER:  
         case TYPE_DENIED_EXECUTE_HANDLER:  
                 len = sizeof(struct ccs_execute_handler_record);  
                 break;  
         default:  
                 return NULL;  
         }  
         /*  
          * If the ACL doesn't have condition part, reduce memory usage  
          * by eliminating sizeof(struct ccs_condition_list *).  
          */  
         if (!condition)  
                 len -= sizeof(ptr->access_me_via_ccs_get_condition_part);  
         ptr = ccs_alloc_element(len);  
         if (!ptr)  
                 return NULL;  
         if (condition) {  
                 ptr->access_me_via_ccs_get_condition_part = condition;  
                 ptr->type = acl_type | ACL_WITH_CONDITION;  
                 return ptr;  
         }  
         /*  
          * Substract sizeof(struct ccs_condition_list *) because I eliminated  
          * sizeof(struct ccs_condition_list *) from "struct ccs_acl_info"  
          * but I must return the start address of "struct ccs_acl_info".  
          */  
         ptr = (void *) (((u8 *) ptr)  
                         - sizeof(ptr->access_me_via_ccs_get_condition_part));  
         ptr->type = acl_type;  
         return ptr;  
 }  

Legend:
Removed from v.2303  
changed lines
  Added in v.2854

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